next 15.2.1-canary.0 → 15.2.1-canary.2
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.
Potentially problematic release.
This version of next might be problematic. Click here for more details.
- package/dist/bin/next +1 -1
- package/dist/build/handle-externals.d.ts +2 -3
- package/dist/build/handle-externals.js +4 -4
- package/dist/build/handle-externals.js.map +1 -1
- package/dist/build/index.js +2 -2
- package/dist/build/swc/index.js +1 -1
- package/dist/build/swc/options.d.ts +1 -0
- package/dist/build/swc/options.js +1 -0
- package/dist/build/swc/options.js.map +1 -1
- package/dist/build/webpack/plugins/build-manifest-plugin.js +3 -5
- package/dist/build/webpack/plugins/build-manifest-plugin.js.map +1 -1
- package/dist/build/webpack/plugins/css-minimizer-plugin.js +2 -2
- package/dist/build/webpack/plugins/css-minimizer-plugin.js.map +1 -1
- package/dist/build/webpack/plugins/minify-webpack-plugin/src/index.js +2 -2
- package/dist/build/webpack/plugins/minify-webpack-plugin/src/index.js.map +1 -1
- package/dist/build/webpack/plugins/next-trace-entrypoints-plugin.d.ts +1 -3
- package/dist/build/webpack/plugins/next-trace-entrypoints-plugin.js +5 -6
- package/dist/build/webpack/plugins/next-trace-entrypoints-plugin.js.map +1 -1
- package/dist/build/webpack/utils.d.ts +3 -1
- package/dist/build/webpack/utils.js +10 -0
- package/dist/build/webpack/utils.js.map +1 -1
- package/dist/build/webpack-config.js +2 -4
- package/dist/build/webpack-config.js.map +1 -1
- package/dist/client/app-bootstrap.js +1 -1
- package/dist/client/components/react-dev-overlay/server/shared.d.ts +0 -3
- package/dist/client/components/react-dev-overlay/server/shared.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/errors/dialog/dialog.d.ts +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/errors/dialog/dialog.js +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/errors/dialog/dialog.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/errors/error-overlay-bottom-stack/index.d.ts +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/errors/error-overlay-bottom-stack/index.js +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/errors/error-overlay-bottom-stack/index.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/errors/error-overlay-layout/error-overlay-layout.d.ts +1 -1
- package/dist/client/components/react-dev-overlay/ui/dev-overlay.js +2 -0
- package/dist/client/components/react-dev-overlay/ui/dev-overlay.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/storybook/with-shadow-portal.js +2 -0
- package/dist/client/components/react-dev-overlay/ui/storybook/with-shadow-portal.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/styles/base.js +2 -14
- package/dist/client/components/react-dev-overlay/ui/styles/base.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/styles/colors.js +2 -22
- package/dist/client/components/react-dev-overlay/ui/styles/colors.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/styles/dark-theme.d.ts +1 -0
- package/dist/client/components/react-dev-overlay/ui/styles/dark-theme.js +41 -0
- package/dist/client/components/react-dev-overlay/ui/styles/dark-theme.js.map +1 -0
- package/dist/client/components/react-dev-overlay/utils/stack-frame.d.ts +11 -3
- package/dist/client/components/react-dev-overlay/utils/stack-frame.js +2 -5
- package/dist/client/components/react-dev-overlay/utils/stack-frame.js.map +1 -1
- package/dist/client/components/router-reducer/reducers/navigate-reducer.js +29 -9
- package/dist/client/components/router-reducer/reducers/navigate-reducer.js.map +1 -1
- package/dist/client/components/segment-cache/navigation.d.ts +5 -1
- package/dist/client/components/segment-cache/navigation.js +28 -19
- package/dist/client/components/segment-cache/navigation.js.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/compiled/next-server/app-page-experimental.runtime.dev.js +3 -3
- package/dist/compiled/next-server/app-page-experimental.runtime.dev.js.map +1 -1
- package/dist/compiled/next-server/app-page.runtime.dev.js +3 -3
- package/dist/compiled/next-server/app-page.runtime.dev.js.map +1 -1
- package/dist/esm/build/handle-externals.js +4 -4
- package/dist/esm/build/handle-externals.js.map +1 -1
- package/dist/esm/build/index.js +2 -2
- package/dist/esm/build/swc/index.js +1 -1
- package/dist/esm/build/swc/options.js +1 -0
- package/dist/esm/build/swc/options.js.map +1 -1
- package/dist/esm/build/webpack/plugins/build-manifest-plugin.js +3 -5
- package/dist/esm/build/webpack/plugins/build-manifest-plugin.js.map +1 -1
- package/dist/esm/build/webpack/plugins/css-minimizer-plugin.js +2 -2
- package/dist/esm/build/webpack/plugins/css-minimizer-plugin.js.map +1 -1
- package/dist/esm/build/webpack/plugins/minify-webpack-plugin/src/index.js +2 -2
- package/dist/esm/build/webpack/plugins/minify-webpack-plugin/src/index.js.map +1 -1
- package/dist/esm/build/webpack/plugins/next-trace-entrypoints-plugin.js +5 -6
- package/dist/esm/build/webpack/plugins/next-trace-entrypoints-plugin.js.map +1 -1
- package/dist/esm/build/webpack/utils.js +6 -0
- package/dist/esm/build/webpack/utils.js.map +1 -1
- package/dist/esm/build/webpack-config.js +2 -4
- package/dist/esm/build/webpack-config.js.map +1 -1
- package/dist/esm/client/app-bootstrap.js +1 -1
- package/dist/esm/client/components/react-dev-overlay/server/shared.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/components/errors/dialog/dialog.js +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/components/errors/dialog/dialog.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/components/errors/error-overlay-bottom-stack/index.js +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/components/errors/error-overlay-bottom-stack/index.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/dev-overlay.js +2 -0
- package/dist/esm/client/components/react-dev-overlay/ui/dev-overlay.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/storybook/with-shadow-portal.js +2 -0
- package/dist/esm/client/components/react-dev-overlay/ui/storybook/with-shadow-portal.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/styles/base.js +2 -14
- package/dist/esm/client/components/react-dev-overlay/ui/styles/base.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/styles/colors.js +2 -23
- package/dist/esm/client/components/react-dev-overlay/ui/styles/colors.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/styles/dark-theme.js +25 -0
- package/dist/esm/client/components/react-dev-overlay/ui/styles/dark-theme.js.map +1 -0
- package/dist/esm/client/components/react-dev-overlay/utils/stack-frame.js +2 -5
- package/dist/esm/client/components/react-dev-overlay/utils/stack-frame.js.map +1 -1
- package/dist/esm/client/components/router-reducer/reducers/navigate-reducer.js +29 -9
- package/dist/esm/client/components/router-reducer/reducers/navigate-reducer.js.map +1 -1
- package/dist/esm/client/components/segment-cache/navigation.js +28 -19
- package/dist/esm/client/components/segment-cache/navigation.js.map +1 -1
- package/dist/esm/client/index.js +1 -1
- package/dist/esm/lib/server-external-packages.json +4 -0
- package/dist/esm/server/config.js +1 -1
- package/dist/esm/server/dev/hot-reloader-turbopack.js +1 -1
- package/dist/esm/server/dev/hot-reloader-webpack.js +1 -1
- package/dist/esm/server/lib/app-info-log.js +1 -1
- package/dist/esm/server/lib/start-server.js +1 -1
- package/dist/lib/server-external-packages.json +4 -0
- package/dist/server/config.js +1 -1
- package/dist/server/dev/hot-reloader-turbopack.js +1 -1
- package/dist/server/dev/hot-reloader-webpack.js +1 -1
- package/dist/server/lib/app-info-log.js +1 -1
- package/dist/server/lib/start-server.js +1 -1
- package/dist/telemetry/anonymous-meta.js +1 -1
- package/dist/telemetry/events/session-stopped.js +2 -2
- package/dist/telemetry/events/version.js +2 -2
- package/package.json +15 -15
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../../../src/client/components/react-dev-overlay/utils/stack-frame.ts"],"sourcesContent":["import type { StackFrame } from 'next/dist/compiled/stacktrace-parser'\nimport type {\n OriginalStackFrameResponse,\n OriginalStackFrameResponseResult,\n OriginalStackFramesRequest,\n} from '../server/shared'\nimport {\n isWebpackInternalResource,\n formatFrameSourceFile,\n} from './webpack-module-path'\nexport interface
|
1
|
+
{"version":3,"sources":["../../../../../src/client/components/react-dev-overlay/utils/stack-frame.ts"],"sourcesContent":["import type { StackFrame } from 'next/dist/compiled/stacktrace-parser'\nimport type {\n OriginalStackFrameResponse,\n OriginalStackFrameResponseResult,\n OriginalStackFramesRequest,\n} from '../server/shared'\nimport {\n isWebpackInternalResource,\n formatFrameSourceFile,\n} from './webpack-module-path'\n\nexport interface ResolvedOriginalStackFrame extends OriginalStackFrameResponse {\n error: false\n reason: null\n external: boolean\n ignored: boolean\n sourceStackFrame: StackFrame\n}\n\nexport interface RejectedOriginalStackFrame extends OriginalStackFrameResponse {\n error: true\n reason: string\n external: boolean\n ignored: boolean\n sourceStackFrame: StackFrame\n}\n\nexport type OriginalStackFrame =\n | ResolvedOriginalStackFrame\n | RejectedOriginalStackFrame\n\nfunction getOriginalStackFrame(\n source: StackFrame,\n response: OriginalStackFrameResponseResult\n): Promise<OriginalStackFrame> {\n async function _getOriginalStackFrame(): Promise<ResolvedOriginalStackFrame> {\n if (response.status === 'rejected') {\n throw new Error(response.reason)\n }\n\n const body: OriginalStackFrameResponse = response.value\n\n return {\n error: false,\n reason: null,\n external: false,\n sourceStackFrame: source,\n originalStackFrame: body.originalStackFrame,\n originalCodeFrame: body.originalCodeFrame || null,\n ignored: body.originalStackFrame?.ignored || false,\n }\n }\n\n // TODO: merge this section into ignoredList handling\n if (source.file === 'file://' || source.file?.match(/https?:\\/\\//)) {\n return Promise.resolve({\n error: false,\n reason: null,\n external: true,\n sourceStackFrame: source,\n originalStackFrame: null,\n originalCodeFrame: null,\n ignored: true,\n })\n }\n\n return _getOriginalStackFrame().catch(\n (err: Error): RejectedOriginalStackFrame => ({\n error: true,\n reason: err?.message ?? err?.toString() ?? 'Unknown Error',\n external: false,\n sourceStackFrame: source,\n originalStackFrame: null,\n originalCodeFrame: null,\n ignored: false,\n })\n )\n}\n\nexport async function getOriginalStackFrames(\n frames: StackFrame[],\n type: 'server' | 'edge-server' | null,\n isAppDir: boolean\n): Promise<OriginalStackFrame[]> {\n const req: OriginalStackFramesRequest = {\n frames,\n isServer: type === 'server',\n isEdgeServer: type === 'edge-server',\n isAppDirectory: isAppDir,\n }\n\n let res: Response | undefined = undefined\n let reason: string | undefined = undefined\n try {\n res = await fetch('/__nextjs_original-stack-frames', {\n method: 'POST',\n body: JSON.stringify(req),\n })\n } catch (e) {\n reason = e + ''\n }\n\n // When fails to fetch the original stack frames, we reject here to be\n // caught at `_getOriginalStackFrame()` and return the stack frames so\n // that the error overlay can render.\n if (res && res.ok && res.status !== 204) {\n const data = await res.json()\n return Promise.all(\n frames.map((frame, index) => getOriginalStackFrame(frame, data[index]))\n )\n } else {\n if (res) {\n reason = await res.text()\n }\n }\n return Promise.all(\n frames.map((frame) =>\n getOriginalStackFrame(frame, {\n status: 'rejected',\n reason: `Failed to fetch the original stack frames ${reason ? `: ${reason}` : ''}`,\n })\n )\n )\n}\n\nexport function getFrameSource(frame: StackFrame): string {\n if (!frame.file) return ''\n\n const isWebpackFrame = isWebpackInternalResource(frame.file)\n\n let str = ''\n // Skip URL parsing for webpack internal file paths.\n if (isWebpackFrame) {\n str = formatFrameSourceFile(frame.file)\n } else {\n try {\n const u = new URL(frame.file)\n\n let parsedPath = ''\n // Strip the origin for same-origin scripts.\n if (globalThis.location?.origin !== u.origin) {\n // URLs can be valid without an `origin`, so long as they have a\n // `protocol`. However, `origin` is preferred.\n if (u.origin === 'null') {\n parsedPath += u.protocol\n } else {\n parsedPath += u.origin\n }\n }\n\n // Strip query string information as it's typically too verbose to be\n // meaningful.\n parsedPath += u.pathname\n str = formatFrameSourceFile(parsedPath)\n } catch {\n str = formatFrameSourceFile(frame.file)\n }\n }\n\n if (!isWebpackInternalResource(frame.file) && frame.lineNumber != null) {\n if (str) {\n if (frame.column != null) {\n str += ` (${frame.lineNumber}:${frame.column})`\n } else {\n str += ` (${frame.lineNumber})`\n }\n }\n }\n return str\n}\n"],"names":["getFrameSource","getOriginalStackFrames","getOriginalStackFrame","source","response","_getOriginalStackFrame","body","status","Error","reason","value","error","external","sourceStackFrame","originalStackFrame","originalCodeFrame","ignored","file","match","Promise","resolve","catch","err","message","toString","frames","type","isAppDir","req","isServer","isEdgeServer","isAppDirectory","res","undefined","fetch","method","JSON","stringify","e","ok","data","json","all","map","frame","index","text","isWebpackFrame","isWebpackInternalResource","str","formatFrameSourceFile","globalThis","u","URL","parsedPath","location","origin","protocol","pathname","lineNumber","column"],"mappings":"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"}
|
@@ -89,7 +89,7 @@ function triggerLazyFetchForLeafSegments(newCache, currentCache, flightSegmentPa
|
|
89
89
|
}
|
90
90
|
return appliedPatch;
|
91
91
|
}
|
92
|
-
function handleNavigationResult(state, mutable, pendingPush, result) {
|
92
|
+
function handleNavigationResult(url, state, mutable, pendingPush, result) {
|
93
93
|
switch(result.tag){
|
94
94
|
case _navigation.NavigationResultTag.MPA:
|
95
95
|
{
|
@@ -98,8 +98,27 @@ function handleNavigationResult(state, mutable, pendingPush, result) {
|
|
98
98
|
return handleExternalUrl(state, mutable, newUrl, pendingPush);
|
99
99
|
}
|
100
100
|
case _navigation.NavigationResultTag.NoOp:
|
101
|
-
|
102
|
-
|
101
|
+
{
|
102
|
+
// The server responded with no change to the current page. However, if
|
103
|
+
// the URL changed, we still need to update that.
|
104
|
+
const newCanonicalUrl = result.data.canonicalUrl;
|
105
|
+
mutable.canonicalUrl = newCanonicalUrl;
|
106
|
+
// Check if the only thing that changed was the hash fragment.
|
107
|
+
const oldUrl = new URL(state.canonicalUrl, url);
|
108
|
+
const onlyHashChange = // We don't need to compare the origins, because client-driven
|
109
|
+
// navigations are always same-origin.
|
110
|
+
url.pathname === oldUrl.pathname && url.search === oldUrl.search && url.hash !== oldUrl.hash;
|
111
|
+
if (onlyHashChange) {
|
112
|
+
// The only updated part of the URL is the hash.
|
113
|
+
mutable.onlyHashChange = true;
|
114
|
+
mutable.shouldScroll = result.data.shouldScroll;
|
115
|
+
mutable.hashFragment = url.hash;
|
116
|
+
// Setting this to an empty array triggers a scroll for all new and
|
117
|
+
// updated segments. See `ScrollAndFocusHandler` for more details.
|
118
|
+
mutable.scrollableSegments = [];
|
119
|
+
}
|
120
|
+
return (0, _handlemutable.handleMutable)(state, mutable);
|
121
|
+
}
|
103
122
|
case _navigation.NavigationResultTag.Success:
|
104
123
|
{
|
105
124
|
// Received a new result.
|
@@ -108,13 +127,12 @@ function handleNavigationResult(state, mutable, pendingPush, result) {
|
|
108
127
|
mutable.canonicalUrl = result.data.canonicalUrl;
|
109
128
|
mutable.scrollableSegments = result.data.scrollableSegments;
|
110
129
|
mutable.shouldScroll = result.data.shouldScroll;
|
111
|
-
|
112
|
-
// mutable.hashFragment = hash
|
130
|
+
mutable.hashFragment = result.data.hash;
|
113
131
|
return (0, _handlemutable.handleMutable)(state, mutable);
|
114
132
|
}
|
115
133
|
case _navigation.NavigationResultTag.Async:
|
116
134
|
{
|
117
|
-
return result.data.then((asyncResult)=>handleNavigationResult(state, mutable, pendingPush, asyncResult), // If the navigation failed, return the current state.
|
135
|
+
return result.data.then((asyncResult)=>handleNavigationResult(url, state, mutable, pendingPush, asyncResult), // If the navigation failed, return the current state.
|
118
136
|
// TODO: This matches the current behavior but we need to do something
|
119
137
|
// better here if the network fails.
|
120
138
|
()=>{
|
@@ -122,8 +140,10 @@ function handleNavigationResult(state, mutable, pendingPush, result) {
|
|
122
140
|
});
|
123
141
|
}
|
124
142
|
default:
|
125
|
-
|
126
|
-
|
143
|
+
{
|
144
|
+
result;
|
145
|
+
return state;
|
146
|
+
}
|
127
147
|
}
|
128
148
|
}
|
129
149
|
function navigateReducer(state, action) {
|
@@ -157,7 +177,7 @@ function navigateReducer(state, action) {
|
|
157
177
|
// it will return a sync result if the navigation was prefetched. Hence
|
158
178
|
// a result type that's more complicated than you might expect.
|
159
179
|
const result = (0, _navigation.navigate)(url, state.cache, state.tree, state.nextUrl, shouldScroll);
|
160
|
-
return handleNavigationResult(state, mutable, pendingPush, result);
|
180
|
+
return handleNavigationResult(url, state, mutable, pendingPush, result);
|
161
181
|
}
|
162
182
|
const prefetchValues = (0, _prefetchcacheutils.getOrCreatePrefetchCacheEntry)({
|
163
183
|
url,
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../../../src/client/components/router-reducer/reducers/navigate-reducer.ts"],"sourcesContent":["import type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime'\nimport type {\n FlightRouterState,\n FlightSegmentPath,\n} from '../../../../server/app-render/types'\nimport { fetchServerResponse } from '../fetch-server-response'\nimport { createHrefFromUrl } from '../create-href-from-url'\nimport { invalidateCacheBelowFlightSegmentPath } from '../invalidate-cache-below-flight-segmentpath'\nimport { applyRouterStatePatchToTree } from '../apply-router-state-patch-to-tree'\nimport { shouldHardNavigate } from '../should-hard-navigate'\nimport { isNavigatingToNewRootLayout } from '../is-navigating-to-new-root-layout'\nimport {\n PrefetchCacheEntryStatus,\n type Mutable,\n type NavigateAction,\n type ReadonlyReducerState,\n type ReducerState,\n} from '../router-reducer-types'\nimport { handleMutable } from '../handle-mutable'\nimport { applyFlightData } from '../apply-flight-data'\nimport { prefetchQueue } from './prefetch-reducer'\nimport { createEmptyCacheNode } from '../../app-router'\nimport { DEFAULT_SEGMENT_KEY } from '../../../../shared/lib/segment'\nimport { listenForDynamicRequest, startPPRNavigation } from '../ppr-navigations'\nimport {\n getOrCreatePrefetchCacheEntry,\n prunePrefetchCache,\n} from '../prefetch-cache-utils'\nimport { clearCacheNodeDataForSegmentPath } from '../clear-cache-node-data-for-segment-path'\nimport { handleAliasedPrefetchEntry } from '../aliased-prefetch-navigations'\nimport {\n navigate as navigateUsingSegmentCache,\n NavigationResultTag,\n type NavigationResult,\n} from '../../segment-cache/navigation'\n\nexport function handleExternalUrl(\n state: ReadonlyReducerState,\n mutable: Mutable,\n url: string,\n pendingPush: boolean\n) {\n mutable.mpaNavigation = true\n mutable.canonicalUrl = url\n mutable.pendingPush = pendingPush\n mutable.scrollableSegments = undefined\n\n return handleMutable(state, mutable)\n}\n\nfunction generateSegmentsFromPatch(\n flightRouterPatch: FlightRouterState\n): FlightSegmentPath[] {\n const segments: FlightSegmentPath[] = []\n const [segment, parallelRoutes] = flightRouterPatch\n\n if (Object.keys(parallelRoutes).length === 0) {\n return [[segment]]\n }\n\n for (const [parallelRouteKey, parallelRoute] of Object.entries(\n parallelRoutes\n )) {\n for (const childSegment of generateSegmentsFromPatch(parallelRoute)) {\n // If the segment is empty, it means we are at the root of the tree\n if (segment === '') {\n segments.push([parallelRouteKey, ...childSegment])\n } else {\n segments.push([segment, parallelRouteKey, ...childSegment])\n }\n }\n }\n\n return segments\n}\n\nfunction triggerLazyFetchForLeafSegments(\n newCache: CacheNode,\n currentCache: CacheNode,\n flightSegmentPath: FlightSegmentPath,\n treePatch: FlightRouterState\n) {\n let appliedPatch = false\n\n newCache.rsc = currentCache.rsc\n newCache.prefetchRsc = currentCache.prefetchRsc\n newCache.loading = currentCache.loading\n newCache.parallelRoutes = new Map(currentCache.parallelRoutes)\n\n const segmentPathsToFill = generateSegmentsFromPatch(treePatch).map(\n (segment) => [...flightSegmentPath, ...segment]\n )\n\n for (const segmentPaths of segmentPathsToFill) {\n clearCacheNodeDataForSegmentPath(newCache, currentCache, segmentPaths)\n\n appliedPatch = true\n }\n\n return appliedPatch\n}\n\nfunction handleNavigationResult(\n state: ReadonlyReducerState,\n mutable: Mutable,\n pendingPush: boolean,\n result: NavigationResult\n): ReducerState {\n switch (result.tag) {\n case NavigationResultTag.MPA: {\n // Perform an MPA navigation.\n const newUrl = result.data\n return handleExternalUrl(state, mutable, newUrl, pendingPush)\n }\n case NavigationResultTag.NoOp:\n // The server responded with no change to the current page.\n return handleMutable(state, mutable)\n case NavigationResultTag.Success: {\n // Received a new result.\n mutable.cache = result.data.cacheNode\n mutable.patchedTree = result.data.flightRouterState\n mutable.canonicalUrl = result.data.canonicalUrl\n mutable.scrollableSegments = result.data.scrollableSegments\n mutable.shouldScroll = result.data.shouldScroll\n // TODO: Not yet implemented\n // mutable.hashFragment = hash\n return handleMutable(state, mutable)\n }\n case NavigationResultTag.Async: {\n return result.data.then(\n (asyncResult) =>\n handleNavigationResult(state, mutable, pendingPush, asyncResult),\n // If the navigation failed, return the current state.\n // TODO: This matches the current behavior but we need to do something\n // better here if the network fails.\n () => {\n return state\n }\n )\n }\n default:\n const _exhaustiveCheck: never = result\n return state\n }\n}\n\nexport function navigateReducer(\n state: ReadonlyReducerState,\n action: NavigateAction\n): ReducerState {\n const { url, isExternalUrl, navigateType, shouldScroll, allowAliasing } =\n action\n const mutable: Mutable = {}\n const { hash } = url\n const href = createHrefFromUrl(url)\n const pendingPush = navigateType === 'push'\n // we want to prune the prefetch cache on every navigation to avoid it growing too large\n prunePrefetchCache(state.prefetchCache)\n\n mutable.preserveCustomHistoryState = false\n mutable.pendingPush = pendingPush\n\n if (isExternalUrl) {\n return handleExternalUrl(state, mutable, url.toString(), pendingPush)\n }\n\n // Handles case where `<meta http-equiv=\"refresh\">` tag is present,\n // which will trigger an MPA navigation.\n if (document.getElementById('__next-page-redirect')) {\n return handleExternalUrl(state, mutable, href, pendingPush)\n }\n\n if (process.env.__NEXT_CLIENT_SEGMENT_CACHE) {\n // (Very Early Experimental Feature) Segment Cache\n //\n // Bypass the normal prefetch cache and use the new per-segment cache\n // implementation instead. This is only supported if PPR is enabled, too.\n //\n // Temporary glue code between the router reducer and the new navigation\n // implementation. Eventually we'll rewrite the router reducer to a\n // state machine.\n // TODO: Currently this always returns an async result, but in the future\n // it will return a sync result if the navigation was prefetched. Hence\n // a result type that's more complicated than you might expect.\n const result = navigateUsingSegmentCache(\n url,\n state.cache,\n state.tree,\n state.nextUrl,\n shouldScroll\n )\n return handleNavigationResult(state, mutable, pendingPush, result)\n }\n\n const prefetchValues = getOrCreatePrefetchCacheEntry({\n url,\n nextUrl: state.nextUrl,\n tree: state.tree,\n prefetchCache: state.prefetchCache,\n allowAliasing,\n })\n const { treeAtTimeOfPrefetch, data } = prefetchValues\n\n prefetchQueue.bump(data)\n\n return data.then(\n ({ flightData, canonicalUrl: canonicalUrlOverride, postponed }) => {\n let isFirstRead = false\n // we only want to mark this once\n if (!prefetchValues.lastUsedTime) {\n // important: we should only mark the cache node as dirty after we unsuspend from the call above\n prefetchValues.lastUsedTime = Date.now()\n isFirstRead = true\n }\n\n // Handle case when navigating to page in `pages` from `app`\n if (typeof flightData === 'string') {\n return handleExternalUrl(state, mutable, flightData, pendingPush)\n }\n\n const updatedCanonicalUrl = canonicalUrlOverride\n ? createHrefFromUrl(canonicalUrlOverride)\n : href\n\n const onlyHashChange =\n !!hash &&\n state.canonicalUrl.split('#', 1)[0] ===\n updatedCanonicalUrl.split('#', 1)[0]\n\n // If only the hash has changed, the server hasn't sent us any new data. We can just update\n // the mutable properties responsible for URL and scroll handling and return early.\n if (onlyHashChange) {\n mutable.onlyHashChange = true\n mutable.canonicalUrl = updatedCanonicalUrl\n mutable.shouldScroll = shouldScroll\n mutable.hashFragment = hash\n mutable.scrollableSegments = []\n return handleMutable(state, mutable)\n }\n\n if (prefetchValues.aliased) {\n const result = handleAliasedPrefetchEntry(\n state,\n flightData,\n url,\n mutable\n )\n\n // We didn't return new router state because we didn't apply the aliased entry for some reason.\n // We'll re-invoke the navigation handler but ensure that we don't attempt to use the aliased entry. This\n // will create an on-demand prefetch entry.\n if (result === false) {\n return navigateReducer(state, { ...action, allowAliasing: false })\n }\n\n return result\n }\n\n let currentTree = state.tree\n let currentCache = state.cache\n let scrollableSegments: FlightSegmentPath[] = []\n for (const normalizedFlightData of flightData) {\n const {\n pathToSegment: flightSegmentPath,\n seedData,\n head,\n isHeadPartial,\n isRootRender,\n } = normalizedFlightData\n let treePatch = normalizedFlightData.tree\n\n // TODO-APP: remove ''\n const flightSegmentPathWithLeadingEmpty = ['', ...flightSegmentPath]\n\n // Create new tree based on the flightSegmentPath and router state patch\n let newTree = applyRouterStatePatchToTree(\n // TODO-APP: remove ''\n flightSegmentPathWithLeadingEmpty,\n currentTree,\n treePatch,\n href\n )\n\n // If the tree patch can't be applied to the current tree then we use the tree at time of prefetch\n // TODO-APP: This should instead fill in the missing pieces in `currentTree` with the data from `treeAtTimeOfPrefetch`, then apply the patch.\n if (newTree === null) {\n newTree = applyRouterStatePatchToTree(\n // TODO-APP: remove ''\n flightSegmentPathWithLeadingEmpty,\n treeAtTimeOfPrefetch,\n treePatch,\n href\n )\n }\n\n if (newTree !== null) {\n if (\n // This is just a paranoid check. When a route is PPRed, the server\n // will send back a static response that's rendered from\n // the root. If for some reason it doesn't, we fall back to the\n // non-PPR implementation.\n // TODO: We should get rid of the else branch and do all navigations\n // via startPPRNavigation. The current structure is just\n // an incremental step.\n seedData &&\n isRootRender &&\n postponed\n ) {\n const task = startPPRNavigation(\n currentCache,\n currentTree,\n treePatch,\n seedData,\n head,\n isHeadPartial,\n scrollableSegments\n )\n\n if (task !== null) {\n if (task.route === null) {\n // Detected a change to the root layout. Perform an full-\n // page navigation.\n return handleExternalUrl(state, mutable, href, pendingPush)\n }\n // Use the tree computed by startPPRNavigation instead\n // of the one computed by applyRouterStatePatchToTree.\n // TODO: We should remove applyRouterStatePatchToTree\n // from the PPR path entirely.\n const patchedRouterState: FlightRouterState = task.route\n newTree = patchedRouterState\n\n const newCache = task.node\n if (newCache !== null) {\n // We've created a new Cache Node tree that contains a prefetched\n // version of the next page. This can be rendered instantly.\n mutable.cache = newCache\n }\n const dynamicRequestTree = task.dynamicRequestTree\n if (dynamicRequestTree !== null) {\n // The prefetched tree has dynamic holes in it. We initiate a\n // dynamic request to fill them in.\n //\n // Do not block on the result. We'll immediately render the Cache\n // Node tree and suspend on the dynamic parts. When the request\n // comes in, we'll fill in missing data and ping React to\n // re-render. Unlike the lazy fetching model in the non-PPR\n // implementation, this is modeled as a single React update +\n // streaming, rather than multiple top-level updates. (However,\n // even in the new model, we'll still need to sometimes update the\n // root multiple times per navigation, like if the server sends us\n // a different response than we expected. For now, we revert back\n // to the lazy fetching mechanism in that case.)\n const dynamicRequest = fetchServerResponse(url, {\n flightRouterState: dynamicRequestTree,\n nextUrl: state.nextUrl,\n })\n\n listenForDynamicRequest(task, dynamicRequest)\n // We store the dynamic request on the `lazyData` property of the CacheNode\n // because we're not going to await the dynamic request here. Since we're not blocking\n // on the dynamic request, `layout-router` will\n // task.node.lazyData = dynamicRequest\n } else {\n // The prefetched tree does not contain dynamic holes — it's\n // fully static. We can skip the dynamic request.\n }\n } else {\n // Nothing changed, so reuse the old cache.\n // TODO: What if the head changed but not any of the segment data?\n // Is that possible? If so, we should clone the whole tree and\n // update the head.\n newTree = treePatch\n }\n } else {\n // The static response does not include any dynamic holes, so\n // there's no need to do a second request.\n // TODO: As an incremental step this just reverts back to the\n // non-PPR implementation. We can simplify this branch further,\n // given that PPR prefetches are always static and return the whole\n // tree. Or in the meantime we could factor it out into a\n // separate function.\n\n if (isNavigatingToNewRootLayout(currentTree, newTree)) {\n return handleExternalUrl(state, mutable, href, pendingPush)\n }\n\n const cache: CacheNode = createEmptyCacheNode()\n let applied = false\n\n if (\n prefetchValues.status === PrefetchCacheEntryStatus.stale &&\n !isFirstRead\n ) {\n // 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\n // this will trigger a lazy fetch for the actual page data by nulling the `rsc` and `prefetchRsc` values for page data,\n // while copying over the `loading` for the segment that contains the page data.\n // We only do this on subsequent reads, as otherwise there'd be no loading data to re-use.\n\n // We skip this branch if only the hash fragment has changed, as we don't want to trigger a lazy fetch in that case\n applied = triggerLazyFetchForLeafSegments(\n cache,\n currentCache,\n flightSegmentPath,\n treePatch\n )\n // since we re-used the stale cache's loading state & refreshed the data,\n // update the `lastUsedTime` so that it can continue to be re-used for the next 30s\n prefetchValues.lastUsedTime = Date.now()\n } else {\n applied = applyFlightData(\n currentCache,\n cache,\n normalizedFlightData,\n prefetchValues\n )\n }\n\n const hardNavigate = shouldHardNavigate(\n // TODO-APP: remove ''\n flightSegmentPathWithLeadingEmpty,\n currentTree\n )\n\n if (hardNavigate) {\n // Copy rsc for the root node of the cache.\n cache.rsc = currentCache.rsc\n cache.prefetchRsc = currentCache.prefetchRsc\n\n invalidateCacheBelowFlightSegmentPath(\n cache,\n currentCache,\n flightSegmentPath\n )\n // Ensure the existing cache value is used when the cache was not invalidated.\n mutable.cache = cache\n } else if (applied) {\n mutable.cache = cache\n // If we applied the cache, we update the \"current cache\" value so any other\n // segments in the FlightDataPath will be able to reference the updated cache.\n currentCache = cache\n }\n\n for (const subSegment of generateSegmentsFromPatch(treePatch)) {\n const scrollableSegmentPath = [\n ...flightSegmentPath,\n ...subSegment,\n ]\n // Filter out the __DEFAULT__ paths as they shouldn't be scrolled to in this case.\n if (\n scrollableSegmentPath[scrollableSegmentPath.length - 1] !==\n DEFAULT_SEGMENT_KEY\n ) {\n scrollableSegments.push(scrollableSegmentPath)\n }\n }\n }\n\n currentTree = newTree\n }\n }\n\n mutable.patchedTree = currentTree\n mutable.canonicalUrl = updatedCanonicalUrl\n mutable.scrollableSegments = scrollableSegments\n mutable.hashFragment = hash\n mutable.shouldScroll = shouldScroll\n\n return handleMutable(state, mutable)\n },\n () => state\n )\n}\n"],"names":["handleExternalUrl","navigateReducer","state","mutable","url","pendingPush","mpaNavigation","canonicalUrl","scrollableSegments","undefined","handleMutable","generateSegmentsFromPatch","flightRouterPatch","segments","segment","parallelRoutes","Object","keys","length","parallelRouteKey","parallelRoute","entries","childSegment","push","triggerLazyFetchForLeafSegments","newCache","currentCache","flightSegmentPath","treePatch","appliedPatch","rsc","prefetchRsc","loading","Map","segmentPathsToFill","map","segmentPaths","clearCacheNodeDataForSegmentPath","handleNavigationResult","result","tag","NavigationResultTag","MPA","newUrl","data","NoOp","Success","cache","cacheNode","patchedTree","flightRouterState","shouldScroll","Async","then","asyncResult","_exhaustiveCheck","action","isExternalUrl","navigateType","allowAliasing","hash","href","createHrefFromUrl","prunePrefetchCache","prefetchCache","preserveCustomHistoryState","toString","document","getElementById","process","env","__NEXT_CLIENT_SEGMENT_CACHE","navigateUsingSegmentCache","tree","nextUrl","prefetchValues","getOrCreatePrefetchCacheEntry","treeAtTimeOfPrefetch","prefetchQueue","bump","flightData","canonicalUrlOverride","postponed","isFirstRead","lastUsedTime","Date","now","updatedCanonicalUrl","onlyHashChange","split","hashFragment","aliased","handleAliasedPrefetchEntry","currentTree","normalizedFlightData","pathToSegment","seedData","head","isHeadPartial","isRootRender","flightSegmentPathWithLeadingEmpty","newTree","applyRouterStatePatchToTree","task","startPPRNavigation","route","patchedRouterState","node","dynamicRequestTree","dynamicRequest","fetchServerResponse","listenForDynamicRequest","isNavigatingToNewRootLayout","createEmptyCacheNode","applied","status","PrefetchCacheEntryStatus","stale","applyFlightData","hardNavigate","shouldHardNavigate","invalidateCacheBelowFlightSegmentPath","subSegment","scrollableSegmentPath","DEFAULT_SEGMENT_KEY"],"mappings":";;;;;;;;;;;;;;;IAoCgBA,iBAAiB;eAAjBA;;IA8GAC,eAAe;eAAfA;;;qCA7IoB;mCACF;uDACoB;6CACV;oCACT;6CACS;oCAOrC;+BACuB;iCACE;iCACF;2BACO;yBACD;gCACwB;oCAIrD;kDAC0C;4CACN;4BAKpC;AAEA,SAASD,kBACdE,KAA2B,EAC3BC,OAAgB,EAChBC,GAAW,EACXC,WAAoB;IAEpBF,QAAQG,aAAa,GAAG;IACxBH,QAAQI,YAAY,GAAGH;IACvBD,QAAQE,WAAW,GAAGA;IACtBF,QAAQK,kBAAkB,GAAGC;IAE7B,OAAOC,IAAAA,4BAAa,EAACR,OAAOC;AAC9B;AAEA,SAASQ,0BACPC,iBAAoC;IAEpC,MAAMC,WAAgC,EAAE;IACxC,MAAM,CAACC,SAASC,eAAe,GAAGH;IAElC,IAAII,OAAOC,IAAI,CAACF,gBAAgBG,MAAM,KAAK,GAAG;QAC5C,OAAO;YAAC;gBAACJ;aAAQ;SAAC;IACpB;IAEA,KAAK,MAAM,CAACK,kBAAkBC,cAAc,IAAIJ,OAAOK,OAAO,CAC5DN,gBACC;QACD,KAAK,MAAMO,gBAAgBX,0BAA0BS,eAAgB;YACnE,mEAAmE;YACnE,IAAIN,YAAY,IAAI;gBAClBD,SAASU,IAAI,CAAC;oBAACJ;uBAAqBG;iBAAa;YACnD,OAAO;gBACLT,SAASU,IAAI,CAAC;oBAACT;oBAASK;uBAAqBG;iBAAa;YAC5D;QACF;IACF;IAEA,OAAOT;AACT;AAEA,SAASW,gCACPC,QAAmB,EACnBC,YAAuB,EACvBC,iBAAoC,EACpCC,SAA4B;IAE5B,IAAIC,eAAe;IAEnBJ,SAASK,GAAG,GAAGJ,aAAaI,GAAG;IAC/BL,SAASM,WAAW,GAAGL,aAAaK,WAAW;IAC/CN,SAASO,OAAO,GAAGN,aAAaM,OAAO;IACvCP,SAASV,cAAc,GAAG,IAAIkB,IAAIP,aAAaX,cAAc;IAE7D,MAAMmB,qBAAqBvB,0BAA0BiB,WAAWO,GAAG,CACjE,CAACrB,UAAY;eAAIa;eAAsBb;SAAQ;IAGjD,KAAK,MAAMsB,gBAAgBF,mBAAoB;QAC7CG,IAAAA,kEAAgC,EAACZ,UAAUC,cAAcU;QAEzDP,eAAe;IACjB;IAEA,OAAOA;AACT;AAEA,SAASS,uBACPpC,KAA2B,EAC3BC,OAAgB,EAChBE,WAAoB,EACpBkC,MAAwB;IAExB,OAAQA,OAAOC,GAAG;QAChB,KAAKC,+BAAmB,CAACC,GAAG;YAAE;gBAC5B,6BAA6B;gBAC7B,MAAMC,SAASJ,OAAOK,IAAI;gBAC1B,OAAO5C,kBAAkBE,OAAOC,SAASwC,QAAQtC;YACnD;QACA,KAAKoC,+BAAmB,CAACI,IAAI;YAC3B,2DAA2D;YAC3D,OAAOnC,IAAAA,4BAAa,EAACR,OAAOC;QAC9B,KAAKsC,+BAAmB,CAACK,OAAO;YAAE;gBAChC,yBAAyB;gBACzB3C,QAAQ4C,KAAK,GAAGR,OAAOK,IAAI,CAACI,SAAS;gBACrC7C,QAAQ8C,WAAW,GAAGV,OAAOK,IAAI,CAACM,iBAAiB;gBACnD/C,QAAQI,YAAY,GAAGgC,OAAOK,IAAI,CAACrC,YAAY;gBAC/CJ,QAAQK,kBAAkB,GAAG+B,OAAOK,IAAI,CAACpC,kBAAkB;gBAC3DL,QAAQgD,YAAY,GAAGZ,OAAOK,IAAI,CAACO,YAAY;gBAC/C,4BAA4B;gBAC5B,8BAA8B;gBAC9B,OAAOzC,IAAAA,4BAAa,EAACR,OAAOC;YAC9B;QACA,KAAKsC,+BAAmB,CAACW,KAAK;YAAE;gBAC9B,OAAOb,OAAOK,IAAI,CAACS,IAAI,CACrB,CAACC,cACChB,uBAAuBpC,OAAOC,SAASE,aAAaiD,cACtD,sDAAsD;gBACtD,sEAAsE;gBACtE,oCAAoC;gBACpC;oBACE,OAAOpD;gBACT;YAEJ;QACA;YACE,MAAMqD,mBAA0BhB;YAChC,OAAOrC;IACX;AACF;AAEO,SAASD,gBACdC,KAA2B,EAC3BsD,MAAsB;IAEtB,MAAM,EAAEpD,GAAG,EAAEqD,aAAa,EAAEC,YAAY,EAAEP,YAAY,EAAEQ,aAAa,EAAE,GACrEH;IACF,MAAMrD,UAAmB,CAAC;IAC1B,MAAM,EAAEyD,IAAI,EAAE,GAAGxD;IACjB,MAAMyD,OAAOC,IAAAA,oCAAiB,EAAC1D;IAC/B,MAAMC,cAAcqD,iBAAiB;IACrC,wFAAwF;IACxFK,IAAAA,sCAAkB,EAAC7D,MAAM8D,aAAa;IAEtC7D,QAAQ8D,0BAA0B,GAAG;IACrC9D,QAAQE,WAAW,GAAGA;IAEtB,IAAIoD,eAAe;QACjB,OAAOzD,kBAAkBE,OAAOC,SAASC,IAAI8D,QAAQ,IAAI7D;IAC3D;IAEA,mEAAmE;IACnE,wCAAwC;IACxC,IAAI8D,SAASC,cAAc,CAAC,yBAAyB;QACnD,OAAOpE,kBAAkBE,OAAOC,SAAS0D,MAAMxD;IACjD;IAEA,IAAIgE,QAAQC,GAAG,CAACC,2BAA2B,EAAE;QAC3C,kDAAkD;QAClD,EAAE;QACF,qEAAqE;QACrE,yEAAyE;QACzE,EAAE;QACF,wEAAwE;QACxE,mEAAmE;QACnE,iBAAiB;QACjB,yEAAyE;QACzE,uEAAuE;QACvE,+DAA+D;QAC/D,MAAMhC,SAASiC,IAAAA,oBAAyB,EACtCpE,KACAF,MAAM6C,KAAK,EACX7C,MAAMuE,IAAI,EACVvE,MAAMwE,OAAO,EACbvB;QAEF,OAAOb,uBAAuBpC,OAAOC,SAASE,aAAakC;IAC7D;IAEA,MAAMoC,iBAAiBC,IAAAA,iDAA6B,EAAC;QACnDxE;QACAsE,SAASxE,MAAMwE,OAAO;QACtBD,MAAMvE,MAAMuE,IAAI;QAChBT,eAAe9D,MAAM8D,aAAa;QAClCL;IACF;IACA,MAAM,EAAEkB,oBAAoB,EAAEjC,IAAI,EAAE,GAAG+B;IAEvCG,8BAAa,CAACC,IAAI,CAACnC;IAEnB,OAAOA,KAAKS,IAAI,CACd;YAAC,EAAE2B,UAAU,EAAEzE,cAAc0E,oBAAoB,EAAEC,SAAS,EAAE;QAC5D,IAAIC,cAAc;QAClB,iCAAiC;QACjC,IAAI,CAACR,eAAeS,YAAY,EAAE;YAChC,gGAAgG;YAChGT,eAAeS,YAAY,GAAGC,KAAKC,GAAG;YACtCH,cAAc;QAChB;QAEA,4DAA4D;QAC5D,IAAI,OAAOH,eAAe,UAAU;YAClC,OAAOhF,kBAAkBE,OAAOC,SAAS6E,YAAY3E;QACvD;QAEA,MAAMkF,sBAAsBN,uBACxBnB,IAAAA,oCAAiB,EAACmB,wBAClBpB;QAEJ,MAAM2B,iBACJ,CAAC,CAAC5B,QACF1D,MAAMK,YAAY,CAACkF,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,KACjCF,oBAAoBE,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE;QAExC,2FAA2F;QAC3F,mFAAmF;QACnF,IAAID,gBAAgB;YAClBrF,QAAQqF,cAAc,GAAG;YACzBrF,QAAQI,YAAY,GAAGgF;YACvBpF,QAAQgD,YAAY,GAAGA;YACvBhD,QAAQuF,YAAY,GAAG9B;YACvBzD,QAAQK,kBAAkB,GAAG,EAAE;YAC/B,OAAOE,IAAAA,4BAAa,EAACR,OAAOC;QAC9B;QAEA,IAAIwE,eAAegB,OAAO,EAAE;YAC1B,MAAMpD,SAASqD,IAAAA,sDAA0B,EACvC1F,OACA8E,YACA5E,KACAD;YAGF,+FAA+F;YAC/F,yGAAyG;YACzG,2CAA2C;YAC3C,IAAIoC,WAAW,OAAO;gBACpB,OAAOtC,gBAAgBC,OAAO;oBAAE,GAAGsD,MAAM;oBAAEG,eAAe;gBAAM;YAClE;YAEA,OAAOpB;QACT;QAEA,IAAIsD,cAAc3F,MAAMuE,IAAI;QAC5B,IAAI/C,eAAexB,MAAM6C,KAAK;QAC9B,IAAIvC,qBAA0C,EAAE;QAChD,KAAK,MAAMsF,wBAAwBd,WAAY;YAC7C,MAAM,EACJe,eAAepE,iBAAiB,EAChCqE,QAAQ,EACRC,IAAI,EACJC,aAAa,EACbC,YAAY,EACb,GAAGL;YACJ,IAAIlE,YAAYkE,qBAAqBrB,IAAI;YAEzC,sBAAsB;YACtB,MAAM2B,oCAAoC;gBAAC;mBAAOzE;aAAkB;YAEpE,wEAAwE;YACxE,IAAI0E,UAAUC,IAAAA,wDAA2B,EACvC,sBAAsB;YACtBF,mCACAP,aACAjE,WACAiC;YAGF,kGAAkG;YAClG,6IAA6I;YAC7I,IAAIwC,YAAY,MAAM;gBACpBA,UAAUC,IAAAA,wDAA2B,EACnC,sBAAsB;gBACtBF,mCACAvB,sBACAjD,WACAiC;YAEJ;YAEA,IAAIwC,YAAY,MAAM;gBACpB,IACE,mEAAmE;gBACnE,wDAAwD;gBACxD,+DAA+D;gBAC/D,0BAA0B;gBAC1B,oEAAoE;gBACpE,wDAAwD;gBACxD,uBAAuB;gBACvBL,YACAG,gBACAjB,WACA;oBACA,MAAMqB,OAAOC,IAAAA,kCAAkB,EAC7B9E,cACAmE,aACAjE,WACAoE,UACAC,MACAC,eACA1F;oBAGF,IAAI+F,SAAS,MAAM;wBACjB,IAAIA,KAAKE,KAAK,KAAK,MAAM;4BACvB,yDAAyD;4BACzD,mBAAmB;4BACnB,OAAOzG,kBAAkBE,OAAOC,SAAS0D,MAAMxD;wBACjD;wBACA,sDAAsD;wBACtD,sDAAsD;wBACtD,qDAAqD;wBACrD,8BAA8B;wBAC9B,MAAMqG,qBAAwCH,KAAKE,KAAK;wBACxDJ,UAAUK;wBAEV,MAAMjF,WAAW8E,KAAKI,IAAI;wBAC1B,IAAIlF,aAAa,MAAM;4BACrB,iEAAiE;4BACjE,4DAA4D;4BAC5DtB,QAAQ4C,KAAK,GAAGtB;wBAClB;wBACA,MAAMmF,qBAAqBL,KAAKK,kBAAkB;wBAClD,IAAIA,uBAAuB,MAAM;4BAC/B,6DAA6D;4BAC7D,mCAAmC;4BACnC,EAAE;4BACF,iEAAiE;4BACjE,+DAA+D;4BAC/D,yDAAyD;4BACzD,2DAA2D;4BAC3D,6DAA6D;4BAC7D,+DAA+D;4BAC/D,kEAAkE;4BAClE,kEAAkE;4BAClE,iEAAiE;4BACjE,gDAAgD;4BAChD,MAAMC,iBAAiBC,IAAAA,wCAAmB,EAAC1G,KAAK;gCAC9C8C,mBAAmB0D;gCACnBlC,SAASxE,MAAMwE,OAAO;4BACxB;4BAEAqC,IAAAA,uCAAuB,EAACR,MAAMM;wBAC9B,2EAA2E;wBAC3E,sFAAsF;wBACtF,+CAA+C;wBAC/C,sCAAsC;wBACxC,OAAO;wBACL,4DAA4D;wBAC5D,iDAAiD;wBACnD;oBACF,OAAO;wBACL,2CAA2C;wBAC3C,kEAAkE;wBAClE,8DAA8D;wBAC9D,mBAAmB;wBACnBR,UAAUzE;oBACZ;gBACF,OAAO;oBACL,6DAA6D;oBAC7D,0CAA0C;oBAC1C,6DAA6D;oBAC7D,+DAA+D;oBAC/D,mEAAmE;oBACnE,yDAAyD;oBACzD,qBAAqB;oBAErB,IAAIoF,IAAAA,wDAA2B,EAACnB,aAAaQ,UAAU;wBACrD,OAAOrG,kBAAkBE,OAAOC,SAAS0D,MAAMxD;oBACjD;oBAEA,MAAM0C,QAAmBkE,IAAAA,+BAAoB;oBAC7C,IAAIC,UAAU;oBAEd,IACEvC,eAAewC,MAAM,KAAKC,4CAAwB,CAACC,KAAK,IACxD,CAAClC,aACD;wBACA,yJAAyJ;wBACzJ,uHAAuH;wBACvH,gFAAgF;wBAChF,0FAA0F;wBAE1F,mHAAmH;wBACnH+B,UAAU1F,gCACRuB,OACArB,cACAC,mBACAC;wBAEF,yEAAyE;wBACzE,mFAAmF;wBACnF+C,eAAeS,YAAY,GAAGC,KAAKC,GAAG;oBACxC,OAAO;wBACL4B,UAAUI,IAAAA,gCAAe,EACvB5F,cACAqB,OACA+C,sBACAnB;oBAEJ;oBAEA,MAAM4C,eAAeC,IAAAA,sCAAkB,EACrC,sBAAsB;oBACtBpB,mCACAP;oBAGF,IAAI0B,cAAc;wBAChB,2CAA2C;wBAC3CxE,MAAMjB,GAAG,GAAGJ,aAAaI,GAAG;wBAC5BiB,MAAMhB,WAAW,GAAGL,aAAaK,WAAW;wBAE5C0F,IAAAA,4EAAqC,EACnC1E,OACArB,cACAC;wBAEF,8EAA8E;wBAC9ExB,QAAQ4C,KAAK,GAAGA;oBAClB,OAAO,IAAImE,SAAS;wBAClB/G,QAAQ4C,KAAK,GAAGA;wBAChB,4EAA4E;wBAC5E,8EAA8E;wBAC9ErB,eAAeqB;oBACjB;oBAEA,KAAK,MAAM2E,cAAc/G,0BAA0BiB,WAAY;wBAC7D,MAAM+F,wBAAwB;+BACzBhG;+BACA+F;yBACJ;wBACD,kFAAkF;wBAClF,IACEC,qBAAqB,CAACA,sBAAsBzG,MAAM,GAAG,EAAE,KACvD0G,4BAAmB,EACnB;4BACApH,mBAAmBe,IAAI,CAACoG;wBAC1B;oBACF;gBACF;gBAEA9B,cAAcQ;YAChB;QACF;QAEAlG,QAAQ8C,WAAW,GAAG4C;QACtB1F,QAAQI,YAAY,GAAGgF;QACvBpF,QAAQK,kBAAkB,GAAGA;QAC7BL,QAAQuF,YAAY,GAAG9B;QACvBzD,QAAQgD,YAAY,GAAGA;QAEvB,OAAOzC,IAAAA,4BAAa,EAACR,OAAOC;IAC9B,GACA,IAAMD;AAEV"}
|
1
|
+
{"version":3,"sources":["../../../../../src/client/components/router-reducer/reducers/navigate-reducer.ts"],"sourcesContent":["import type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime'\nimport type {\n FlightRouterState,\n FlightSegmentPath,\n} from '../../../../server/app-render/types'\nimport { fetchServerResponse } from '../fetch-server-response'\nimport { createHrefFromUrl } from '../create-href-from-url'\nimport { invalidateCacheBelowFlightSegmentPath } from '../invalidate-cache-below-flight-segmentpath'\nimport { applyRouterStatePatchToTree } from '../apply-router-state-patch-to-tree'\nimport { shouldHardNavigate } from '../should-hard-navigate'\nimport { isNavigatingToNewRootLayout } from '../is-navigating-to-new-root-layout'\nimport {\n PrefetchCacheEntryStatus,\n type Mutable,\n type NavigateAction,\n type ReadonlyReducerState,\n type ReducerState,\n} from '../router-reducer-types'\nimport { handleMutable } from '../handle-mutable'\nimport { applyFlightData } from '../apply-flight-data'\nimport { prefetchQueue } from './prefetch-reducer'\nimport { createEmptyCacheNode } from '../../app-router'\nimport { DEFAULT_SEGMENT_KEY } from '../../../../shared/lib/segment'\nimport { listenForDynamicRequest, startPPRNavigation } from '../ppr-navigations'\nimport {\n getOrCreatePrefetchCacheEntry,\n prunePrefetchCache,\n} from '../prefetch-cache-utils'\nimport { clearCacheNodeDataForSegmentPath } from '../clear-cache-node-data-for-segment-path'\nimport { handleAliasedPrefetchEntry } from '../aliased-prefetch-navigations'\nimport {\n navigate as navigateUsingSegmentCache,\n NavigationResultTag,\n type NavigationResult,\n} from '../../segment-cache/navigation'\n\nexport function handleExternalUrl(\n state: ReadonlyReducerState,\n mutable: Mutable,\n url: string,\n pendingPush: boolean\n) {\n mutable.mpaNavigation = true\n mutable.canonicalUrl = url\n mutable.pendingPush = pendingPush\n mutable.scrollableSegments = undefined\n\n return handleMutable(state, mutable)\n}\n\nfunction generateSegmentsFromPatch(\n flightRouterPatch: FlightRouterState\n): FlightSegmentPath[] {\n const segments: FlightSegmentPath[] = []\n const [segment, parallelRoutes] = flightRouterPatch\n\n if (Object.keys(parallelRoutes).length === 0) {\n return [[segment]]\n }\n\n for (const [parallelRouteKey, parallelRoute] of Object.entries(\n parallelRoutes\n )) {\n for (const childSegment of generateSegmentsFromPatch(parallelRoute)) {\n // If the segment is empty, it means we are at the root of the tree\n if (segment === '') {\n segments.push([parallelRouteKey, ...childSegment])\n } else {\n segments.push([segment, parallelRouteKey, ...childSegment])\n }\n }\n }\n\n return segments\n}\n\nfunction triggerLazyFetchForLeafSegments(\n newCache: CacheNode,\n currentCache: CacheNode,\n flightSegmentPath: FlightSegmentPath,\n treePatch: FlightRouterState\n) {\n let appliedPatch = false\n\n newCache.rsc = currentCache.rsc\n newCache.prefetchRsc = currentCache.prefetchRsc\n newCache.loading = currentCache.loading\n newCache.parallelRoutes = new Map(currentCache.parallelRoutes)\n\n const segmentPathsToFill = generateSegmentsFromPatch(treePatch).map(\n (segment) => [...flightSegmentPath, ...segment]\n )\n\n for (const segmentPaths of segmentPathsToFill) {\n clearCacheNodeDataForSegmentPath(newCache, currentCache, segmentPaths)\n\n appliedPatch = true\n }\n\n return appliedPatch\n}\n\nfunction handleNavigationResult(\n url: URL,\n state: ReadonlyReducerState,\n mutable: Mutable,\n pendingPush: boolean,\n result: NavigationResult\n): ReducerState {\n switch (result.tag) {\n case NavigationResultTag.MPA: {\n // Perform an MPA navigation.\n const newUrl = result.data\n return handleExternalUrl(state, mutable, newUrl, pendingPush)\n }\n case NavigationResultTag.NoOp: {\n // The server responded with no change to the current page. However, if\n // the URL changed, we still need to update that.\n const newCanonicalUrl = result.data.canonicalUrl\n mutable.canonicalUrl = newCanonicalUrl\n\n // Check if the only thing that changed was the hash fragment.\n const oldUrl = new URL(state.canonicalUrl, url)\n const onlyHashChange =\n // We don't need to compare the origins, because client-driven\n // navigations are always same-origin.\n url.pathname === oldUrl.pathname &&\n url.search === oldUrl.search &&\n url.hash !== oldUrl.hash\n if (onlyHashChange) {\n // The only updated part of the URL is the hash.\n mutable.onlyHashChange = true\n mutable.shouldScroll = result.data.shouldScroll\n mutable.hashFragment = url.hash\n // Setting this to an empty array triggers a scroll for all new and\n // updated segments. See `ScrollAndFocusHandler` for more details.\n mutable.scrollableSegments = []\n }\n\n return handleMutable(state, mutable)\n }\n case NavigationResultTag.Success: {\n // Received a new result.\n mutable.cache = result.data.cacheNode\n mutable.patchedTree = result.data.flightRouterState\n mutable.canonicalUrl = result.data.canonicalUrl\n mutable.scrollableSegments = result.data.scrollableSegments\n mutable.shouldScroll = result.data.shouldScroll\n mutable.hashFragment = result.data.hash\n return handleMutable(state, mutable)\n }\n case NavigationResultTag.Async: {\n return result.data.then(\n (asyncResult) =>\n handleNavigationResult(url, state, mutable, pendingPush, asyncResult),\n // If the navigation failed, return the current state.\n // TODO: This matches the current behavior but we need to do something\n // better here if the network fails.\n () => {\n return state\n }\n )\n }\n default: {\n result satisfies never\n return state\n }\n }\n}\n\nexport function navigateReducer(\n state: ReadonlyReducerState,\n action: NavigateAction\n): ReducerState {\n const { url, isExternalUrl, navigateType, shouldScroll, allowAliasing } =\n action\n const mutable: Mutable = {}\n const { hash } = url\n const href = createHrefFromUrl(url)\n const pendingPush = navigateType === 'push'\n // we want to prune the prefetch cache on every navigation to avoid it growing too large\n prunePrefetchCache(state.prefetchCache)\n\n mutable.preserveCustomHistoryState = false\n mutable.pendingPush = pendingPush\n\n if (isExternalUrl) {\n return handleExternalUrl(state, mutable, url.toString(), pendingPush)\n }\n\n // Handles case where `<meta http-equiv=\"refresh\">` tag is present,\n // which will trigger an MPA navigation.\n if (document.getElementById('__next-page-redirect')) {\n return handleExternalUrl(state, mutable, href, pendingPush)\n }\n\n if (process.env.__NEXT_CLIENT_SEGMENT_CACHE) {\n // (Very Early Experimental Feature) Segment Cache\n //\n // Bypass the normal prefetch cache and use the new per-segment cache\n // implementation instead. This is only supported if PPR is enabled, too.\n //\n // Temporary glue code between the router reducer and the new navigation\n // implementation. Eventually we'll rewrite the router reducer to a\n // state machine.\n // TODO: Currently this always returns an async result, but in the future\n // it will return a sync result if the navigation was prefetched. Hence\n // a result type that's more complicated than you might expect.\n const result = navigateUsingSegmentCache(\n url,\n state.cache,\n state.tree,\n state.nextUrl,\n shouldScroll\n )\n return handleNavigationResult(url, state, mutable, pendingPush, result)\n }\n\n const prefetchValues = getOrCreatePrefetchCacheEntry({\n url,\n nextUrl: state.nextUrl,\n tree: state.tree,\n prefetchCache: state.prefetchCache,\n allowAliasing,\n })\n const { treeAtTimeOfPrefetch, data } = prefetchValues\n\n prefetchQueue.bump(data)\n\n return data.then(\n ({ flightData, canonicalUrl: canonicalUrlOverride, postponed }) => {\n let isFirstRead = false\n // we only want to mark this once\n if (!prefetchValues.lastUsedTime) {\n // important: we should only mark the cache node as dirty after we unsuspend from the call above\n prefetchValues.lastUsedTime = Date.now()\n isFirstRead = true\n }\n\n // Handle case when navigating to page in `pages` from `app`\n if (typeof flightData === 'string') {\n return handleExternalUrl(state, mutable, flightData, pendingPush)\n }\n\n const updatedCanonicalUrl = canonicalUrlOverride\n ? createHrefFromUrl(canonicalUrlOverride)\n : href\n\n const onlyHashChange =\n !!hash &&\n state.canonicalUrl.split('#', 1)[0] ===\n updatedCanonicalUrl.split('#', 1)[0]\n\n // If only the hash has changed, the server hasn't sent us any new data. We can just update\n // the mutable properties responsible for URL and scroll handling and return early.\n if (onlyHashChange) {\n mutable.onlyHashChange = true\n mutable.canonicalUrl = updatedCanonicalUrl\n mutable.shouldScroll = shouldScroll\n mutable.hashFragment = hash\n mutable.scrollableSegments = []\n return handleMutable(state, mutable)\n }\n\n if (prefetchValues.aliased) {\n const result = handleAliasedPrefetchEntry(\n state,\n flightData,\n url,\n mutable\n )\n\n // We didn't return new router state because we didn't apply the aliased entry for some reason.\n // We'll re-invoke the navigation handler but ensure that we don't attempt to use the aliased entry. This\n // will create an on-demand prefetch entry.\n if (result === false) {\n return navigateReducer(state, { ...action, allowAliasing: false })\n }\n\n return result\n }\n\n let currentTree = state.tree\n let currentCache = state.cache\n let scrollableSegments: FlightSegmentPath[] = []\n for (const normalizedFlightData of flightData) {\n const {\n pathToSegment: flightSegmentPath,\n seedData,\n head,\n isHeadPartial,\n isRootRender,\n } = normalizedFlightData\n let treePatch = normalizedFlightData.tree\n\n // TODO-APP: remove ''\n const flightSegmentPathWithLeadingEmpty = ['', ...flightSegmentPath]\n\n // Create new tree based on the flightSegmentPath and router state patch\n let newTree = applyRouterStatePatchToTree(\n // TODO-APP: remove ''\n flightSegmentPathWithLeadingEmpty,\n currentTree,\n treePatch,\n href\n )\n\n // If the tree patch can't be applied to the current tree then we use the tree at time of prefetch\n // TODO-APP: This should instead fill in the missing pieces in `currentTree` with the data from `treeAtTimeOfPrefetch`, then apply the patch.\n if (newTree === null) {\n newTree = applyRouterStatePatchToTree(\n // TODO-APP: remove ''\n flightSegmentPathWithLeadingEmpty,\n treeAtTimeOfPrefetch,\n treePatch,\n href\n )\n }\n\n if (newTree !== null) {\n if (\n // This is just a paranoid check. When a route is PPRed, the server\n // will send back a static response that's rendered from\n // the root. If for some reason it doesn't, we fall back to the\n // non-PPR implementation.\n // TODO: We should get rid of the else branch and do all navigations\n // via startPPRNavigation. The current structure is just\n // an incremental step.\n seedData &&\n isRootRender &&\n postponed\n ) {\n const task = startPPRNavigation(\n currentCache,\n currentTree,\n treePatch,\n seedData,\n head,\n isHeadPartial,\n scrollableSegments\n )\n\n if (task !== null) {\n if (task.route === null) {\n // Detected a change to the root layout. Perform an full-\n // page navigation.\n return handleExternalUrl(state, mutable, href, pendingPush)\n }\n // Use the tree computed by startPPRNavigation instead\n // of the one computed by applyRouterStatePatchToTree.\n // TODO: We should remove applyRouterStatePatchToTree\n // from the PPR path entirely.\n const patchedRouterState: FlightRouterState = task.route\n newTree = patchedRouterState\n\n const newCache = task.node\n if (newCache !== null) {\n // We've created a new Cache Node tree that contains a prefetched\n // version of the next page. This can be rendered instantly.\n mutable.cache = newCache\n }\n const dynamicRequestTree = task.dynamicRequestTree\n if (dynamicRequestTree !== null) {\n // The prefetched tree has dynamic holes in it. We initiate a\n // dynamic request to fill them in.\n //\n // Do not block on the result. We'll immediately render the Cache\n // Node tree and suspend on the dynamic parts. When the request\n // comes in, we'll fill in missing data and ping React to\n // re-render. Unlike the lazy fetching model in the non-PPR\n // implementation, this is modeled as a single React update +\n // streaming, rather than multiple top-level updates. (However,\n // even in the new model, we'll still need to sometimes update the\n // root multiple times per navigation, like if the server sends us\n // a different response than we expected. For now, we revert back\n // to the lazy fetching mechanism in that case.)\n const dynamicRequest = fetchServerResponse(url, {\n flightRouterState: dynamicRequestTree,\n nextUrl: state.nextUrl,\n })\n\n listenForDynamicRequest(task, dynamicRequest)\n // We store the dynamic request on the `lazyData` property of the CacheNode\n // because we're not going to await the dynamic request here. Since we're not blocking\n // on the dynamic request, `layout-router` will\n // task.node.lazyData = dynamicRequest\n } else {\n // The prefetched tree does not contain dynamic holes — it's\n // fully static. We can skip the dynamic request.\n }\n } else {\n // Nothing changed, so reuse the old cache.\n // TODO: What if the head changed but not any of the segment data?\n // Is that possible? If so, we should clone the whole tree and\n // update the head.\n newTree = treePatch\n }\n } else {\n // The static response does not include any dynamic holes, so\n // there's no need to do a second request.\n // TODO: As an incremental step this just reverts back to the\n // non-PPR implementation. We can simplify this branch further,\n // given that PPR prefetches are always static and return the whole\n // tree. Or in the meantime we could factor it out into a\n // separate function.\n\n if (isNavigatingToNewRootLayout(currentTree, newTree)) {\n return handleExternalUrl(state, mutable, href, pendingPush)\n }\n\n const cache: CacheNode = createEmptyCacheNode()\n let applied = false\n\n if (\n prefetchValues.status === PrefetchCacheEntryStatus.stale &&\n !isFirstRead\n ) {\n // 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\n // this will trigger a lazy fetch for the actual page data by nulling the `rsc` and `prefetchRsc` values for page data,\n // while copying over the `loading` for the segment that contains the page data.\n // We only do this on subsequent reads, as otherwise there'd be no loading data to re-use.\n\n // We skip this branch if only the hash fragment has changed, as we don't want to trigger a lazy fetch in that case\n applied = triggerLazyFetchForLeafSegments(\n cache,\n currentCache,\n flightSegmentPath,\n treePatch\n )\n // since we re-used the stale cache's loading state & refreshed the data,\n // update the `lastUsedTime` so that it can continue to be re-used for the next 30s\n prefetchValues.lastUsedTime = Date.now()\n } else {\n applied = applyFlightData(\n currentCache,\n cache,\n normalizedFlightData,\n prefetchValues\n )\n }\n\n const hardNavigate = shouldHardNavigate(\n // TODO-APP: remove ''\n flightSegmentPathWithLeadingEmpty,\n currentTree\n )\n\n if (hardNavigate) {\n // Copy rsc for the root node of the cache.\n cache.rsc = currentCache.rsc\n cache.prefetchRsc = currentCache.prefetchRsc\n\n invalidateCacheBelowFlightSegmentPath(\n cache,\n currentCache,\n flightSegmentPath\n )\n // Ensure the existing cache value is used when the cache was not invalidated.\n mutable.cache = cache\n } else if (applied) {\n mutable.cache = cache\n // If we applied the cache, we update the \"current cache\" value so any other\n // segments in the FlightDataPath will be able to reference the updated cache.\n currentCache = cache\n }\n\n for (const subSegment of generateSegmentsFromPatch(treePatch)) {\n const scrollableSegmentPath = [\n ...flightSegmentPath,\n ...subSegment,\n ]\n // Filter out the __DEFAULT__ paths as they shouldn't be scrolled to in this case.\n if (\n scrollableSegmentPath[scrollableSegmentPath.length - 1] !==\n DEFAULT_SEGMENT_KEY\n ) {\n scrollableSegments.push(scrollableSegmentPath)\n }\n }\n }\n\n currentTree = newTree\n }\n }\n\n mutable.patchedTree = currentTree\n mutable.canonicalUrl = updatedCanonicalUrl\n mutable.scrollableSegments = scrollableSegments\n mutable.hashFragment = hash\n mutable.shouldScroll = shouldScroll\n\n return handleMutable(state, mutable)\n },\n () => state\n )\n}\n"],"names":["handleExternalUrl","navigateReducer","state","mutable","url","pendingPush","mpaNavigation","canonicalUrl","scrollableSegments","undefined","handleMutable","generateSegmentsFromPatch","flightRouterPatch","segments","segment","parallelRoutes","Object","keys","length","parallelRouteKey","parallelRoute","entries","childSegment","push","triggerLazyFetchForLeafSegments","newCache","currentCache","flightSegmentPath","treePatch","appliedPatch","rsc","prefetchRsc","loading","Map","segmentPathsToFill","map","segmentPaths","clearCacheNodeDataForSegmentPath","handleNavigationResult","result","tag","NavigationResultTag","MPA","newUrl","data","NoOp","newCanonicalUrl","oldUrl","URL","onlyHashChange","pathname","search","hash","shouldScroll","hashFragment","Success","cache","cacheNode","patchedTree","flightRouterState","Async","then","asyncResult","action","isExternalUrl","navigateType","allowAliasing","href","createHrefFromUrl","prunePrefetchCache","prefetchCache","preserveCustomHistoryState","toString","document","getElementById","process","env","__NEXT_CLIENT_SEGMENT_CACHE","navigateUsingSegmentCache","tree","nextUrl","prefetchValues","getOrCreatePrefetchCacheEntry","treeAtTimeOfPrefetch","prefetchQueue","bump","flightData","canonicalUrlOverride","postponed","isFirstRead","lastUsedTime","Date","now","updatedCanonicalUrl","split","aliased","handleAliasedPrefetchEntry","currentTree","normalizedFlightData","pathToSegment","seedData","head","isHeadPartial","isRootRender","flightSegmentPathWithLeadingEmpty","newTree","applyRouterStatePatchToTree","task","startPPRNavigation","route","patchedRouterState","node","dynamicRequestTree","dynamicRequest","fetchServerResponse","listenForDynamicRequest","isNavigatingToNewRootLayout","createEmptyCacheNode","applied","status","PrefetchCacheEntryStatus","stale","applyFlightData","hardNavigate","shouldHardNavigate","invalidateCacheBelowFlightSegmentPath","subSegment","scrollableSegmentPath","DEFAULT_SEGMENT_KEY"],"mappings":"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"}
|
@@ -12,7 +12,10 @@ type MPANavigationResult = {
|
|
12
12
|
};
|
13
13
|
type NoOpNavigationResult = {
|
14
14
|
tag: NavigationResultTag.NoOp;
|
15
|
-
data:
|
15
|
+
data: {
|
16
|
+
canonicalUrl: string;
|
17
|
+
shouldScroll: boolean;
|
18
|
+
};
|
16
19
|
};
|
17
20
|
type SuccessfulNavigationResult = {
|
18
21
|
tag: NavigationResultTag.Success;
|
@@ -22,6 +25,7 @@ type SuccessfulNavigationResult = {
|
|
22
25
|
canonicalUrl: string;
|
23
26
|
scrollableSegments: Array<FlightSegmentPath>;
|
24
27
|
shouldScroll: boolean;
|
28
|
+
hash: string;
|
25
29
|
};
|
26
30
|
};
|
27
31
|
type AsyncNavigationResult = {
|
@@ -32,10 +32,6 @@ var NavigationResultTag = /*#__PURE__*/ function(NavigationResultTag) {
|
|
32
32
|
NavigationResultTag[NavigationResultTag["Async"] = 3] = "Async";
|
33
33
|
return NavigationResultTag;
|
34
34
|
}({});
|
35
|
-
const noOpNavigationResult = {
|
36
|
-
tag: 2,
|
37
|
-
data: null
|
38
|
-
};
|
39
35
|
function navigate(url, currentCacheNode, currentFlightRouterState, nextUrl, shouldScroll) {
|
40
36
|
const now = Date.now();
|
41
37
|
const cacheKey = (0, _cachekey.createCacheKey)(url.href, nextUrl);
|
@@ -47,16 +43,16 @@ function navigate(url, currentCacheNode, currentFlightRouterState, nextUrl, shou
|
|
47
43
|
const prefetchSeedData = snapshot.seedData;
|
48
44
|
const prefetchHead = route.head;
|
49
45
|
const isPrefetchHeadPartial = route.isHeadPartial;
|
50
|
-
const
|
51
|
-
return navigateUsingPrefetchedRouteTree(url, nextUrl, currentCacheNode, currentFlightRouterState, prefetchFlightRouterState, prefetchSeedData, prefetchHead, isPrefetchHeadPartial,
|
46
|
+
const newCanonicalUrl = route.canonicalUrl;
|
47
|
+
return navigateUsingPrefetchedRouteTree(url, nextUrl, currentCacheNode, currentFlightRouterState, prefetchFlightRouterState, prefetchSeedData, prefetchHead, isPrefetchHeadPartial, newCanonicalUrl, shouldScroll, url.hash);
|
52
48
|
}
|
53
49
|
// There's no matching prefetch for this route in the cache.
|
54
50
|
return {
|
55
51
|
tag: 3,
|
56
|
-
data: navigateDynamicallyWithNoPrefetch(url, nextUrl, currentCacheNode, currentFlightRouterState, shouldScroll)
|
52
|
+
data: navigateDynamicallyWithNoPrefetch(url, nextUrl, currentCacheNode, currentFlightRouterState, shouldScroll, url.hash)
|
57
53
|
};
|
58
54
|
}
|
59
|
-
function navigateUsingPrefetchedRouteTree(url, nextUrl, currentCacheNode, currentFlightRouterState, prefetchFlightRouterState, prefetchSeedData, prefetchHead, isPrefetchHeadPartial, canonicalUrl, shouldScroll) {
|
55
|
+
function navigateUsingPrefetchedRouteTree(url, nextUrl, currentCacheNode, currentFlightRouterState, prefetchFlightRouterState, prefetchSeedData, prefetchHead, isPrefetchHeadPartial, canonicalUrl, shouldScroll, hash) {
|
60
56
|
// Recursively construct a prefetch tree by reading from the Segment Cache. To
|
61
57
|
// maintain compatibility, we output the same data structures as the old
|
62
58
|
// prefetching implementation: FlightRouterState and CacheNodeSeedData.
|
@@ -77,12 +73,19 @@ function navigateUsingPrefetchedRouteTree(url, nextUrl, currentCacheNode, curren
|
|
77
73
|
// The prefetched tree does not contain dynamic holes — it's
|
78
74
|
// fully static. We can skip the dynamic request.
|
79
75
|
}
|
80
|
-
return navigationTaskToResult(task, currentCacheNode, canonicalUrl, scrollableSegments, shouldScroll);
|
76
|
+
return navigationTaskToResult(task, currentCacheNode, canonicalUrl, scrollableSegments, shouldScroll, hash);
|
81
77
|
}
|
82
|
-
// The server sent back an empty tree patch. There's nothing to update
|
83
|
-
|
78
|
+
// The server sent back an empty tree patch. There's nothing to update, except
|
79
|
+
// possibly the URL.
|
80
|
+
return {
|
81
|
+
tag: 2,
|
82
|
+
data: {
|
83
|
+
canonicalUrl,
|
84
|
+
shouldScroll
|
85
|
+
}
|
86
|
+
};
|
84
87
|
}
|
85
|
-
function navigationTaskToResult(task, currentCacheNode, canonicalUrl, scrollableSegments, shouldScroll) {
|
88
|
+
function navigationTaskToResult(task, currentCacheNode, canonicalUrl, scrollableSegments, shouldScroll, hash) {
|
86
89
|
const flightRouterState = task.route;
|
87
90
|
if (flightRouterState === null) {
|
88
91
|
// When no router state is provided, it signals that we should perform an
|
@@ -100,7 +103,8 @@ function navigationTaskToResult(task, currentCacheNode, canonicalUrl, scrollable
|
|
100
103
|
cacheNode: newCacheNode !== null ? newCacheNode : currentCacheNode,
|
101
104
|
canonicalUrl,
|
102
105
|
scrollableSegments,
|
103
|
-
shouldScroll
|
106
|
+
shouldScroll,
|
107
|
+
hash
|
104
108
|
}
|
105
109
|
};
|
106
110
|
}
|
@@ -168,7 +172,7 @@ function readRenderSnapshotFromCache(now, tree) {
|
|
168
172
|
]
|
169
173
|
};
|
170
174
|
}
|
171
|
-
async function navigateDynamicallyWithNoPrefetch(url, nextUrl, currentCacheNode, currentFlightRouterState, shouldScroll) {
|
175
|
+
async function navigateDynamicallyWithNoPrefetch(url, nextUrl, currentCacheNode, currentFlightRouterState, shouldScroll, hash) {
|
172
176
|
// Runs when a navigation happens but there's no cached prefetch we can use.
|
173
177
|
// Don't bother to wait for a prefetch response; go straight to a full
|
174
178
|
// navigation that contains both static and dynamic data in a single stream.
|
@@ -185,8 +189,6 @@ async function navigateDynamicallyWithNoPrefetch(url, nextUrl, currentCacheNode,
|
|
185
189
|
nextUrl
|
186
190
|
});
|
187
191
|
const { flightData, canonicalUrl: canonicalUrlOverride } = await promiseForDynamicServerResponse;
|
188
|
-
// TODO: Detect if the only thing that changed was the hash, like we do in
|
189
|
-
// in navigateReducer
|
190
192
|
if (typeof flightData === 'string') {
|
191
193
|
// This is an MPA navigation.
|
192
194
|
const newUrl = flightData;
|
@@ -224,10 +226,17 @@ async function navigateDynamicallyWithNoPrefetch(url, nextUrl, currentCacheNode,
|
|
224
226
|
// The prefetched tree does not contain dynamic holes — it's
|
225
227
|
// fully static. We don't need to process the server response further.
|
226
228
|
}
|
227
|
-
return navigationTaskToResult(task, currentCacheNode, canonicalUrl, scrollableSegments, shouldScroll);
|
229
|
+
return navigationTaskToResult(task, currentCacheNode, canonicalUrl, scrollableSegments, shouldScroll, hash);
|
228
230
|
}
|
229
|
-
// The server sent back an empty tree patch. There's nothing to update
|
230
|
-
|
231
|
+
// The server sent back an empty tree patch. There's nothing to update, except
|
232
|
+
// possibly the URL.
|
233
|
+
return {
|
234
|
+
tag: 2,
|
235
|
+
data: {
|
236
|
+
canonicalUrl,
|
237
|
+
shouldScroll
|
238
|
+
}
|
239
|
+
};
|
231
240
|
}
|
232
241
|
function simulatePrefetchTreeUsingDynamicTreePatch(currentTree, flightData) {
|
233
242
|
// Takes the current FlightRouterState and applies the router state patch
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../../src/client/components/segment-cache/navigation.ts"],"sourcesContent":["import type {\n CacheNodeSeedData,\n FlightRouterState,\n FlightSegmentPath,\n} from '../../../server/app-render/types'\nimport type {\n CacheNode,\n HeadData,\n LoadingModuleData,\n} from '../../../shared/lib/app-router-context.shared-runtime'\nimport type { NormalizedFlightData } from '../../flight-data-helpers'\nimport { fetchServerResponse } from '../router-reducer/fetch-server-response'\nimport {\n startPPRNavigation,\n listenForDynamicRequest,\n type Task as PPRNavigationTask,\n} from '../router-reducer/ppr-navigations'\nimport { createHrefFromUrl as createCanonicalUrl } from '../router-reducer/create-href-from-url'\nimport {\n EntryStatus,\n readRouteCacheEntry,\n readSegmentCacheEntry,\n waitForSegmentCacheEntry,\n type RouteTree,\n} from './cache'\nimport { createCacheKey } from './cache-key'\n\nexport const enum NavigationResultTag {\n MPA,\n Success,\n NoOp,\n Async,\n}\n\ntype MPANavigationResult = {\n tag: NavigationResultTag.MPA\n data: string\n}\n\ntype NoOpNavigationResult = {\n tag: NavigationResultTag.NoOp\n data: null\n}\n\ntype SuccessfulNavigationResult = {\n tag: NavigationResultTag.Success\n data: {\n flightRouterState: FlightRouterState\n cacheNode: CacheNode\n canonicalUrl: string\n scrollableSegments: Array<FlightSegmentPath>\n shouldScroll: boolean\n }\n}\n\ntype AsyncNavigationResult = {\n tag: NavigationResultTag.Async\n data: Promise<\n MPANavigationResult | NoOpNavigationResult | SuccessfulNavigationResult\n >\n}\n\nexport type NavigationResult =\n | MPANavigationResult\n | SuccessfulNavigationResult\n | NoOpNavigationResult\n | AsyncNavigationResult\n\nconst noOpNavigationResult: NoOpNavigationResult = {\n tag: NavigationResultTag.NoOp,\n data: null,\n}\n\n/**\n * Navigate to a new URL, using the Segment Cache to construct a response.\n *\n * To allow for synchronous navigations whenever possible, this is not an async\n * function. It returns a promise only if there's no matching prefetch in\n * the cache. Otherwise it returns an immediate result and uses Suspense/RSC to\n * stream in any missing data.\n */\nexport function navigate(\n url: URL,\n currentCacheNode: CacheNode,\n currentFlightRouterState: FlightRouterState,\n nextUrl: string | null,\n shouldScroll: boolean\n): NavigationResult {\n const now = Date.now()\n\n const cacheKey = createCacheKey(url.href, nextUrl)\n const route = readRouteCacheEntry(now, cacheKey)\n if (route !== null && route.status === EntryStatus.Fulfilled) {\n // We have a matching prefetch.\n const snapshot = readRenderSnapshotFromCache(now, route.tree)\n const prefetchFlightRouterState = snapshot.flightRouterState\n const prefetchSeedData = snapshot.seedData\n const prefetchHead = route.head\n const isPrefetchHeadPartial = route.isHeadPartial\n const canonicalUrl = route.canonicalUrl\n return navigateUsingPrefetchedRouteTree(\n url,\n nextUrl,\n currentCacheNode,\n currentFlightRouterState,\n prefetchFlightRouterState,\n prefetchSeedData,\n prefetchHead,\n isPrefetchHeadPartial,\n canonicalUrl,\n shouldScroll\n )\n }\n // There's no matching prefetch for this route in the cache.\n return {\n tag: NavigationResultTag.Async,\n data: navigateDynamicallyWithNoPrefetch(\n url,\n nextUrl,\n currentCacheNode,\n currentFlightRouterState,\n shouldScroll\n ),\n }\n}\n\nfunction navigateUsingPrefetchedRouteTree(\n url: URL,\n nextUrl: string | null,\n currentCacheNode: CacheNode,\n currentFlightRouterState: FlightRouterState,\n prefetchFlightRouterState: FlightRouterState,\n prefetchSeedData: CacheNodeSeedData | null,\n prefetchHead: HeadData | null,\n isPrefetchHeadPartial: boolean,\n canonicalUrl: string,\n shouldScroll: boolean\n): SuccessfulNavigationResult | NoOpNavigationResult | MPANavigationResult {\n // Recursively construct a prefetch tree by reading from the Segment Cache. To\n // maintain compatibility, we output the same data structures as the old\n // prefetching implementation: FlightRouterState and CacheNodeSeedData.\n // TODO: Eventually updateCacheNodeOnNavigation (or the equivalent) should\n // read from the Segment Cache directly. It's only structured this way for now\n // so we can share code with the old prefetching implementation.\n const scrollableSegments: Array<FlightSegmentPath> = []\n const task = startPPRNavigation(\n currentCacheNode,\n currentFlightRouterState,\n prefetchFlightRouterState,\n prefetchSeedData,\n prefetchHead,\n isPrefetchHeadPartial,\n scrollableSegments\n )\n if (task !== null) {\n const dynamicRequestTree = task.dynamicRequestTree\n if (dynamicRequestTree !== null) {\n const promiseForDynamicServerResponse = fetchServerResponse(url, {\n flightRouterState: dynamicRequestTree,\n nextUrl,\n })\n listenForDynamicRequest(task, promiseForDynamicServerResponse)\n } else {\n // The prefetched tree does not contain dynamic holes — it's\n // fully static. We can skip the dynamic request.\n }\n return navigationTaskToResult(\n task,\n currentCacheNode,\n canonicalUrl,\n scrollableSegments,\n shouldScroll\n )\n }\n // The server sent back an empty tree patch. There's nothing to update.\n return noOpNavigationResult\n}\n\nfunction navigationTaskToResult(\n task: PPRNavigationTask,\n currentCacheNode: CacheNode,\n canonicalUrl: string,\n scrollableSegments: Array<FlightSegmentPath>,\n shouldScroll: boolean\n): SuccessfulNavigationResult | MPANavigationResult {\n const flightRouterState = task.route\n if (flightRouterState === null) {\n // When no router state is provided, it signals that we should perform an\n // MPA navigation.\n return {\n tag: NavigationResultTag.MPA,\n data: canonicalUrl,\n }\n }\n const newCacheNode = task.node\n return {\n tag: NavigationResultTag.Success,\n data: {\n flightRouterState,\n cacheNode: newCacheNode !== null ? newCacheNode : currentCacheNode,\n canonicalUrl,\n scrollableSegments,\n shouldScroll,\n },\n }\n}\n\nfunction readRenderSnapshotFromCache(\n now: number,\n tree: RouteTree\n): { flightRouterState: FlightRouterState; seedData: CacheNodeSeedData } {\n let childRouterStates: { [parallelRouteKey: string]: FlightRouterState } = {}\n let childSeedDatas: {\n [parallelRouteKey: string]: CacheNodeSeedData | null\n } = {}\n const slots = tree.slots\n if (slots !== null) {\n for (const parallelRouteKey in slots) {\n const childTree = slots[parallelRouteKey]\n const childResult = readRenderSnapshotFromCache(now, childTree)\n childRouterStates[parallelRouteKey] = childResult.flightRouterState\n childSeedDatas[parallelRouteKey] = childResult.seedData\n }\n }\n\n let rsc: React.ReactNode | null = null\n let loading: LoadingModuleData | Promise<LoadingModuleData> = null\n let isPartial: boolean = true\n\n const segmentEntry = readSegmentCacheEntry(now, tree.key)\n if (segmentEntry !== null) {\n switch (segmentEntry.status) {\n case EntryStatus.Fulfilled: {\n // Happy path: a cache hit\n rsc = segmentEntry.rsc\n loading = segmentEntry.loading\n isPartial = segmentEntry.isPartial\n break\n }\n case EntryStatus.Pending: {\n // We haven't received data for this segment yet, but there's already\n // an in-progress request. Since it's extremely likely to arrive\n // before the dynamic data response, we might as well use it.\n const promiseForFulfilledEntry = waitForSegmentCacheEntry(segmentEntry)\n rsc = promiseForFulfilledEntry.then((entry) =>\n entry !== null ? entry.rsc : null\n )\n loading = promiseForFulfilledEntry.then((entry) =>\n entry !== null ? entry.loading : null\n )\n // Since we don't know yet whether the segment is partial or fully\n // static, we must assume it's partial; we can't skip the\n // dynamic request.\n isPartial = true\n break\n }\n case EntryStatus.Empty:\n case EntryStatus.Rejected:\n break\n default:\n segmentEntry satisfies never\n }\n }\n\n return {\n flightRouterState: [\n tree.segment,\n childRouterStates,\n null,\n null,\n tree.isRootLayout,\n ],\n seedData: [tree.segment, rsc, childSeedDatas, loading, isPartial],\n }\n}\n\nasync function navigateDynamicallyWithNoPrefetch(\n url: URL,\n nextUrl: string | null,\n currentCacheNode: CacheNode,\n currentFlightRouterState: FlightRouterState,\n shouldScroll: boolean\n): Promise<\n MPANavigationResult | SuccessfulNavigationResult | NoOpNavigationResult\n> {\n // Runs when a navigation happens but there's no cached prefetch we can use.\n // Don't bother to wait for a prefetch response; go straight to a full\n // navigation that contains both static and dynamic data in a single stream.\n // (This is unlike the old navigation implementation, which instead blocks\n // the dynamic request until a prefetch request is received.)\n //\n // To avoid duplication of logic, we're going to pretend that the tree\n // returned by the dynamic request is, in fact, a prefetch tree. Then we can\n // use the same server response to write the actual data into the CacheNode\n // tree. So it's the same flow as the \"happy path\" (prefetch, then\n // navigation), except we use a single server response for both stages.\n\n const promiseForDynamicServerResponse = fetchServerResponse(url, {\n flightRouterState: currentFlightRouterState,\n nextUrl,\n })\n const { flightData, canonicalUrl: canonicalUrlOverride } =\n await promiseForDynamicServerResponse\n\n // TODO: Detect if the only thing that changed was the hash, like we do in\n // in navigateReducer\n\n if (typeof flightData === 'string') {\n // This is an MPA navigation.\n const newUrl = flightData\n return {\n tag: NavigationResultTag.MPA,\n data: newUrl,\n }\n }\n\n // Since the response format of dynamic requests and prefetches is slightly\n // different, we'll need to massage the data a bit. Create FlightRouterState\n // tree that simulates what we'd receive as the result of a prefetch.\n const prefetchFlightRouterState = simulatePrefetchTreeUsingDynamicTreePatch(\n currentFlightRouterState,\n flightData\n )\n\n // In our simulated prefetch payload, we pretend that there's no seed data\n // nor a prefetch head.\n const prefetchSeedData = null\n const prefetchHead = null\n const isPrefetchHeadPartial = true\n\n const canonicalUrl = createCanonicalUrl(\n canonicalUrlOverride ? canonicalUrlOverride : url\n )\n\n // Now we proceed exactly as we would for normal navigation.\n const scrollableSegments: Array<FlightSegmentPath> = []\n const task = startPPRNavigation(\n currentCacheNode,\n currentFlightRouterState,\n prefetchFlightRouterState,\n prefetchSeedData,\n prefetchHead,\n isPrefetchHeadPartial,\n scrollableSegments\n )\n if (task !== null) {\n // In this case, we've already sent the dynamic request, so we don't\n // actually use the request tree created by `startPPRNavigation`,\n // except to check if it contains dynamic holes.\n //\n // This is almost always true, but it could be false if all the segment data\n // was present in the cache, but the route tree was not. E.g. navigating\n // to a URL that was not prefetched but rewrites to a different URL\n // that was.\n const hasDynamicHoles = task.dynamicRequestTree !== null\n if (hasDynamicHoles) {\n listenForDynamicRequest(task, promiseForDynamicServerResponse)\n } else {\n // The prefetched tree does not contain dynamic holes — it's\n // fully static. We don't need to process the server response further.\n }\n return navigationTaskToResult(\n task,\n currentCacheNode,\n canonicalUrl,\n scrollableSegments,\n shouldScroll\n )\n }\n // The server sent back an empty tree patch. There's nothing to update.\n return noOpNavigationResult\n}\n\nfunction simulatePrefetchTreeUsingDynamicTreePatch(\n currentTree: FlightRouterState,\n flightData: Array<NormalizedFlightData>\n): FlightRouterState {\n // Takes the current FlightRouterState and applies the router state patch\n // received from the server, to create a full FlightRouterState tree that we\n // can pretend was returned by a prefetch.\n //\n // (It sounds similar to what applyRouterStatePatch does, but it doesn't need\n // to handle stuff like interception routes or diffing since that will be\n // handled later.)\n let baseTree = currentTree\n for (const { segmentPath, tree: treePatch } of flightData) {\n // If the server sends us multiple tree patches, we only need to clone the\n // base tree when applying the first patch. After the first patch, we can\n // apply the remaining patches in place without copying.\n const canMutateInPlace = baseTree !== currentTree\n baseTree = simulatePrefetchTreeUsingDynamicTreePatchImpl(\n baseTree,\n treePatch,\n segmentPath,\n canMutateInPlace,\n 0\n )\n }\n\n return baseTree\n}\n\nfunction simulatePrefetchTreeUsingDynamicTreePatchImpl(\n baseRouterState: FlightRouterState,\n patch: FlightRouterState,\n segmentPath: FlightSegmentPath,\n canMutateInPlace: boolean,\n index: number\n) {\n if (index === segmentPath.length) {\n // We reached the part of the tree that we need to patch.\n return patch\n }\n\n // segmentPath represents the parent path of subtree. It's a repeating\n // pattern of parallel route key and segment:\n //\n // [string, Segment, string, Segment, string, Segment, ...]\n //\n // This path tells us which part of the base tree to apply the tree patch.\n //\n // NOTE: In the case of a fully dynamic request with no prefetch, we receive\n // the FlightRouterState patch in the same request as the dynamic data.\n // Therefore we don't need to worry about diffing the segment values; we can\n // assume the server sent us a correct result.\n const updatedParallelRouteKey: string = segmentPath[index]\n // const segment: Segment = segmentPath[index + 1] <-- Not used, see note above\n\n const baseChildren = baseRouterState[1]\n const newChildren: { [parallelRouteKey: string]: FlightRouterState } = {}\n for (const parallelRouteKey in baseChildren) {\n if (parallelRouteKey === updatedParallelRouteKey) {\n const childBaseRouterState = baseChildren[parallelRouteKey]\n newChildren[parallelRouteKey] =\n simulatePrefetchTreeUsingDynamicTreePatchImpl(\n childBaseRouterState,\n patch,\n segmentPath,\n canMutateInPlace,\n // Advance the index by two and keep cloning until we reach\n // the end of the segment path.\n index + 2\n )\n } else {\n // This child is not being patched. Copy it over as-is.\n newChildren[parallelRouteKey] = baseChildren[parallelRouteKey]\n }\n }\n\n if (canMutateInPlace) {\n // We can mutate the base tree in place, because the base tree is already\n // a clone.\n baseRouterState[1] = newChildren\n return baseRouterState\n }\n\n // Clone all the fields except the children.\n //\n // Based on equivalent logic in apply-router-state-patch-to-tree, but should\n // confirm whether we need to copy all of these fields. Not sure the server\n // ever sends, e.g. the refetch marker.\n const clone: FlightRouterState = [baseRouterState[0], newChildren]\n if (2 in baseRouterState) {\n clone[2] = baseRouterState[2]\n }\n if (3 in baseRouterState) {\n clone[3] = baseRouterState[3]\n }\n if (4 in baseRouterState) {\n clone[4] = baseRouterState[4]\n }\n return clone\n}\n"],"names":["NavigationResultTag","navigate","noOpNavigationResult","tag","data","url","currentCacheNode","currentFlightRouterState","nextUrl","shouldScroll","now","Date","cacheKey","createCacheKey","href","route","readRouteCacheEntry","status","EntryStatus","Fulfilled","snapshot","readRenderSnapshotFromCache","tree","prefetchFlightRouterState","flightRouterState","prefetchSeedData","seedData","prefetchHead","head","isPrefetchHeadPartial","isHeadPartial","canonicalUrl","navigateUsingPrefetchedRouteTree","navigateDynamicallyWithNoPrefetch","scrollableSegments","task","startPPRNavigation","dynamicRequestTree","promiseForDynamicServerResponse","fetchServerResponse","listenForDynamicRequest","navigationTaskToResult","newCacheNode","node","cacheNode","childRouterStates","childSeedDatas","slots","parallelRouteKey","childTree","childResult","rsc","loading","isPartial","segmentEntry","readSegmentCacheEntry","key","Pending","promiseForFulfilledEntry","waitForSegmentCacheEntry","then","entry","Empty","Rejected","segment","isRootLayout","flightData","canonicalUrlOverride","newUrl","simulatePrefetchTreeUsingDynamicTreePatch","createCanonicalUrl","hasDynamicHoles","currentTree","baseTree","segmentPath","treePatch","canMutateInPlace","simulatePrefetchTreeUsingDynamicTreePatchImpl","baseRouterState","patch","index","length","updatedParallelRouteKey","baseChildren","newChildren","childBaseRouterState","clone"],"mappings":"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"}
|
1
|
+
{"version":3,"sources":["../../../../src/client/components/segment-cache/navigation.ts"],"sourcesContent":["import type {\n CacheNodeSeedData,\n FlightRouterState,\n FlightSegmentPath,\n} from '../../../server/app-render/types'\nimport type {\n CacheNode,\n HeadData,\n LoadingModuleData,\n} from '../../../shared/lib/app-router-context.shared-runtime'\nimport type { NormalizedFlightData } from '../../flight-data-helpers'\nimport { fetchServerResponse } from '../router-reducer/fetch-server-response'\nimport {\n startPPRNavigation,\n listenForDynamicRequest,\n type Task as PPRNavigationTask,\n} from '../router-reducer/ppr-navigations'\nimport { createHrefFromUrl as createCanonicalUrl } from '../router-reducer/create-href-from-url'\nimport {\n EntryStatus,\n readRouteCacheEntry,\n readSegmentCacheEntry,\n waitForSegmentCacheEntry,\n type RouteTree,\n} from './cache'\nimport { createCacheKey } from './cache-key'\n\nexport const enum NavigationResultTag {\n MPA,\n Success,\n NoOp,\n Async,\n}\n\ntype MPANavigationResult = {\n tag: NavigationResultTag.MPA\n data: string\n}\n\ntype NoOpNavigationResult = {\n tag: NavigationResultTag.NoOp\n data: {\n canonicalUrl: string\n shouldScroll: boolean\n }\n}\n\ntype SuccessfulNavigationResult = {\n tag: NavigationResultTag.Success\n data: {\n flightRouterState: FlightRouterState\n cacheNode: CacheNode\n canonicalUrl: string\n scrollableSegments: Array<FlightSegmentPath>\n shouldScroll: boolean\n hash: string\n }\n}\n\ntype AsyncNavigationResult = {\n tag: NavigationResultTag.Async\n data: Promise<\n MPANavigationResult | NoOpNavigationResult | SuccessfulNavigationResult\n >\n}\n\nexport type NavigationResult =\n | MPANavigationResult\n | SuccessfulNavigationResult\n | NoOpNavigationResult\n | AsyncNavigationResult\n\n/**\n * Navigate to a new URL, using the Segment Cache to construct a response.\n *\n * To allow for synchronous navigations whenever possible, this is not an async\n * function. It returns a promise only if there's no matching prefetch in\n * the cache. Otherwise it returns an immediate result and uses Suspense/RSC to\n * stream in any missing data.\n */\nexport function navigate(\n url: URL,\n currentCacheNode: CacheNode,\n currentFlightRouterState: FlightRouterState,\n nextUrl: string | null,\n shouldScroll: boolean\n): NavigationResult {\n const now = Date.now()\n\n const cacheKey = createCacheKey(url.href, nextUrl)\n const route = readRouteCacheEntry(now, cacheKey)\n if (route !== null && route.status === EntryStatus.Fulfilled) {\n // We have a matching prefetch.\n const snapshot = readRenderSnapshotFromCache(now, route.tree)\n const prefetchFlightRouterState = snapshot.flightRouterState\n const prefetchSeedData = snapshot.seedData\n const prefetchHead = route.head\n const isPrefetchHeadPartial = route.isHeadPartial\n const newCanonicalUrl = route.canonicalUrl\n return navigateUsingPrefetchedRouteTree(\n url,\n nextUrl,\n currentCacheNode,\n currentFlightRouterState,\n prefetchFlightRouterState,\n prefetchSeedData,\n prefetchHead,\n isPrefetchHeadPartial,\n newCanonicalUrl,\n shouldScroll,\n url.hash\n )\n }\n // There's no matching prefetch for this route in the cache.\n return {\n tag: NavigationResultTag.Async,\n data: navigateDynamicallyWithNoPrefetch(\n url,\n nextUrl,\n currentCacheNode,\n currentFlightRouterState,\n shouldScroll,\n url.hash\n ),\n }\n}\n\nfunction navigateUsingPrefetchedRouteTree(\n url: URL,\n nextUrl: string | null,\n currentCacheNode: CacheNode,\n currentFlightRouterState: FlightRouterState,\n prefetchFlightRouterState: FlightRouterState,\n prefetchSeedData: CacheNodeSeedData | null,\n prefetchHead: HeadData | null,\n isPrefetchHeadPartial: boolean,\n canonicalUrl: string,\n shouldScroll: boolean,\n hash: string\n): SuccessfulNavigationResult | NoOpNavigationResult | MPANavigationResult {\n // Recursively construct a prefetch tree by reading from the Segment Cache. To\n // maintain compatibility, we output the same data structures as the old\n // prefetching implementation: FlightRouterState and CacheNodeSeedData.\n // TODO: Eventually updateCacheNodeOnNavigation (or the equivalent) should\n // read from the Segment Cache directly. It's only structured this way for now\n // so we can share code with the old prefetching implementation.\n const scrollableSegments: Array<FlightSegmentPath> = []\n const task = startPPRNavigation(\n currentCacheNode,\n currentFlightRouterState,\n prefetchFlightRouterState,\n prefetchSeedData,\n prefetchHead,\n isPrefetchHeadPartial,\n scrollableSegments\n )\n if (task !== null) {\n const dynamicRequestTree = task.dynamicRequestTree\n if (dynamicRequestTree !== null) {\n const promiseForDynamicServerResponse = fetchServerResponse(url, {\n flightRouterState: dynamicRequestTree,\n nextUrl,\n })\n listenForDynamicRequest(task, promiseForDynamicServerResponse)\n } else {\n // The prefetched tree does not contain dynamic holes — it's\n // fully static. We can skip the dynamic request.\n }\n return navigationTaskToResult(\n task,\n currentCacheNode,\n canonicalUrl,\n scrollableSegments,\n shouldScroll,\n hash\n )\n }\n // The server sent back an empty tree patch. There's nothing to update, except\n // possibly the URL.\n return {\n tag: NavigationResultTag.NoOp,\n data: {\n canonicalUrl,\n shouldScroll,\n },\n }\n}\n\nfunction navigationTaskToResult(\n task: PPRNavigationTask,\n currentCacheNode: CacheNode,\n canonicalUrl: string,\n scrollableSegments: Array<FlightSegmentPath>,\n shouldScroll: boolean,\n hash: string\n): SuccessfulNavigationResult | MPANavigationResult {\n const flightRouterState = task.route\n if (flightRouterState === null) {\n // When no router state is provided, it signals that we should perform an\n // MPA navigation.\n return {\n tag: NavigationResultTag.MPA,\n data: canonicalUrl,\n }\n }\n const newCacheNode = task.node\n return {\n tag: NavigationResultTag.Success,\n data: {\n flightRouterState,\n cacheNode: newCacheNode !== null ? newCacheNode : currentCacheNode,\n canonicalUrl,\n scrollableSegments,\n shouldScroll,\n hash,\n },\n }\n}\n\nfunction readRenderSnapshotFromCache(\n now: number,\n tree: RouteTree\n): { flightRouterState: FlightRouterState; seedData: CacheNodeSeedData } {\n let childRouterStates: { [parallelRouteKey: string]: FlightRouterState } = {}\n let childSeedDatas: {\n [parallelRouteKey: string]: CacheNodeSeedData | null\n } = {}\n const slots = tree.slots\n if (slots !== null) {\n for (const parallelRouteKey in slots) {\n const childTree = slots[parallelRouteKey]\n const childResult = readRenderSnapshotFromCache(now, childTree)\n childRouterStates[parallelRouteKey] = childResult.flightRouterState\n childSeedDatas[parallelRouteKey] = childResult.seedData\n }\n }\n\n let rsc: React.ReactNode | null = null\n let loading: LoadingModuleData | Promise<LoadingModuleData> = null\n let isPartial: boolean = true\n\n const segmentEntry = readSegmentCacheEntry(now, tree.key)\n if (segmentEntry !== null) {\n switch (segmentEntry.status) {\n case EntryStatus.Fulfilled: {\n // Happy path: a cache hit\n rsc = segmentEntry.rsc\n loading = segmentEntry.loading\n isPartial = segmentEntry.isPartial\n break\n }\n case EntryStatus.Pending: {\n // We haven't received data for this segment yet, but there's already\n // an in-progress request. Since it's extremely likely to arrive\n // before the dynamic data response, we might as well use it.\n const promiseForFulfilledEntry = waitForSegmentCacheEntry(segmentEntry)\n rsc = promiseForFulfilledEntry.then((entry) =>\n entry !== null ? entry.rsc : null\n )\n loading = promiseForFulfilledEntry.then((entry) =>\n entry !== null ? entry.loading : null\n )\n // Since we don't know yet whether the segment is partial or fully\n // static, we must assume it's partial; we can't skip the\n // dynamic request.\n isPartial = true\n break\n }\n case EntryStatus.Empty:\n case EntryStatus.Rejected:\n break\n default:\n segmentEntry satisfies never\n }\n }\n\n return {\n flightRouterState: [\n tree.segment,\n childRouterStates,\n null,\n null,\n tree.isRootLayout,\n ],\n seedData: [tree.segment, rsc, childSeedDatas, loading, isPartial],\n }\n}\n\nasync function navigateDynamicallyWithNoPrefetch(\n url: URL,\n nextUrl: string | null,\n currentCacheNode: CacheNode,\n currentFlightRouterState: FlightRouterState,\n shouldScroll: boolean,\n hash: string\n): Promise<\n MPANavigationResult | SuccessfulNavigationResult | NoOpNavigationResult\n> {\n // Runs when a navigation happens but there's no cached prefetch we can use.\n // Don't bother to wait for a prefetch response; go straight to a full\n // navigation that contains both static and dynamic data in a single stream.\n // (This is unlike the old navigation implementation, which instead blocks\n // the dynamic request until a prefetch request is received.)\n //\n // To avoid duplication of logic, we're going to pretend that the tree\n // returned by the dynamic request is, in fact, a prefetch tree. Then we can\n // use the same server response to write the actual data into the CacheNode\n // tree. So it's the same flow as the \"happy path\" (prefetch, then\n // navigation), except we use a single server response for both stages.\n\n const promiseForDynamicServerResponse = fetchServerResponse(url, {\n flightRouterState: currentFlightRouterState,\n nextUrl,\n })\n const { flightData, canonicalUrl: canonicalUrlOverride } =\n await promiseForDynamicServerResponse\n\n if (typeof flightData === 'string') {\n // This is an MPA navigation.\n const newUrl = flightData\n return {\n tag: NavigationResultTag.MPA,\n data: newUrl,\n }\n }\n\n // Since the response format of dynamic requests and prefetches is slightly\n // different, we'll need to massage the data a bit. Create FlightRouterState\n // tree that simulates what we'd receive as the result of a prefetch.\n const prefetchFlightRouterState = simulatePrefetchTreeUsingDynamicTreePatch(\n currentFlightRouterState,\n flightData\n )\n\n // In our simulated prefetch payload, we pretend that there's no seed data\n // nor a prefetch head.\n const prefetchSeedData = null\n const prefetchHead = null\n const isPrefetchHeadPartial = true\n\n const canonicalUrl = createCanonicalUrl(\n canonicalUrlOverride ? canonicalUrlOverride : url\n )\n\n // Now we proceed exactly as we would for normal navigation.\n const scrollableSegments: Array<FlightSegmentPath> = []\n const task = startPPRNavigation(\n currentCacheNode,\n currentFlightRouterState,\n prefetchFlightRouterState,\n prefetchSeedData,\n prefetchHead,\n isPrefetchHeadPartial,\n scrollableSegments\n )\n if (task !== null) {\n // In this case, we've already sent the dynamic request, so we don't\n // actually use the request tree created by `startPPRNavigation`,\n // except to check if it contains dynamic holes.\n //\n // This is almost always true, but it could be false if all the segment data\n // was present in the cache, but the route tree was not. E.g. navigating\n // to a URL that was not prefetched but rewrites to a different URL\n // that was.\n const hasDynamicHoles = task.dynamicRequestTree !== null\n if (hasDynamicHoles) {\n listenForDynamicRequest(task, promiseForDynamicServerResponse)\n } else {\n // The prefetched tree does not contain dynamic holes — it's\n // fully static. We don't need to process the server response further.\n }\n return navigationTaskToResult(\n task,\n currentCacheNode,\n canonicalUrl,\n scrollableSegments,\n shouldScroll,\n hash\n )\n }\n // The server sent back an empty tree patch. There's nothing to update, except\n // possibly the URL.\n return {\n tag: NavigationResultTag.NoOp,\n data: {\n canonicalUrl,\n shouldScroll,\n },\n }\n}\n\nfunction simulatePrefetchTreeUsingDynamicTreePatch(\n currentTree: FlightRouterState,\n flightData: Array<NormalizedFlightData>\n): FlightRouterState {\n // Takes the current FlightRouterState and applies the router state patch\n // received from the server, to create a full FlightRouterState tree that we\n // can pretend was returned by a prefetch.\n //\n // (It sounds similar to what applyRouterStatePatch does, but it doesn't need\n // to handle stuff like interception routes or diffing since that will be\n // handled later.)\n let baseTree = currentTree\n for (const { segmentPath, tree: treePatch } of flightData) {\n // If the server sends us multiple tree patches, we only need to clone the\n // base tree when applying the first patch. After the first patch, we can\n // apply the remaining patches in place without copying.\n const canMutateInPlace = baseTree !== currentTree\n baseTree = simulatePrefetchTreeUsingDynamicTreePatchImpl(\n baseTree,\n treePatch,\n segmentPath,\n canMutateInPlace,\n 0\n )\n }\n\n return baseTree\n}\n\nfunction simulatePrefetchTreeUsingDynamicTreePatchImpl(\n baseRouterState: FlightRouterState,\n patch: FlightRouterState,\n segmentPath: FlightSegmentPath,\n canMutateInPlace: boolean,\n index: number\n) {\n if (index === segmentPath.length) {\n // We reached the part of the tree that we need to patch.\n return patch\n }\n\n // segmentPath represents the parent path of subtree. It's a repeating\n // pattern of parallel route key and segment:\n //\n // [string, Segment, string, Segment, string, Segment, ...]\n //\n // This path tells us which part of the base tree to apply the tree patch.\n //\n // NOTE: In the case of a fully dynamic request with no prefetch, we receive\n // the FlightRouterState patch in the same request as the dynamic data.\n // Therefore we don't need to worry about diffing the segment values; we can\n // assume the server sent us a correct result.\n const updatedParallelRouteKey: string = segmentPath[index]\n // const segment: Segment = segmentPath[index + 1] <-- Not used, see note above\n\n const baseChildren = baseRouterState[1]\n const newChildren: { [parallelRouteKey: string]: FlightRouterState } = {}\n for (const parallelRouteKey in baseChildren) {\n if (parallelRouteKey === updatedParallelRouteKey) {\n const childBaseRouterState = baseChildren[parallelRouteKey]\n newChildren[parallelRouteKey] =\n simulatePrefetchTreeUsingDynamicTreePatchImpl(\n childBaseRouterState,\n patch,\n segmentPath,\n canMutateInPlace,\n // Advance the index by two and keep cloning until we reach\n // the end of the segment path.\n index + 2\n )\n } else {\n // This child is not being patched. Copy it over as-is.\n newChildren[parallelRouteKey] = baseChildren[parallelRouteKey]\n }\n }\n\n if (canMutateInPlace) {\n // We can mutate the base tree in place, because the base tree is already\n // a clone.\n baseRouterState[1] = newChildren\n return baseRouterState\n }\n\n // Clone all the fields except the children.\n //\n // Based on equivalent logic in apply-router-state-patch-to-tree, but should\n // confirm whether we need to copy all of these fields. Not sure the server\n // ever sends, e.g. the refetch marker.\n const clone: FlightRouterState = [baseRouterState[0], newChildren]\n if (2 in baseRouterState) {\n clone[2] = baseRouterState[2]\n }\n if (3 in baseRouterState) {\n clone[3] = baseRouterState[3]\n }\n if (4 in baseRouterState) {\n clone[4] = baseRouterState[4]\n }\n return clone\n}\n"],"names":["NavigationResultTag","navigate","url","currentCacheNode","currentFlightRouterState","nextUrl","shouldScroll","now","Date","cacheKey","createCacheKey","href","route","readRouteCacheEntry","status","EntryStatus","Fulfilled","snapshot","readRenderSnapshotFromCache","tree","prefetchFlightRouterState","flightRouterState","prefetchSeedData","seedData","prefetchHead","head","isPrefetchHeadPartial","isHeadPartial","newCanonicalUrl","canonicalUrl","navigateUsingPrefetchedRouteTree","hash","tag","data","navigateDynamicallyWithNoPrefetch","scrollableSegments","task","startPPRNavigation","dynamicRequestTree","promiseForDynamicServerResponse","fetchServerResponse","listenForDynamicRequest","navigationTaskToResult","newCacheNode","node","cacheNode","childRouterStates","childSeedDatas","slots","parallelRouteKey","childTree","childResult","rsc","loading","isPartial","segmentEntry","readSegmentCacheEntry","key","Pending","promiseForFulfilledEntry","waitForSegmentCacheEntry","then","entry","Empty","Rejected","segment","isRootLayout","flightData","canonicalUrlOverride","newUrl","simulatePrefetchTreeUsingDynamicTreePatch","createCanonicalUrl","hasDynamicHoles","currentTree","baseTree","segmentPath","treePatch","canMutateInPlace","simulatePrefetchTreeUsingDynamicTreePatchImpl","baseRouterState","patch","index","length","updatedParallelRouteKey","baseChildren","newChildren","childBaseRouterState","clone"],"mappings":"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"}
|
package/dist/client/index.js
CHANGED
@@ -61,7 +61,7 @@ const _hooksclientcontextsharedruntime = require("../shared/lib/hooks-client-con
|
|
61
61
|
const _onrecoverableerror = require("./react-client-callbacks/on-recoverable-error");
|
62
62
|
const _tracer = /*#__PURE__*/ _interop_require_default._(require("./tracing/tracer"));
|
63
63
|
const _isnextroutererror = require("./components/is-next-router-error");
|
64
|
-
const version = "15.2.1-canary.
|
64
|
+
const version = "15.2.1-canary.2";
|
65
65
|
let router;
|
66
66
|
const emitter = (0, _mitt.default)();
|
67
67
|
const looseToArray = (input)=>[].slice.call(input);
|