Buffer.from('{"nodes":')

// Turbopack trace files start with this magic header (written by trace_writer.rs)
const TURBOPACK_TRACE_HEADER = Buffer.from('TRACEv0')

const PROGRESS_CHUNK_SIZE = 64 * 1024 // 64 KB

export interface UploadTraceOptions {
  directory?: string
}

function getUploadUrl(): string {
  return process.env.__NEXT_UPLOAD_TRACE_URL_OVERRIDE || UPLOAD_TRACE_URL
}

function formatBytes(bytes: number): string {
  if (bytes < 1024) return `${bytes} B`
  if (bytes < 1024 * 1024) return `${(byt

 = Math.round(width * ratio)
  const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(width - filled)
  const percent = (ratio * 100).toFixed(0).padStart(3)
  return `  [${bar}] ${percent}% ${formatBytes(current)}/${formatBytes(total)}`
}

function createPr

es / 1024).toFixed(1)} KB`
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`
}

function renderProgressBar(current: number, total: number): string {
  const width = 30
  const ratio = Math.min(current / total, 1)
  const filled


lib/router/utils/remove-trailing-slash'
import { parsePath } from '../shared/lib/router/utils/parse-path'

/**
 * Normalizes the trailing slash of a path according to the `trailingSlash` option
 * in `next.config.js`.
 */
export const normalizePathTrailingSlash = (path: string) => {
  // 47 is the char code for '/'
  if (path.charCodeAt(0) !== 47 || process.env.__NEXT_MANUAL_TRAILING_SLASH) {
    return path
  }

  const { pathname, query, hash } = parsePath(path)
  if (process.env.__NEXT_TRAILING_SLASH) {

 `${removeTrailingSlash(pathname)}${query}${hash}`
    } else if (pathname.endsWith('/')) {
      return `${pathname}${query}${hash}`
    } else {
      return `${pathname}/${query}${hash}`
    }
  }

  return `${removeTrailingSlash(pathname)}${query}${has

    if (/\.[^/]+\/?$/.test(pathname)) {
      return


import { useRouter } from './router'

const nextjsRouteAnnouncerStyles: React.CSSProperties = {
  border: 0,
  clip: 'rect(0 0 0 0)',
  height: '1px',
  margin: '-1px',
  overflow: 'hidden',
  padding: 0,
  position: 'absolute',
  top: 0,
  width: '1px',

  // https://medium.com/@jessebeach/beware-smushed-off-screen-accessible-text-5952a4c2cbfe
  whiteSpace: 'nowrap',
  wordWrap: 'normal',
}

export const RouteAnnouncer = () => {
  const { asPath } = useRouter()
  const [routeAnnouncement, setRouteAnnounce

es, announce the new page’s title following this
  // priority: first the document title (from head), otherwise the first h1, or
  // if none of these exist, then the pathname from the URL. This methodology is
  // inspired by Marcy Sutton’s accessible cli

ment] = React.useState('')

  // Only announce the path change, but not for the first load because screen
  // reader will do that automatically.
  const previouslyLoadedPath = React.useRef(asPath)

  // Every time the path chang


bals } from '../trace/shared'
import type { ExportAppResult } from '../export/types'
import type { FetchMetrics } from '../server/base-http'

const DIAGNOSTICS_DIR = 'diagnostics'
const DIAGNOSTICS_FILE = 'build-diagnostics.json'
const FETCH_METRICS_FILE = 'fetch-metrics.json'
const INCREMENTAL_BUILDS_FILE = 'incremental-build-diagnostics.json'
const FRAMEWORK_VERSION_FILE = 'framework.json'

interface BuildDiagnostics {
  // The current stage of the build process. This should be updated as the
  // build p

etDiagnosticsDir(): Promise<string> {
  const distDir = traceGlobals.get('distDir')
  const diagnosticsDir = join(distDir, DIAGNOSTICS_DIR)
  await mkdir(diagnosticsDir, { recursive: true })
  return diagnosticsDir
}

/**
 * Saves the exact version of Next

rogresses so it's what stage the build was in when an error
  // happened.
  buildStage?: string
  // Additional debug information about the configuration for the build.
  buildOptions?: Record<string, string>
}

async function g


ceId } from './shared'
import { Telemetry } from '../telemetry/storage'

export default function uploadTrace({
  traceUploadUrl,
  mode,
  projectDir,
  distDir,
  isTurboSession,
  sync,
}: {
  traceUploadUrl: string
  mode: 'dev' | 'build'
  projectDir: string
  distDir: string
  isTurboSession: boolean
  sync?: boolean
}) {
  const { NEXT_TRACE_UPLOAD_DEBUG } = process.env
  const telemetry = new Telemetry({ distDir })

  // Note: cross-spawn is not used here as it causes
  // a new command window to app

  NEXT_TRACE_UPLOAD_DEBUG || sync
      ? child_process.spawnSync
      : child_process.spawn

  spawn(
    process.execPath,
    [
      require.resolve('./trace-uploader'),
      traceUploadUrl,
      mode,
      projectDir,
      distDir,
      String(i

ear when we don't want it to
  const child_process =
    require('child_process') as typeof import('child_process')

  // we use spawnSync when debugging to ensure logs are piped
  // correctly to stdout/stderr
  const spawn =


basePath = process.env.__NEXT_ROUTER_BASEPATH || ''
const pathname = `${basePath}/__nextjs_source-map`

export const findSourceMapURL =
  // Source maps are only served by the dev server.
  process.env.__NEXT_DEV_SERVER
    ? function findSourceMapURL(filename: string): string | null {
        if (filename === '') {
          return null
        }

        if (
          filename.startsWith(document.location.origin) &&
          filename.includes('/_next/static')
        ) {
          // This is a request f

o the filename, with an added `.map` extension. The
          // browser can just request this file, and it gets served through the
          // normal dev server, without the need to route this through
          // the `/__nextjs_source-map` dev middlewar

or a client chunk. This can only happen when
          // using Turbopack. In this case, since we control how those source
          // maps are generated, we can safely assume that the sourceMappingURL
          // is relative t


---------------------------------------------------

/**
 * The 6 file categories we partition each route's files into. Each file is
 * placed into exactly one category to avoid double-counting.
 *
 * To add a new category, extend this tuple, add a label below, and update
 * the relevant collector(s).
 */
const CATEGORIES = [
  'clientJs',
  'clientCss',
  'clientMaps',
  'serverBundled',
  'serverUnbundled',
  'serverMaps',
] as const
type Category = (typeof CATEGORIES)[number]

/** Human-readable column t

Unbundled: 'Server Unbundled',
  serverMaps: 'Server Source Maps',
}

/**
 * Per-route file sets, one entry per category.
 *
 * Paths are stored either relative to `distDir` (for files that live inside
 * the build output) or as absolute paths (for files t

itles, in the same order as CATEGORIES. */
const CATEGORY_LABELS: Record<Category, string> = {
  clientJs: 'Client JS',
  clientCss: 'Client CSS',
  clientMaps: 'Client Source Maps',
  serverBundled: 'Server Bundled JS',
  server


from '../shared/lib/router/utils/querystring'
import { formatWithValidation } from '../shared/lib/router/utils/format-url'
import { omit } from '../shared/lib/router/utils/omit'
import { normalizeRepeatedSlashes } from '../shared/lib/utils'
import { normalizePathTrailingSlash } from './normalize-trailing-slash'
import { isLocalURL } from '../shared/lib/router/utils/is-local-url'
import { isDynamicRoute } from '../shared/lib/router/utils'
import { interpolateAs } from '../shared/lib/router/utils/interpolate-

cluded).
 * Preserves absolute urls.
 */
export function resolveHref(
  router: NextRouter,
  href: Url,
  resolveAs: true
): [string, string] | [string]
export function resolveHref(
  router: NextRouter,
  href: Url,
  resolveAs?: false
): string
export f

as'
import { getRouteRegex } from '../shared/lib/router/utils/route-regex'
import { getRouteMatcher } from '../shared/lib/router/utils/route-matcher'

/**
 * Resolves a given hyperlink with a certain router state (basePath not in


port { traceGlobals } from '../shared'
import { PHASE_PRODUCTION_BUILD } from '../../shared/lib/constants'
import { createJsonReporter } from './to-json'

const allowlistedEvents = new Set([
  'next-build',
  'run-turbopack',
  'run-webpack',
  'run-typescript',
  'run-eslint',
  'static-check',
  'collect-build-traces',
  'static-generation',
  'output-export-full-static-export',
  'adapter-handle-build-complete',
  'output-standalone',
  'telemetry-flush',
  'turbopack-build-events',
  'turbopack-persiste

pack-compaction',
])

export default createJsonReporter({
  filename: 'trace-build',
  sizeLimit: Infinity,
  filter: (event) => {
    const phase = traceGlobals.get('phase')
    return phase === PHASE_PRODUCTION_BUILD && allowlistedEvents.has(event.name)


ny` type.
import './register-deployment-id-global'
import { initialize, version, router, emitter } from './'
import initHMR from './dev/hot-middleware-client'

import { pageBootstrap } from './page-bootstrap'
//@ts-expect-error requires "moduleResolution": "node16" in tsconfig.json and not .ts extension
import { connect } from '@vercel/turbopack-ecmascript-runtime/browser/dev/hmr-client/hmr-client.ts'
import type { TurbopackMessageSentToBrowser } from '../server/dev/hot-reloader-types'

window.next = {
  ve

// for the page loader
declare let __turbopack_load__: any

const devClient = initHMR()
initialize({
  devClient,
})
  .then(({ assetPrefix }) => {
    // for the page loader
    ;(self as any).__turbopack_load_page_chunks__ = (
      page: string,
      c

rsion,
  turbopack: true,
  // router is initialized later so it has to be live-binded
  get router() {
    return router
  },
  emitter,
}
;(self as any).__next_set_public_path__ = () => {}
;(self as any).__webpack_hash__ = ''


b.com/facebook/react/blob/b565373afd0cc1988497e1107106e851e8cfb261/packages/react-dom-bindings/src/shared/sanitizeURL.js

// A javascript: URL can contain leading C0 control or \u0020 SPACE,
// and any newline or tab are filtered out as if they're not part of the URL.
// https://url.spec.whatwg.org/#url-parsing
// Tab or newline are defined as \r\n\t:
// https://infra.spec.whatwg.org/#ascii-tab-or-newline
// A C0 control is a code point in the range \u0000 NULL to \u001F
// INFORMATION SEPARATOR ONE, inclus

-space

const isJavaScriptProtocol =
  // eslint-disable-next-line no-control-regex
  /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*:/i

export function isJavaScriptURLString(url: str


 { PromiseQueue } from './promise-queue'

describe('PromiseQueue', () => {
  it('should limit the number of concurrent promises', async () => {
    const queue = new PromiseQueue(2)
    const results: number[] = []

    const promises = Array.from({ length: 5 }, (_, i) =>
      queue.enqueue(async () => {
        results.push(i)
        await new Promise((resolve) => setTimeout(resolve, 100))
        return i
      })
    )

    const resolved = await Promise.all(promises)

    expect(resolved).toEqual([0,

s = Array.from({ length: 5 }, (_, i) =>
      queue.enqueue(async () => {
        results.push(i)
        await new Promise((resolve) => setTimeout(resolve, 100))
        return i
      })
    )

    queue.bump(promises[3])

    const resolved = await Prom

1, 2, 3, 4])
    expect(results).toEqual([0, 1, 2, 3, 4])
  })
  it('should allow bumping a promise to be next in the queue', async () => {
    const queue = new PromiseQueue(2)
    const results: number[] = []

    const promise


romise queue that allows you to limit the number of concurrent promises
    that are running at any given time. It's used to limit the number of concurrent
    prefetch requests that are being made to the server but could be used for other
    things as well.
*/
export class PromiseQueue {
  #maxConcurrency: number
  #runningCount: number
  #queue: Array<{
    promiseFn: Promise<any>
    task: () => void
  }>

  constructor(maxConcurrency = 5) {
    this.#maxConcurrency = maxConcurrency
    this.#runningCou

solve, reject) => {
      taskResolve = resolve
      taskReject = reject
    }) as Promise<T>

    const task = async () => {
      try {
        this.#runningCount++
        const result = await promiseFn()
        taskResolve(result)
      } catch (erro

nt = 0
    this.#queue = []
  }

  enqueue<T>(promiseFn: () => Promise<T>): Promise<T> {
    let taskResolve: (value: T | PromiseLike<T>) => void
    let taskReject: (reason?: any) => void

    const taskPromise = new Promise((re


arams implementation shared between client and server.
 * This file is intentionally not marked as 'use client' or 'use server'
 * so it can be imported by both environments.
 */

/** @internal */
class ReadonlyURLSearchParamsError extends Error {
  constructor() {
    super(
      'Method unavailable on `ReadonlyURLSearchParams`. Read more: https://nextjs.org/docs/app/api-reference/functions/use-search-params#updating-searchparams'
    )
  }
}

/**
 * A read-only version of URLSearchParams that throws erro

e on `ReadonlyURLSearchParams`. Read more: https://nextjs.org/docs/app/api-reference/functions/use-search-params#updating-searchparams */
  append() {
    throw new ReadonlyURLSearchParamsError()
  }
  /** @deprecated Method unavailable on `ReadonlyURLSear

rs when mutation methods are called.
 * This ensures that the URLSearchParams returned by useSearchParams() cannot be mutated.
 */
export class ReadonlyURLSearchParams extends URLSearchParams {
  /** @deprecated Method unavailabl


t'
import type { AppRouterInstance } from '../../shared/lib/app-router-context.shared-runtime'
import { useRouter } from './navigation'
import { getRedirectTypeFromError, getURLFromRedirectError } from './redirect'
import { type RedirectType, isRedirectError } from './redirect-error'

interface RedirectBoundaryProps {
  router: AppRouterInstance
  children: React.ReactNode
}

function HandleRedirect({
  redirect,
  reset,
  redirectType,
}: {
  redirect: string
  redirectType: RedirectType
  reset: () => vo

reset()
    })
  }, [redirect, redirectType, reset, router])

  return null
}

export class RedirectErrorBoundary extends React.Component<
  RedirectBoundaryProps,
  { redirect: string | null; redirectType: RedirectType | null }
> {
  constructor(props: Re

id
}) {
  const router = useRouter()

  useEffect(() => {
    React.startTransition(() => {
      if (redirectType === 'push') {
        router.push(redirect, {})
      } else {
        router.replace(redirect, {})
      }


 { RedirectStatusCode } from './redirect-status-code'

export const REDIRECT_ERROR_CODE = 'NEXT_REDIRECT'

export type RedirectType = 'push' | 'replace'

export type RedirectError = Error & {
  digest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};`
}

/**
 * Checks an error to determine if it's an error generated by the
 * `redirect(url)` helper.
 *
 * @param error the error that may reference a redirect error
 * @returns true if the error is a redirect error
 */
export fun

gest = error.digest.split(';')
  const [errorCode, type] = digest
  const destination = digest.slice(2, -2).join(';')
  const status = digest.at(-2)

  const statusCode = Number(status)

  return (
    errorCode === REDIRECT_ERROR_CODE &&
    (type === 're

ction isRedirectError(error: unknown): error is RedirectError {
  if (
    typeof error !== 'object' ||
    error === null ||
    !('digest' in error) ||
    typeof error.digest !== 'string'
  ) {
    return false
  }

  const di


ectError,
  isRedirectError,
  REDIRECT_ERROR_CODE,
} from './redirect-error'

const actionAsyncStorage =
  typeof window === 'undefined'
    ? (
        require('../../server/app-render/action-async-storage.external') as typeof import('../../server/app-render/action-async-storage.external')
      ).actionAsyncStorage
    : undefined

export function getRedirectError(
  url: string,
  type: RedirectType,
  statusCode: RedirectStatusCode = RedirectStatusCode.TemporaryRedirect
): RedirectError {
  const error

* [Server Components](https://nextjs.org/docs/app/building-your-application/rendering/server-components),
 * [Route Handlers](https://nextjs.org/docs/app/building-your-application/routing/route-handlers), and
 * [Server Actions](https://nextjs.org/docs/app

 = new Error(REDIRECT_ERROR_CODE) as RedirectError
  error.digest = `${REDIRECT_ERROR_CODE};${type};${url};${statusCode};`
  return error
}

/**
 * This function allows you to redirect the user to another URL. It can be used in


TTP_ERROR_FALLBACK_ERROR_CODE,
  type HTTPAccessFallbackError,
} from './http-access-fallback/http-access-fallback'

// TODO: Add `unauthorized` docs
/**
 * @experimental
 * This function allows you to render the [unauthorized.js file](https://nextjs.org/docs/app/api-reference/file-conventions/unauthorized)
 * within a route segment as well as inject a tag.
 *
 * `unauthorized()` can be used in
 * [Server Components](https://nextjs.org/docs/app/building-your-application/rendering/server-components),
 * [Rou

more: [Next.js Docs: `unauthorized`](https://nextjs.org/docs/app/api-reference/functions/unauthorized)
 */

const DIGEST = `${HTTP_ERROR_FALLBACK_ERROR_CODE};401`

export function unauthorized(): never {
  if (!process.env.__NEXT_EXPERIMENTAL_AUTH_INTERRUP

te Handlers](https://nextjs.org/docs/app/building-your-application/routing/route-handlers), and
 * [Server Actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations).
 *
 *
 * Read


args: ConstructorParameters<typeof Error>) {
    super(...args)
    this.name = 'UnrecognizedActionError'
  }
}

/**
 * Check whether a server action call failed because the server action was not recognized by the server.
 * This can happen if the client and the server are not from the same deployment.
 *
 * Example usage:
 * ```ts
 * try {
 *   await myServerAction();
 * } catch (err) {
 *   if (unstable_isUnrecognizedActionError(err)) {
 *     // The client is from a different deployment than the server.

 *     window.alert("Please refresh the page and try again");
 *     return;
 *   }
 * }
 * ```
 * */
export function unstable_isUnrecognizedActionError(
  error: unknown
): error is UnrecognizedActionError {
  return !!(
    error &&
    typeof error ===

*     // Reloading the page will fix this mismatch.


rror } from '../../server/dynamic-rendering-utils'
import { isPostpone } from '../../server/lib/router-utils/is-postpone'
import { isBailoutToCSRError } from '../../shared/lib/lazy-dynamic/bailout-to-csr'
import { isNextRouterError } from './is-next-router-error'
import {
  isDynamicPostpone,
  isPrerenderInterruptedError,
} from '../../server/app-render/dynamic-rendering'
import { isDynamicServerError } from './hooks-server-context'

export function unstable_rethrow(error: unknown): void {
  if (
    isNex

) ||
    isDynamicServerError(error) ||
    isDynamicPostpone(error) ||
    isPostpone(error) ||
    isHangingPromiseRejectionError(error) ||
    isPrerenderInterruptedError(error)
  ) {
    throw error
  }

  if (error instanceof Error && 'cause' in error

tRouterError(error) ||
    isBailoutToCSRError(error


* This function should be used to rethrow internal Next.js errors so that they can be handled by the framework.
 * When wrapping an API that uses errors to interrupt control flow, you should use this function before you do any error handling.
 * This function will rethrow the error if it is a Next.js error so it can be handled, otherwise it will do nothing.
 *
 * Read more: [Next.js Docs: `unstable_rethrow`](https://nextjs.org/docs/app/api-reference/functions/unstable_rethrow)
 */
export const unstable_reth

 window === 'undefined'
    ? (
        require('./unstable-rethrow.server') as typeof import('./unstable-rethrow.server')
      ).unstable_rethrow
    : (
        require('./unstable-rethrow.browser') as typeof import('./unstable-rethrow.browser')
      )


router-instance'
import {
  ACTION_REFRESH,
  type AppRouterState,
  type ReducerActions,
  type ReducerState,
} from './router-reducer/router-reducer-types'

// The app router state lives outside of React, so we can import the dispatch
// method directly wherever we need it, rather than passing it around via props
// or context.
let dispatch: Dispatch<ReducerActions> | null = null

/**
 * Called when the instant navigation test lock is released. If the router
 * is initialized, dispatches a soft refresh to

 (dispatch !== null) {
      dispatch({ type: ACTION_REFRESH, bypassCacheInvalidation: true })
    } else {
      window.location.reload()
    }
  }
}

export function dispatchAppRouterAction(action: ReducerActions) {
  if (dispatch === null) {
    throw n

 fetch dynamic data. If not
 * (e.g. the lock was released before hydration finished), falls back to a
 * hard reload.
 */
export function refreshOnInstantNavigationUnlock() {
  if (process.env.__NEXT_EXPOSE_TESTING_API) {
    if


t, {
  createContext,
  useContext,
  useState,
  useOptimistic,
  startTransition,
} from 'react'

const OfflineContext = createContext<boolean>(false)

// Module-level reference to the optimistic setter. Assigned inside the
// provider component on every render. Called by the offline module
// (via dispatchOfflineChange) to update the React tree.
let setOptimistic: ((value: boolean) => void) | null = null
let setCanonical: ((value: boolean) => void) | null = null

/**
 * Called by the offline module when

if (canonical === null || optimistic === null) {
    return
  }
  startTransition(() => {
    canonical(isOffline)
    optimistic(isOffline)
  })
}

export function OfflineProvider({ children }: { children: React.ReactNode }) {
  const [canonicalOffline, s

the offline state changes.
 * Dispatches into React via startTransition + useOptimistic.
 */
export function dispatchOfflineChange(isOffline: boolean): void {
  const canonical = setCanonical
  const optimistic = setOptimistic


lient'

// This facade ensures that the boundary code is DCE'd in browser bundles.
//
// It also exists to satisfy `browser-chunks.test.ts`, which looks for
// references to code in `packages/next/src/server` in browser bundles and errors if it finds any.
// A "use client" module seems to always have always have an entry in the browser bundle,
// so this module cannot be colocated with the rest of the instant validation code,
// because it ends up looking like it's importing server code in the browser
// ev

' && process.env.__NEXT_CACHE_COMPONENTS
    ? (require('../../../server/app-render/instant-validation/boundary-impl') as typeof import('../../../server/app-render/instant-validation/boundary-impl'))
    : ({} as typeof import('../../../server/app-render/i

en though all the server code inside is actually DCE'd.

const {
  InstantValidationBoundaryContext,
  PlaceValidationBoundaryBelowThisLevel,
  RenderValidationBoundaryAtThisLevel,
  SlotMarker,
} =
  typeof window === 'undefined


was provided.
 * When this is the dynamicStaleTime, the default DYNAMIC_STALETIME_MS is used.
 */
export const UnknownDynamicStaleTime = -1

/**
 * Converts a dynamic stale time (in seconds, as sent by the server in the `d`
 * field of the Flight response) to an absolute staleAt timestamp. When the
 * value is unknown, falls back to the global DYNAMIC_STALETIME_MS.
 */
export function computeDynamicStaleAt(
  now: number,
  dynamicStaleTimeSeconds: number
): number {
  return dynamicStaleTimeSeconds !== Unk

ache-map'

export type BFCacheEntry = {
  rsc: React.ReactNode | null
  prefetchRsc: React.ReactNode | null
  head: React.ReactNode | null
  prefetchHead: React.ReactNode | null

  // The bfcacheId of the CacheNode that wrote this entry. Restored on
  // h

nownDynamicStaleTime
    ? now + dynamicStaleTimeSeconds * 1000
    : now + DYNAMIC_STALETIME_MS
}
import {
  setInCacheMap,
  getFromCacheMap,
  EntryStatus,
  type UnknownMapEntry,
  type CacheMap,
  createCacheMap,
} from './c


e<K, T> = T & { __brand: K }

// Only functions in this module should be allowed to create CacheKeys.
export type NormalizedPathname = Opaque<'NormalizedPathname', string>
export type NormalizedSearch = Opaque<'NormalizedSearch', string>
export type NormalizedNextUrl = Opaque<'NormalizedNextUrl', string>

export type RouteCacheKey = Opaque<
  'RouteCacheKey',
  {
    pathname: NormalizedPathname
    search: NormalizedSearch
    nextUrl: NormalizedNextUrl | null

    // TODO: Eventually the dynamic params wi

CacheKey(
  originalHref: string,
  nextUrl: string | null
): RouteCacheKey {
  const originalUrl = new URL(originalHref)
  const cacheKey = {
    pathname: originalUrl.pathname as NormalizedPathname,
    search: originalUrl.search as NormalizedSearch,

ll be added here, too.
  }
>

export function create


ps://localhost', 'foo/bar/baz']) -> 'yay'
 *
 * NOTE: Array syntax is used in these examples for illustration purposes, but
 * in reality the paths are lists.
 *
 * The parts of the keypath represent the different inputs that contribute
 * to the entry value. To illustrate, if you were to use this data type to store
 * HTTP responses, the keypath would include the URL and everything listed by
 * the Vary header.
 *
 * See vary-path.ts for more details.
 *
 * The order of elements in a keypath must be cons

lback as part of its keypath, it means that the entry does not
 * vary by that key. When querying the cache, if an exact match is not found for
 * a keypath, the cache will check for a Fallback match instead. Each element of
 * the keypath may have a Fallb

istent between lookups to
 * be considered the same, but besides that, the order of the keys is not
 * semantically meaningful.
 *
 * Keypaths may include a special kind of key called Fallback. When an entry is
 * stored with Fal


from '../../navigation-build-id'
import { NEXT_NAV_DEPLOYMENT_ID_HEADER } from '../../../lib/constants'

/**
 * Ensures a minimum stale time of 30s to avoid issues where the server sends a too
 * short-lived stale time, which would prevent anything from being prefetched.
 */
export function getStaleTimeMs(staleTimeSeconds: number): number {
  return Math.max(staleTimeSeconds, 30) * 1000
}

// A note on async/await when working in the prefetch cache:
//
// Most async operations in the prefetch cache should *

ache and traverse its
// data structures synchronously. For example, if there's a synchronous update
// we can take an immediate snapshot of the cache to produce something we can
// render. Limiting the use of async/await also makes it easier to avoid race

not* use async/await,
// Instead, spawn a subtask that writes the results to a cache entry, and attach
// a "ping" listener to notify the prefetch queue to try again.
//
// The reason is we need to be able to access the segment c


h } from './navigation-testing-lock'

/**
 * Internal `fetch` used by the Next.js client router.
 *
 * When the Instant Navigation Testing API is enabled, the navigation lock may
 * install a blocking override on `window.fetch` for the duration of a lock
 * scope. To let internal fetches bypass the lock, callers go through a wrapper
 * that falls back to the pre-lock fetch captured at lock-acquire time.
 *
 * When the testing API is not enabled, this calls window.fetch directly.
 */
function fetchInternal(

Promise<Response> {
  if (process.env.__NEXT_EXPOSE_TESTING_API) {
    const preLockFetch = getPreLockFetch()
    if (preLockFetch !== null) {
      return preLockFetch(input, init)
    }
  }
  return fetch(input, init)
}

export { fetchInternal as fetch }

  input: RequestInfo | URL,
  init?: RequestInit
):


 { pingPrefetchScheduler } from './scheduler'

// We use an LRU for memory management. We must update this whenever we add or
// remove a new cache entry, or when an entry changes size.

let head: UnknownMapEntry | null = null
let lruSize: number = 0

// TODO: I chose the max size somewhat arbitrarily. Consider setting this based
// on navigator.deviceMemory, or some other heuristic. We should make this
// customizable via the Next.js config, too.
const maxLruSize = 50 * 1024 * 1024 // 50 MB

export functio

+= node.size
    // Whenever we add an entry, we need to check if we've exceeded the
    // max size. We don't evict entries immediately; they're evicted later in
    // an asynchronous task.
    ensureCleanupIsScheduled()
  } else {
    // This is a move.

n lruPut(node: UnknownMapEntry) {
  if (head === node) {
    // Already at the head
    return
  }
  const prev = node.prev
  const next = node.next
  if (next === null || prev === null) {
    // This is an insertion
    lruSize


es.
 * The CookieStore handler distinguishes them by value: pending = external,
 * captured = self-write (ignored).
 */

import type {
  FlightRouterState,
  InstantCookie,
} from '../../../shared/lib/app-router-types'
import { NEXT_INSTANT_TEST_COOKIE } from '../app-router-headers'
import { refreshOnInstantNavigationUnlock } from '../use-action-queue'

type InstantNavCookieState = 'empty' | 'pending' | 'mpa' | 'spa'

function parseCookieValue(raw: string): InstantNavCookieState {
  if (raw === '') {
    re

ng'
}

function writeCookieValue(value: InstantCookie): void {
  if (typeof cookieStore === 'undefined') {
    return
  }
  // Read the existing cookie to preserve its attributes (domain, path),
  // then write back with the new value. This updates the sam

turn 'empty'
  }
  try {
    const parsed = JSON.parse(raw)
    if (Array.isArray(parsed) && parsed.length >= 3) {
      const rawState = parsed[2]
      return rawState === null ? 'mpa' : 'spa'
    }
  } catch {}
  return 'pendi


 convertRootFlightRouterStateToRouteTree,
  getStaleAt,
  writeStaticStageResponseIntoCache,
  processRuntimePrefetchStream,
  writeDynamicRenderResponseIntoCache,
  type RouteTree,
  type FulfilledRouteCacheEntry,
} from './cache'
import { discoverKnownRoute } from './optimistic-routes'
import { createCacheKey, type NormalizedSearch } from './cache-key'
import { schedulePrefetchTask } from './scheduler'
import { PrefetchPriority, FetchStrategy } from './types'
import { getLinkForCurrentNavigation } from '.

Path } from '../router-reducer/compute-changed-path'
import { isJavaScriptURLString } from '../../lib/javascript-url'
import { UnknownDynamicStaleTime, computeDynamicStaleAt } from './bfcache'

/**
 * Navigate to a new URL, using the Segment Cache to const

./links'
import type { PageVaryPath } from './vary-path'
import type { AppRouterState } from '../router-reducer/router-reducer-types'
import { ScrollBehavior } from '../router-reducer/router-reducer-types'
import { computeChanged


: Called after receiving a route tree from the server.
 *    Traverses the route tree, compares URL parts to segments, and populates
 *    the known route tree if they match. Routes are always inserted into the
 *    cache.
 *
 * 2. matchKnownRoute: Called when looking up a route with no cache entry.
 *    Matches the candidate URL against learned patterns. Returns a synthetic
 *    cache entry if successful, or null to fall back to server resolution.
 *
 * Rewrite detection happens during traversal: if a U

no eviction. Route patterns are
 * derived from the filesystem, so they don't become stale within a session.
 * Cache invalidation on deploy clears everything anyway.
 *
 * Current limitations (deopt to server resolution):
 * - Rewrites: Detected during tr

RL path part doesn't match
 * the corresponding route segment, we stop populating the known route tree
 * (since the mapping is incorrect) but still insert the route into the cache.
 *
 * The known route tree is append-only with


ared/lib/app-router-types'
import { createPrefetchURL } from '../app-router-utils'
import { createCacheKey } from './cache-key'
import { schedulePrefetchTask } from './scheduler'
import { PrefetchPriority, type PrefetchTaskFetchStrategy } from './types'

/**
 * Entrypoint for prefetching a URL into the Segment Cache.
 * @param href - The URL to prefetch. Typically this will come from a <Link>,
 * or router.prefetch. It must be validated before we attempt to prefetch it.
 * @param nextUrl - A special header

param fetchStrategy - Whether to prefetch dynamic data, in addition to
 * static data. This is used by `<Link prefetch={true}>`.
 * @param onInvalidate - A callback that will be called when the prefetch cache
 * When called, it signals to the listener that

used by the server for interception routes.
 * Roughly corresponds to the current URL.
 * @param treeAtTimeOfPrefetch - The FlightRouterState at the time the prefetch
 * was requested. This is only used when PPR is disabled.
 * @


prefetch
   * it is. For example, was it initiated by a link? Or was it an imperative
   * call? If it was initiated by a link, we can remove it from the queue when
   * the link leaves the viewport, but if it was an imperative call, then we
   * should keep it in the queue until it's fulfilled.
   *
   * We can also add priority levels. For example, hovering over a link could
   * increase the priority of its prefetch.
   */
  sortId: number

  /**
   * The priority of the task. Like sortId, this affects t

can be adjusted based on what kind of work they're doing.
   * Concretely, prefetching the route tree is higher priority than prefetching
   * segment data.
   */
  phase: PrefetchPhase

  /**
   * These fields are temporary state for tracking the currentl

he task's position in
   * the queue, so it must never be updated without resifting the heap.
   */
  priority: PrefetchPriority

  /**
   * The phase of the task. Tasks are split into multiple phases so that their
   * priority


onstants for the Segment Cache.
 */

export const enum NavigationResultTag {
  MPA,
  Success,
  NoOp,
  Async,
}

/**
 * The priority of the prefetch task. Higher numbers are higher priority.
 */
export const enum PrefetchPriority {
  /**
   * Assigned to the most recently hovered/touched link. Special network
   * bandwidth is reserved for this task only. There's only ever one Intent-
   * priority task at a time; when a new Intent task is scheduled, the previous
   * one is bumped down to Default.
   */

 is available.
   */
  Background = 0,
}

export const enum FetchStrategy {
  // Deliberately ordered so we can easily compare two segments
  // and determine if one segment is "more specific" than another
  // (i.e. if it's likely that it contains more da

  Intent = 2,
  /**
   * The default priority for prefetch tasks.
   */
  Default = 1,
  /**
   * Assigned to tasks when they spawn non-blocking background work, like
   * revalidating a partially cached entry to see if more data


(or other param-like) inputs that a cache
 * entry may vary by. This is used by the CacheMap module to reuse cache entries
 * across different param values. If a param has a value of Fallback, it means
 * the cache entry is reusable for all possible values of that param. See
 * cache-map.ts for details.
 *
 * A segment's vary path is a pure function of a segment's position in a
 * particular route tree and the (post-rewrite) URL that is being queried. More
 * concretely, successive queries of the cache for

ary path node corresponds to. Used by
   * getFulfilledSegmentVaryPath to determine which params to replace with
   * Fallback based on the varyParams set from the server.
   *
   * - For path params: the param name (e.g., 'slug')
   * - For search params:

the same segment always use
 * the same vary path.
 *
 * A route's vary path is simpler: it's comprised of the pathname, search
 * string, and Next-URL header.
 */
export type VaryPath = {
  /**
   * Identifies which param this v


import React from 'react'
import { errorStyles, errorThemeCss, WarningIcon } from './error-styles'

// This is the static 500.html page for App Router apps.
// Always a server error, rendered at build time.
function AppError() {
  return (

        <title>500: This page couldn’t load</title>

      </p>
            <form style={errorStyles.form}>
              <button type="submit" style={errorStyles.button}>
                Reload
              </button>
            </form>
          </div>
        </div>
      </body>
    </html>
  )
}

expor

tyles.card}>
            <WarningIcon />

This page couldn’t load

              A server error occurred. Reload to try again.


i,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"',
    height: '100vh',
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
  },
  card: {
    marginTop: '-32px',
    maxWidth: '325px',
    padding: '32px 28px',
    textAlign: 'left' as const,
  },
  icon: {
    marginBottom: '24px',
  },
  title: {
    fontSize: '24px',
    fontWeight: 500,
    letterSpacing: '-0.02em',
    lineHeight: '32px',
    margin: '0 0 12px 0',
    color: 'var(--next-error

ex',
    gap: '8px',
    alignItems: 'center',
  },
  button: {
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    height: '32px',
    padding: '0 12px',
    fontSize: '14px',
    fontWeight: 500,
    lineHeight: '20px'

-title)',
  },
  message: {
    fontSize: '14px',
    fontWeight: 400,
    lineHeight: '21px',
    margin: '0 0 20px 0',
    color: 'var(--next-error-message)',
  },
  form: {
    margin: 0,
  },
  buttonGroup: {
    display: 'fl


ndleISRError } from '../handle-isr-error'
import { errorStyles, errorThemeCss, WarningIcon } from './error-styles'

export type GlobalErrorComponent = React.ComponentType<{
  error: any
  reset: () => void
  unstable_retry: () => void
}>

function DefaultGlobalError({ error }: { error: any }) {
  const digest: string | undefined = error?.digest
  const isServerError = !!digest

  const message = isServerError
    ? 'A server error occurred. Reload to try again.'
    : 'Reload to try again, or go back.'

  h

            <WarningIcon />

This page couldn’t load

{message}

andleISRError({ error })

  return (
    <html id="__next_error__">
      <head>
        <style dangerouslySetInnerHTML={{ __html: errorThemeCss }} />
      </head>
      <body>
        <div style={errorStyles.container}>


fallbacks for few HTTP 4xx errors.
 *
 * e.g. 404
 * 404 represents not found, and the fallback component pair contains the component and its styles.
 *
 */

import React, { useContext } from 'react'
import { useUntrackedPathname } from '../navigation-untracked'
import {
  HTTPAccessErrorStatus,
  getAccessFallbackHTTPStatus,
  getAccessFallbackErrorTypeByStatus,
  isHTTPAccessFallbackError,
} from './http-access-fallback'
import { warnOnce } from '../../../shared/lib/utils/warn-once'
import { MissingSlotCo

quired once `React.createElement` understands that positional args go into children
  children?: React.ReactNode
  missingSlots?: Set<string>
}

interface HTTPAccessFallbackErrorBoundaryProps
  extends HTTPAccessFallbackBoundaryProps {
  pathname: string |

ntext } from '../../../shared/lib/app-router-context.shared-runtime'

interface HTTPAccessFallbackBoundaryProps {
  notFound?: React.ReactNode
  forbidden?: React.ReactNode
  unauthorized?: React.ReactNode
  // TODO: Make this re


les } from '../styles/access-error-styles'

export function HTTPAccessErrorFallback({
  status,
  message,
}: {
  status: number
  message: string
}) {
  return (
    <>
      {/*  */}
      <title>{`${status}: ${message}`}</title>
      {/*  */}

    border-right: 1px solid rgba(255, 255, 255, .3);
                  }
                }
              */
              __html: `body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:da

    border-right: 1px solid rgba(0, 0, 0, .3);
                }

                @media (prefers-color-scheme: dark) {
                  body { color: #fff; background: #000; }
                  .next-error-h1 {


rorStatus = {
  NOT_FOUND: 404,
  FORBIDDEN: 403,
  UNAUTHORIZED: 401,
}

const ALLOWED_CODES = new Set(Object.values(HTTPAccessErrorStatus))

export const HTTP_ERROR_FALLBACK_ERROR_CODE = 'NEXT_HTTP_ERROR_FALLBACK'

export type HTTPAccessFallbackError = Error & {
  digest: `${typeof HTTP_ERROR_FALLBACK_ERROR_CODE};${string}`
}

/**
 * Checks an error to determine if it's an error generated by
 * the HTTP navigation APIs `notFound()`, `forbidden()` or `unauthorized()`.
 *
 * @param error the error that may

error === null ||
    !('digest' in error) ||
    typeof error.digest !== 'string'
  ) {
    return false
  }
  const [prefix, httpStatus] = error.digest.split(';')

  return (
    prefix === HTTP_ERROR_FALLBACK_ERROR_CODE &&
    ALLOWED_CODES.has(Number(h

reference a HTTP access error
 * @returns true if the error is a HTTP access error
 */
export function isHTTPAccessFallbackError(
  error: unknown
): error is HTTPAccessFallbackError {
  if (
    typeof error !== 'object' ||


st ACTION_HEADER = 'next-action' as const
// TODO: Instead of sending the full router state, we only need to send the
// segment path. Saves bytes. Then we could also use this field for segment
// prefetches, which also need to specify a particular segment.
export const NEXT_ROUTER_STATE_TREE_HEADER = 'next-router-state-tree' as const
export const NEXT_ROUTER_PREFETCH_HEADER = 'next-router-prefetch' as const
// This contains the path to the segment being prefetched.
// TODO: If we change next-router-state-t

tch' as const
export const NEXT_HMR_REFRESH_HEADER = 'next-hmr-refresh' as const
export const NEXT_HMR_REFRESH_HASH_COOKIE = '__next_hmr_refresh_hash__' as const
export const NEXT_URL = 'next-url' as const
export const RSC_CONTENT_TYPE_HEADER = 'text/x-com

ree to be a segment path, we can use
// that instead. Then next-router-prefetch and next-router-segment-prefetch can
// be merged into a single enum.
export const NEXT_ROUTER_SEGMENT_PREFETCH_HEADER =
  'next-router-segment-prefe


ot } from '../../shared/lib/router/utils/is-bot'
import { addBasePath } from '../add-base-path'

export function isExternalURL(url: URL) {
  return url.origin !== window.location.origin
}

/**
 * Given a link href, constructs the URL that should be prefetched. Returns null
 * in cases where prefetching should be disabled, like external URLs, or
 * during development.
 * @param href The href passed to <Link>, router.prefetch(), or similar
 * @returns A URL object to prefetch, or null if prefetching should be

 URL(addBasePath(href), window.location.href)
  } catch (_) {
    // TODO: Does this need to throw or can we just console.error instead? Does
    // anyone rely on this throwing? (Seems unlikely.)
    throw new Error(
      `Cannot prefetch '${href}' becau

 disabled
 */
export function createPrefetchURL(href: string): URL | null {
  // Don't prefetch for bots as they don't navigate.
  if (isBot(window.navigator.userAgent)) {
    return null
  }

  let url: URL
  try {
    url = new


eState } from 'react'

// When the flag is disabled, only track the currently active tree
const MAX_BF_CACHE_ENTRIES = process.env.__NEXT_CACHE_COMPONENTS ? 3 : 1

export type RouterBFCacheEntry = {
  tree: FlightRouterState
  cacheNode: CacheNode
  stateKey: string
  // The entries form a linked list, sorted in order of most recently active.
  next: RouterBFCacheEntry | null
}

/**
 * Keeps track of the most recent N trees (FlightRouterStates) that were active
 * at a certain segment level. E.g. for a segm

vel.
 *
 * The purpose of this cache is to we can preserve the React and DOM state of
 * some number of inactive trees, by rendering them in an <Activity> boundary.
 * That means it would not make sense for the the lifetime of the cache to be
 * any longer

ent "/a/b/[param]", this hook
 * tracks the last N param values that the router rendered for N.
 *
 * The result of this hook precisely determines the number and order of
 * trees that are rendered in parallel at their segment le


ver/request/params'
import { LayoutRouterContext } from '../../shared/lib/app-router-context.shared-runtime'
import { use } from 'react'
import { urlSearchParamsToParsedUrlQuery } from '../route-params'
import { SearchParamsContext } from '../../shared/lib/hooks-client-context.shared-runtime'

/**
 * When the Page is a client component we send the params and searchParams to this client wrapper
 * where they are turned into dynamically tracked values before being passed to the actual Page component.
 *
 * ad

o the caller to decide if the promises are needed.
 */
export function ClientPageRoot({
  Component,
  serverProvidedParams,
}: {
  Component: React.ComponentType<any>
  serverProvidedParams: null | {
    searchParams: ParsedUrlQuery
    params: Params

ditionally we may send promises representing the params and searchParams. We don't ever use these passed
 * values but it can be necessary for the sender to send a Promise that doesn't resolve in certain situations.
 * It is up t


 { Params } from '../../server/request/params'
import { LayoutRouterContext } from '../../shared/lib/app-router-context.shared-runtime'
import { use } from 'react'

/**
 * When the Page is a client component we send the params to this client wrapper
 * where they are turned into dynamically tracked values before being passed to the actual Segment component.
 *
 * additionally we may send a promise representing params. We don't ever use this passed
 * value but it can be necessary for the sender to send a Pr

dedParams,
}: {
  Component: React.ComponentType<any>
  slots: { [key: string]: React.ReactNode }
  serverProvidedParams: null | {
    params: Params
    promises: Array<Promise<any>> | null
  }
}) {
  let params: Params
  if (serverProvidedParams !== null

omise that doesn't resolve in certain situations
 * such as when cacheComponents is enabled. It is up to the caller to decide if the promises are needed.
 */
export function ClientSegmentRoot({
  Component,
  slots,
  serverProvi


import { ErrorBoundary } from './error-boundary'
import { disableSmoothScrollDuringRouteTransition } from '../../shared/lib/router/utils/disable-smooth-scroll'
import { RedirectBoundary } from './redirect-boundary'
import { HTTPAccessFallbackBoundary } from './http-access-fallback/error-boundary'
import { createRouterCacheKey } from './router-reducer/create-router-cache-key'
import {
  useRouterBFCache,
  type RouterBFCacheEntry,
} from './bfcache-state-manager'
import { normalizeAppPath } from '../../share

{ Params } from '../../server/request/params'
import { isDeferredRsc } from './router-reducer/ppr-navigations'

const enableNewScrollHandler = process.env.__NEXT_APP_NEW_SCROLL_HANDLER

const __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = (

d/lib/router/utils/app-paths'
import {
  NavigationPromisesContext,
  type NavigationPromises,
} from '../../shared/lib/hooks-client-context.shared-runtime'
import { getParamValueFromCacheKey } from '../route-params'
import type


 'react'
import { createHrefFromUrl } from './router-reducer/create-href-from-url'

export function handleHardNavError(error: unknown): boolean {
  if (
    typeof window !== 'undefined' &&
    window.next.__pendingUrl &&
    createHrefFromUrl(new URL(window.location.href)) !==
      createHrefFromUrl(window.next.__pendingUrl)
  ) {
    console.error(
      `Error occurred during navigation, falling back to hard navigation`,
      error
    )
    window.location.href = window.next.__pendingUrl.toString()

ct-hooks/rules-of-hooks
    useEffect(() => {
      const uncaughtExceptionHandler = (
        evt: ErrorEvent | PromiseRejectionEvent
      ) => {
        const error = 'reason' in evt ? evt.reason : evt.error
        // if we have an unhandled exception/

  return true
  }
  return false
}

export function useNavFailureHandler() {
  if (process.env.__NEXT_APP_NAV_FAIL_HANDLING) {
    // this if is only for DCE of the feature flag not conditional
    // eslint-disable-next-line rea


  result: 'pass' | 'fail' | 'skipped'
}

type TaskScript = () => Promise<TaskResult>

type PlatformTaskScript =
  | {
      win32: TaskScript
      linux?: TaskScript
      darwin?: TaskScript
      default?: TaskScript
    }
  | {
      linux: TaskScript
      win32?: TaskScript
      darwin?: TaskScript
      default?: TaskScript
    }
  | {
      darwin: TaskScript
      win32?: TaskScript
      linux?: TaskScript
      default?: TaskScript
    }
  | {
      // A common task script if task does not need

ackage.json`).version
  } catch {
    return 'N/A'
  }
}

async function getNextConfig() {
  const config = await loadConfig(PHASE_INFO, process.cwd())

  return {
    output: config.output ?? 'N/A',
    experimental: {
      useWasmBinary: config.experime

 to be platform specific.
      default: TaskScript
      win32?: TaskScript
      linux?: TaskScript
      darwin?: TaskScript
    }

function getPackageVersion(packageName: string) {
  try {
    return require(`${packageName}/p


lare const __webpack_require__: any
declare let __webpack_public_path__: string

import { getAssetToken, getAssetTokenQuery } from '../shared/lib/deployment-id'

// If we have a deployment ID query string, we need to append it to the webpack chunk names
// I am keeping the process check explicit so this can be statically optimized
if (getAssetToken()) {
  const suffix = getAssetTokenQuery()
  const getChunkScriptFilename = __webpack_require__.u
  __webpack_require__.u = (...args: any[]) =>
    // We enode t

ny[]) =>
    getChunkCssFilename(...args) + suffix

  const getMiniCssFilename = __webpack_require__.miniCssF
  __webpack_require__.miniCssF = (...args: any[]) =>
    getMiniCssFilename(...args) + suffix
}

// Ignore the module ID transform in client.
;(se

he chunk filename because our static server matches against and encoded
    // filename path.
    getChunkScriptFilename(...args) + suffix

  const getChunkCssFilename = __webpack_require__.k
  __webpack_require__.k = (...args: a


{ ComponentProps } from 'react'
import ClientLinkComponent, { type LinkProps, useLinkStatus } from './link'

export default function LinkComponent(
  props: ComponentProps<typeof ClientLinkComponent>
) {
  const isLegacyBehavior = props.legacyBehavior
  const childIsHostComponent =
    typeof props.children === 'string' ||
    typeof props.children === 'number' ||
    typeof (props.children as any)?.type === 'string'
  const childIsClientComponent =
    (props.children as any)?.type?.$$typeof ===
    Symbol

azy Component as a direct child of \`<Link legacyBehavior>\` from a Server Component is not supported. If you need legacyBehavior, wrap your Lazy Component in a Client Component that renders the Link's \`<a>\` tag.`
      )
    } else {
      console.error

.for('react.client.reference')

  if (isLegacyBehavior && !childIsHostComponent && !childIsClientComponent) {
    if ((props.children as any)?.type?.$$typeof === Symbol.for('react.lazy')) {
      console.error(
        `Using a L


Info } from 'react'
import { isNextRouterError } from '../components/is-next-router-error'
import { isBailoutToCSRError } from '../../shared/lib/lazy-dynamic/bailout-to-csr'
import { reportGlobalError } from './report-global-error'
import { ErrorBoundaryHandler } from '../components/error-boundary'
import DefaultErrorBoundary from '../components/builtin/global-error'

const devToolErrorMod: typeof import('../../next-devtools/userspace/app/errors') =
  process.env.NODE_ENV !== 'production'
    ? (require('..

leError: console.error.bind(console),
      }

export function onCaughtError(
  thrownValue: unknown,
  errorInfo: ErrorInfo & { errorBoundary?: React.Component }
) {
  const errorBoundaryComponent = errorInfo.errorBoundary?.constructor

  let isImplicitEr

/../next-devtools/userspace/app/errors') as typeof import('../../next-devtools/userspace/app/errors'))
    : {
        decorateDevError: (error: unknown) => error as Error,
        handleClientError: () => {},
        originConso


red between both pages router and app router

import type { HydrationOptions } from 'react-dom/client'
import { isBailoutToCSRError } from '../../shared/lib/lazy-dynamic/bailout-to-csr'
import isError from '../../lib/is-error'
import { reportGlobalError } from './report-global-error'

const recoverableErrors = new WeakSet<Error>()

const isInstantTest =
  process.env.__NEXT_EXPOSE_TESTING_API &&
  typeof self !== 'undefined' &&
  !!self.__next_instant_test

export function isRecoverableError(error: Error):

& 'cause' in error ? error.cause : error
  // Skip certain custom errors which are not expected to be reported on client
  if (isBailoutToCSRError(cause)) return

  // Instant Navigation Testing API: suppress "server could not finish this
  // Suspense bou

boolean {
  return recoverableErrors.has(error)
}

export const onRecoverableError: HydrationOptions['onRecoverableError'] = (
  error
) => {
  // x-ref: https://github.com/facebook/react/pull/28736
  let cause = isError(error) &


,
  type InstrumentedPromise,
  type NavigationPromises,
} from '../../shared/lib/hooks-client-context.shared-runtime'
import {
  computeSelectedLayoutSegment,
  getSelectedLayoutSegmentPath,
} from '../../shared/lib/segment'

/**
 * Promises are cached by tree to ensure stability across suspense retries.
 */
type LayoutSegmentPromisesCache = {
  selectedLayoutSegmentPromises: Map<string, InstrumentedPromise<string | null>>
  selectedLayoutSegmentsPromises: Map<string, InstrumentedPromise<string[]>>
}

cons

evTools instrumentation.
 */
function createLayoutSegmentPromises(
  tree: FlightRouterState
): LayoutSegmentPromisesCache | null {
  if (process.env.NODE_ENV === 'production') {
    return null
  }

  // Check if we already have cached promises for this t

t layoutSegmentPromisesCache = new WeakMap<
  FlightRouterState,
  LayoutSegmentPromisesCache
>()

/**
 * Creates instrumented promises for layout segment hooks at a given tree level.
 * This is dev-only code for React Suspense D


ks-client-context.shared-runtime'
import {
  computeSelectedLayoutSegment,
  getSelectedLayoutSegmentPath,
} from '../../shared/lib/segment'

const useDynamicRouteParams =
  typeof window === 'undefined'
    ? (
        require('../../server/app-render/dynamic-rendering') as typeof import('../../server/app-render/dynamic-rendering')
      ).useDynamicRouteParams
    : undefined

const useDynamicSearchParams =
  typeof window === 'undefined'
    ? (
        require('../../server/app-render/dynamic-rendering'

lientValidation,
} =
  typeof window === 'undefined' && process.env.__NEXT_CACHE_COMPONENTS
    ? (require('../../server/app-render/instant-validation/instant-samples-client') as typeof import('../../server/app-render/instant-validation/instant-samples-cli

) as typeof import('../../server/app-render/dynamic-rendering')
      ).useDynamicSearchParams
    : undefined

const {
  instrumentParamsForClientValidation,
  instrumentSearchParamsForClientValidation,
  expectCompleteParamsInC


 to be extended in the
 * future — e.g., instrumenting module chunk loading, Flight chunk resolution,
 * or eventually being promoted to a React-level feature.
 *
 * All stateful behavior (event listeners, polling, state tracking) only runs
 * in the browser. On the server and during hydration, getOffline() always
 * returns false.
 *
 * ## Known limitation: queued fetches
 *
 * When the user navigates multiple times while offline, each navigation queues
 * a separate fetch that blocks on waitForConnection(

 issue new fetches at all. This is
 *   the primary shield against duplicate requests.
 * - Fetch cancellation: on router.refresh(), we could abort pending blocked
 *   fetches since refresh invalidates all dynamic caches.
 */

// Backoff delays for the po

). When connectivity is
 * restored, all of them resume and retry simultaneously.
 *
 * Future mitigations:
 * - Stale cache access (PR 3): offline navigations will reuse back-forward
 *   cache entries, so most navigations won't


import { createPortal } from 'react-dom'
import type { FlightRouterState } from '../../shared/lib/app-router-types'

const ANNOUNCER_TYPE = 'next-route-announcer'
const ANNOUNCER_ID = '__next-route-announcer__'

function getAnnouncerNode() {
  const existingAnnouncer = document.getElementsByName(ANNOUNCER_TYPE)[0]
  if (existingAnnouncer?.shadowRoot?.childNodes[0]) {
    return existingAnnouncer.shadowRoot.childNodes[0] as HTMLElement
  } else {
    const container = document.createElement(ANNOUNCER_TYPE)

      'position:absolute;border:0;height:1px;margin:-1px;padding:0;width:1px;clip:rect(0 0 0 0);overflow:hidden;white-space:nowrap;word-wrap:normal'

    // Use shadow DOM here to avoid any potential CSS bleed
    const shadow = container.attachShadow({ m

    container.style.cssText = 'position:absolute'
    const announcer = document.createElement('div')
    announcer.ariaLive = 'assertive'
    announcer.id = ANNOUNCER_ID
    announcer.role = 'alert'
    announcer.style.cssText =


from 'react'
import { isThenable } from '../../shared/lib/is-thenable'
import {
  FetchStrategy,
  type PrefetchTaskFetchStrategy,
} from './segment-cache/types'
import { prefetch as prefetchWithSegmentCache } from './segment-cache/prefetch'
import { navigate } from './segment-cache/navigation'
import {
  dispatchAppRouterAction,
  dispatchGestureState,
} from './use-action-queue'
import { resetKnownRoutes } from './segment-cache/optimistic-routes'
import { FreshnessPolicy } from './router-reducer/ppr-navig

-runtime'
import { setLinkForCurrentNavigation, type LinkInstance } from './links'
import type { ClientInstrumentationHooks } from '../app-index'
import type { GlobalErrorComponent } from './builtin/global-error'
import { isJavaScriptURLString } from '../l

ations'
import { addBasePath } from '../add-base-path'
import { isExternalURL } from './app-router-utils'
import type {
  AppRouterInstance,
  NavigateOptions,
  PrefetchOptions,
} from '../../shared/lib/app-router-context.shared


rom 'react'

import { useUntrackedPathname } from './navigation-untracked'
import { isNextRouterError } from './is-next-router-error'
import { handleHardNavError } from './nav-failure-handler'
import { handleISRError } from './handle-isr-error'
import { isBot } from '../../shared/lib/router/utils/is-bot'
import { AppRouterContext } from '../../shared/lib/app-router-context.shared-runtime'
import { RouterContext as PagesRouterContext } from '../../shared/lib/router-context.shared-runtime'

const isBotUserAge

omponentType<{
    props: P
    errorInfo: ErrorInfo
  }>
  props: P
  children: React.ReactNode
}

type CatchErrorState = {
  error: null | { thrownValue: unknown }
  previousPathname: string | null
}

// This is forked from error-boundary.
// TODO: Exten

nt =
  typeof window !== 'undefined' && isBot(window.navigator.userAgent)

type UserProps = Record<string, any>

type CatchErrorProps<P extends UserProps> = {
  pathname: string | null
  isPagesRouter: boolean
  fallback: React.C


TTP_ERROR_FALLBACK_ERROR_CODE,
  type HTTPAccessFallbackError,
} from './http-access-fallback/http-access-fallback'

// TODO: Add `forbidden` docs
/**
 * @experimental
 * This function allows you to render the [forbidden.js file](https://nextjs.org/docs/app/api-reference/file-conventions/forbidden)
 * within a route segment as well as inject a tag.
 *
 * `forbidden()` can be used in
 * [Server Components](https://nextjs.org/docs/app/building-your-application/rendering/server-components),
 * [Route Handlers]

Docs: `forbidden`](https://nextjs.org/docs/app/api-reference/functions/forbidden)
 */

const DIGEST = `${HTTP_ERROR_FALLBACK_ERROR_CODE};403`

export function forbidden(): never {
  if (!process.env.__NEXT_EXPERIMENTAL_AUTH_INTERRUPTS) {
    throw new Erro

(https://nextjs.org/docs/app/building-your-application/routing/route-handlers), and
 * [Server Actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations).
 *
 * Read more: [Next.js


es,
  getTraceEvents,
  initializeTraceState,
  recordTraceEvents,
  trace,
} from './trace'

describe('Trace', () => {
  beforeEach(() => {
    initializeTraceState({
      lastId: 0,
      shouldSaveTraceEvents: true,
    })
    clearTraceEvents()
  })

  describe('Tracer', () => {
    it('traces a block of code', async () => {
      const tmpDir = await mkdtemp(join(tmpdir(), 'json-reporter'))
      setGlobal('distDir', tmpDir)
      setGlobal('phase', 'anything')

      const root = trace('root-span', u

(resolve) => {
          setTimeout(resolve, 100)
        })
        await delayedPromise
      })
      root.stop()
      const traceEvents = getTraceEvents()
      expect(traceEvents.length).toEqual(3)
      expect(traceEvents[0].name).toEqual('child-spa

ndefined, {
        'some-tag': 'some-value',
      })
      root.traceChild('child-span').traceFn(() => null)
      await root.traceChild('async-child-span').traceAsyncFn(async () => {
        const delayedPromise = new Promise(


 React, { type JSX } from 'react'
import type {
  BaseContext,
  NextComponentType,
  NextPageContext,
} from '../shared/lib/utils'
import type { NextRouter } from './router'
import { useRouter } from './router'

export type WithRouterProps = {
  router: NextRouter
}

export type ExcludeRouterProps<P> = Pick<
  P,
  Exclude<keyof P, keyof WithRouterProps>
>

export default function withRouter<
  P extends WithRouterProps,
  C extends BaseContext = NextPageContext,
>(
  ComposedComponent: NextComponentType<C

dComponent.getInitialProps
  // This is needed to allow checking for custom getInitialProps in _app
  ;(WithRouterWrapper as any).origGetInitialProps = (
    ComposedComponent as any
  ).origGetInitialProps
  if (process.env.NODE_ENV !== 'production') {

, any, P>
): React.ComponentType<ExcludeRouterProps<P>> {
  function WithRouterWrapper(props: any): JSX.Element {
    return <ComposedComponent router={useRouter()} {...props} />
  }

  WithRouterWrapper.getInitialProps = Compose


e ImageLoader = (resolverProps: ImageLoaderProps) => string

export type ImageLoaderProps = {
  src: string
  width: number
  quality?: number
}

// Do not export - this is an internal type only
// because `next.config.js` is only meant for the
// built-in loaders, not for a custom loader() prop.
type ImageLoaderWithConfig = (
  resolverProps: ImageLoaderPropsWithConfig
) => string
type ImageLoaderPropsWithConfig = ImageLoaderProps & {
  config: Readonly<ImageConfig>
}

function imgixLoader({
  config,
  sr

  // auto params can be combined with comma separation, or reiteration
  params.set('auto', params.getAll('auto').join(',') || 'format')
  params.set('fit', params.get('fit') || 'max')
  params.set('w', params.get('w') || width.toString())

  if (quality

c,
  width,
  quality,
}: ImageLoaderPropsWithConfig): string {
  // Demo: https://static.imgix.net/daisy.png?auto=format&fit=max&w=300
  const url = new URL(`${config.path}${normalizeSrc(src)}`)
  const params = url.searchParams


eContext } from '../../shared/lib/hooks-client-context.shared-runtime'

/**
 * This checks to see if the current render has any unknown route parameters that
 * would cause the pathname to be dynamic. It's used to trigger a different
 * render path in the error boundary.
 *
 * @returns true if there are any unknown route parameters, false otherwise
 */
function hasFallbackRouteParams(): boolean {
  if (typeof window === 'undefined') {
    // AsyncLocalStorage should not be included in the client bundle.

age.getStore()
    if (!workUnitStore) return false

    switch (workUnitStore.type) {
      case 'prerender':
      case 'prerender-client':
      case 'prerender-ppr':
      case 'validation-client':
        const fallbackParams = workUnitStore.fallbackR

 const { workUnitAsyncStorage } =
      require('../../server/app-render/work-unit-async-storage.external') as typeof import('../../server/app-render/work-unit-async-storage.external')

    const workUnitStore = workUnitAsyncStor


uestIdleCallback } from '../request-idle-callback'

// 3.8s was arbitrarily chosen as it's what https://web.dev/interactive
// considers as "Good" time-to-interactive. We must assume something went
// wrong beyond this point, and then fall-back to a full page transition to
// show the user something of value.
const MS_MAX_IDLE_DELAY = 3800

/** Resolve a promise that times out after given amount of milliseconds. */
export function resolvePromiseWithTimeout<T>(
  p: Promise<T>,
  err: Error,
  devPromise: Pr

    // We wrap these checks separately for better dead-code elimination in
    // production bundles.
    if (process.env.NODE_ENV === 'development') {
      ;(devPromise || Promise.resolve()).then(() => {
        requestIdleCallback(() =>
          setT

omise<void> | undefined
): Promise<T> {
  return new Promise((resolve, reject) => {
    let cancelled = false

    p.then((r) => {
      // Resolved, cancel the timeout
      cancelled = true
      resolve(r)
    }).catch(reject)


dleHardNavError } from './nav-failure-handler'
import { handleISRError } from './handle-isr-error'
import { isBot } from '../../shared/lib/router/utils/is-bot'
import {
  AppRouterContext,
  type AppRouterInstance,
} from '../../shared/lib/app-router-context.shared-runtime'

const isBotUserAgent =
  typeof window !== 'undefined' && isBot(window.navigator.userAgent)

export type ErrorInfo = {
  error: unknown
  reset: () => void
  unstable_retry: () => void
}

export type ErrorComponent = React.ComponentType

rorBoundaryHandlerProps extends ErrorBoundaryProps {
  pathname: string | null
  errorComponent: ErrorComponent
}

interface ErrorBoundaryHandlerState {
  error: null | { thrownValue: unknown }
  previousPathname: string | null
}

export class ErrorBoundar

<ErrorInfo>

export interface ErrorBoundaryProps {
  children?: React.ReactNode
  errorComponent: ErrorComponent | undefined
  errorStyles?: React.ReactNode | undefined
  errorScripts?: React.ReactNode | undefined
}

interface Er


-action-queue'
import { setLastCommittedTree } from './router-reducer/reducers/committed-state'
import { AppRouterAnnouncer } from './app-router-announcer'
import { RedirectBoundary } from './redirect-boundary'
import { findHeadInCache } from './router-reducer/reducers/find-head-in-cache'
import { unresolvedThenable } from './unresolved-thenable'
import { removeBasePath } from '../remove-base-path'
import { hasBasePath } from '../has-base-path'
import {
  extractSourcePageFromFlightRouterState,
  getSelecte

te,
} from './app-router-instance'
import { getRedirectTypeFromError, getURLFromRedirectError } from './redirect'
import { isRedirectError } from './redirect-error'
import { pingVisibleLinks } from './links'
import RootErrorBoundary from './errors/root-err

dParams,
} from './router-reducer/compute-changed-path'
import { useNavFailureHandler } from './nav-failure-handler'
import {
  dispatchTraverseAction,
  publicAppRouterInstance,
  type AppRouterActionQueue,
  type GlobalErrorSta


adable: ReadableStream<Uint8Array>
  readonly writer: WritableStreamDefaultWriter<Uint8Array>
}

const pairs = new Map<string, DebugChannelReadableWriterPair>()

const DEBUG_CHANNEL_STORAGE_KEY_PREFIX = '__next_debug_channel:'

// Buffer for the initial document's debug channel data. Written to
// sessionStorage once complete so it can be restored when the browser serves
// the page from HTTP cache (back-forward navigation, tab duplication, etc.).
let initialDocumentDebugChunks: Uint8Array[] = []

function

 for (let i = 0; i < chunk.byteLength; i++) {
        binary += String.fromCharCode(chunk[i])
      }
      return btoa(binary)
    })
  )

  try {
    sessionStorage.setItem(key, value)
  } catch {
    // Likely a quota error. Drop entries from previous d

persistDebugChannelToSessionStorage(requestId: string): void {
  const key = DEBUG_CHANNEL_STORAGE_KEY_PREFIX + requestId
  const value = JSON.stringify(
    initialDocumentDebugChunks.map((chunk) => {
      let binary = ''


s wrapper function is used to safely select the best available function
// to schedule removal of the no-FOUC styles workaround. requestAnimationFrame
// is the ideal choice, but when used in iframes, there are no guarantees that
// the callback will actually be called, which could stall the promise returned
// from displayContent.
//
// See: https://www.vector-logic.com/blog/posts/on-request-animation-frame-and-embedded-iframes
const safeCallbackQueue = (callback: () => void) => {
  if (window.requestAnima

der` in development. It must be called before hydration, or else
// rendering won't have the correct computed values in effects.
export function displayContent(): Promise<void> {
  return new Promise((resolve) => {
    safeCallbackQueue(function () {

tionFrame && window.self === window.top) {
    window.requestAnimationFrame(callback)
  } else {
    window.setTimeout(callback)
  }
}

// This function is used to remove Next.js' no-FOUC styles workaround for using
// `style-loa


server/dev/hot-reloader-types'
import type {
  NextRouter,
  PrivateRouteInfo,
} from '../../shared/lib/router/router'
import connect from './hot-reloader/pages/hot-reloader-pages'
import { sendMessage } from './hot-reloader/pages/websocket'

// Define a local type for the window.next object
interface NextWindow {
  next?: {
    router?: NextRouter & {
      components: { [pathname: string]: PrivateRouteInfo }
    }
  }
  __nextDevClientId?: string
  location: Location
}

declare const window: NextWindow

l

uter

    // Determine if we're on an error page or the router is not initialized
    const isOnErrorPage =
      !router || router.pathname === '/404' || router.pathname === '/_error'

    switch (message.type) {
      case HMR_MESSAGE_SENT_TO_BROWSER.REL

et reloading = false

export default () => {
  const devClient = connect()

  devClient.subscribeToHmrEvent((message) => {
    if (reloading) return

    // Retrieve the router if it's available
    const router = window.next?.ro


xport default async () => {
  // Never send pings when using Turbopack as it's not used.
  // Pings were originally used to keep track of active routes in on-demand-entries with webpack.
  if (process.env.TURBOPACK) {
    return
  }

  Router.ready(() => {
    setInterval(() => {
      // when notFound: true is returned we should use the notFoundPage
      // as the Router.pathname will point to the 404 page but we want
      // to ping the source page that returned notFound: true instead
      const notFou

 const pathname =
        (Router.pathname === '/404' || Router.pathname === '/_error') &&
        notFoundSrcPage
          ? notFoundSrcPage
          : Router.pathname

      sendMessage(JSON.stringify({ event: 'ping', page: pathname }))
    }, 2500)


ace Window {
    __NEXT_HMR_LATENCY_CB: ((latencyMs: number) => void) | undefined
  }
}

/**
 * Logs information about a completed HMR to the console, the server (via a
 * `client-hmr-latency` event), and to `self.__NEXT_HMR_LATENCY_CB` (a debugging
 * hook).
 *
 * @param hasUpdate Set this to `false` to avoid reporting the HMR event via a
 *   `client-hmr-latency` event or to `self.__NEXT_HMR_LATENCY_CB`. Used by
 *   turbopack when we must report a message to the browser console (because we
 *   already l

 | number>,
  startMsSinceEpoch: number,
  endMsSinceEpoch: number,
  hasUpdate: boolean = true
) {
  const latencyMs = endMsSinceEpoch - startMsSinceEpoch
  console.log(`[Fast Refresh] done in ${latencyMs}ms`)
  if (!hasUpdate) {
    return
  }
  sendMess

ogged a "rebuilding" message), but it's not a real HMR, so we
 *   don't want to impact our telemetry.
 */
export default function reportHmrLatency(
  sendMessage: (message: string) => void,
  updatedModules: ReadonlyArray<string


ormalizedAssetPrefix } from '../../../shared/lib/normalized-asset-prefix'

function getSocketProtocol(assetPrefix: string): string {
  let protocol = window.location.protocol

  try {
    // assetPrefix is a url
    protocol = new URL(assetPrefix).protocol
  } catch {}

  return protocol === 'http:' ? 'ws:' : 'wss:'
}

export function getSocketUrl(assetPrefix: string | undefined): string {
  const prefix = normalizedAssetPrefix(assetPrefix)
  const protocol = getSocketProtocol(assetPrefix || '')

  if (URL.

x)) {
    // since normalized asset prefix is ensured to be a URL format,
    // we can safely replace the protocol
    return prefix.replace(/^http/, 'ws')
  }

  const { hostname, port } = window.location
  return `${protocol}//${hostname}${port ? `:${po


 type { HmrMessageSentToBrowser } from '../../../server/dev/hot-reloader-types'

export const REACT_REFRESH_FULL_RELOAD =
  '[Fast Refresh] performing full reload\n\n' +
  "Fast Refresh will perform a full reload when you edit a file that's imported by modules outside of the React rendering tree.\n" +
  'You might have a file which exports a React component but also exports a value that is imported by a non-React component file.\n' +
  'Consider migrating the non-React component export to a separate file an

t in your React tree.'

export const REACT_REFRESH_FULL_RELOAD_FROM_ERROR =
  '[Fast Refresh] performing full reload because your application had an unrecoverable error'

export function reportInvalidHmrMessage(
  message: HmrMessageSentToBrowser | Message

d importing it into both files.\n\n' +
  'It is also possible the parent component of the component you edited is a class component, which disables Fast Refresh.\n' +
  'Fast Refresh requires at least one parent function componen


 TurbopackUpdate } from '../../../build/swc/types'

declare global {
  interface Window {
    __NEXT_HMR_TURBOPACK_REPORT_NOISY_NOOP_EVENTS: boolean | undefined
  }
}

// How long to wait before reporting the HMR start, used to suppress irrelevant
// `BUILDING` events. Does not impact reported latency.
const TURBOPACK_HMR_START_DELAY_MS = 100

interface HmrUpdate {
  hasUpdates: boolean
  updatedModules: Set<string>
  startMsSinceEpoch: number
  endMsSinceEpoch: number
}

export class TurbopackHmr {
  #upda

    this.#updatedModules = new Set()
    this.#reportedHmrStart = false
  }

  // HACK: Turbopack tends to generate a lot of irrelevant "BUILDING" actions,
  // as it reports *any* compilation, including fully no-op/cached compilations
  // and those unre

tedModules: Set<string>
  #startMsSinceEpoch: number | undefined
  #lastUpdateMsSinceEpoch: number | undefined
  #deferredReportHmrStartId: ReturnType<typeof setTimeout> | undefined
  #reportedHmrStart: boolean

  constructor() {


T_REQUEST_ID_HEADER,
} from '../app-router-headers'
import { callServer } from '../../app-call-server'
import { findSourceMapURL } from '../../app-find-source-map-url'
import {
  normalizeFlightData,
  prepareFlightRouterStateForRequest,
  type NormalizedFlightData,
} from '../../flight-data-helpers'
import { setCacheBustingSearchParam } from './set-cache-busting-search-param'
import { urlToUrlWithoutFlightMarker } from '../../route-params'
import type { NormalizedSearch } from '../segment-cache/cache-key'

Byte,
  createNonTaskyPrefetchResponseStream,
} from '../segment-cache/cache'
import { UnknownDynamicStaleTime } from '../segment-cache/bfcache'

const createFromReadableStream =
  createFromReadableStreamBrowser as (typeof import('react-server-dom-webpack

import { getDeploymentId } from '../../../shared/lib/deployment-id'
import { getNavigationBuildId } from '../../navigation-build-id'
import { NEXT_NAV_DEPLOYMENT_ID_HEADER } from '../../../lib/constants'
import {
  stripIsPartial


ared/lib/app-router-types'
import { PrefetchHint } from '../../../shared/lib/app-router-types'
import type { RouteTree } from '../segment-cache/cache'

export function isNavigatingToNewRootLayout(
  currentTree: FlightRouterState,
  nextTree: RouteTree
): boolean {
  // Compare segments
  const currentTreeSegment = currentTree[0]
  const nextTreeSegment = nextTree.segment

  // If any segment is different before we find the root layout, the root layout has changed.
  // E.g. /same/(group1)/layout.js -> /sam

nt)) {
    // Compare dynamic param name and type but ignore the value, different values would not affect the current root layout
    // /[name] - /slug1 and /slug2, both values (slug1 & slug2) still has the same layout /[name]/layout.js
    if (
      cur

e/(group2)/layout.js
  // First segment is 'same' for both, keep looking. (group1) changed to (group2) before the root layout was found, it must have changed.
  if (Array.isArray(currentTreeSegment) && Array.isArray(nextTreeSegme


E,
  ACTION_SERVER_PATCH,
  ACTION_RESTORE,
  ACTION_REFRESH,
  ACTION_HMR_REFRESH,
  ACTION_SERVER_ACTION,
} from './router-reducer-types'
import type {
  ReducerActions,
  ReducerState,
  ReadonlyReducerState,
} from './router-reducer-types'
import { navigateReducer } from './reducers/navigate-reducer'
import { serverPatchReducer } from './reducers/server-patch-reducer'
import { restoreReducer } from './reducers/restore-reducer'
import { refreshReducer } from './reducers/refresh-reducer'
import { hmrRefre

cerState,
  action: ReducerActions
): ReducerState {
  switch (action.type) {
    case ACTION_NAVIGATE: {
      return navigateReducer(state, action)
    }
    case ACTION_SERVER_PATCH: {
      return serverPatchReducer(state, action)
    }
    case ACTION

shReducer } from './reducers/hmr-refresh-reducer'
import { serverActionReducer } from './reducers/server-action-reducer'

/**
 * Reducer that handles the app-router state updates.
 */
function clientReducer(
  state: ReadonlyRedu


m '../../../shared/lib/router/utils/cache-busting-search-param'
import {
  NEXT_ROUTER_PREFETCH_HEADER,
  NEXT_ROUTER_SEGMENT_PREFETCH_HEADER,
  NEXT_ROUTER_STATE_TREE_HEADER,
  NEXT_URL,
  NEXT_RSC_UNION_QUERY,
} from '../app-router-headers'
import type { RequestHeaders } from './fetch-server-response'

async function computeClientCacheBustingSearchParam(
  headers: RequestHeaders
): Promise<string> {
  if (typeof globalThis.crypto?.subtle?.digest === 'function') {
    return computeCacheBustingSearchParam

 headers[NEXT_ROUTER_PREFETCH_HEADER],
    headers[NEXT_ROUTER_SEGMENT_PREFETCH_HEADER],
    headers[NEXT_ROUTER_STATE_TREE_HEADER],
    headers[NEXT_URL]
  )
}

/**
 * Mutates the provided URL by adding a cache-busting search parameter for CDNs that don't

(
      headers[NEXT_ROUTER_PREFETCH_HEADER],
      headers[NEXT_ROUTER_SEGMENT_PREFETCH_HEADER],
      headers[NEXT_ROUTER_STATE_TREE_HEADER],
      headers[NEXT_URL]
    )
  }

  return computeLegacyCacheBustingSearchParam(


 type {
  FlightRouterState,
  FlightDataPath,
  Segment,
} from '../../../shared/lib/app-router-types'
import { getNextFlightSegmentPath } from '../../flight-data-helpers'
import { matchSegment } from '../match-segments'

// TODO-APP: flightSegmentPath will be empty in case of static response, needs to be handled.
export function shouldHardNavigate(
  flightSegmentPath: FlightDataPath,
  flightRouterState: FlightRouterState
): boolean {
  const [segment, parallelRoutes] = flightRouterState
  // TODO-APP: C

nt)) {
    // If dynamic parameter in tree doesn't match up with segment path a hard navigation is triggered.
    if (Array.isArray(currentSegment)) {
      return true
    }

    // If the existing segment did not match soft navigation is triggered.
    r

heck if `as` can be replaced.
  const [currentSegment, parallelRouteKey] = flightSegmentPath as [
    Segment,
    string,
  ]

  // Check if current segment matches the existing segment.
  if (!matchSegment(currentSegment, segme


rom '../../../../shared/lib/app-router-types'
import { DEFAULT_SEGMENT_KEY } from '../../../../shared/lib/segment'
import { createRouterCacheKey } from '../create-router-cache-key'

export function findHeadInCache(
  cache: CacheNode,
  parallelRoutes: FlightRouterState[1]
): [CacheNode, string, string] | null {
  return findHeadInCacheImpl(cache, parallelRoutes, '', '')
}

function findHeadInCacheImpl(
  cache: CacheNode,
  parallelRoutes: FlightRouterState[1],
  keyPrefix: string,
  keyPrefixWithoutSearch

ache, keyPrefix, keyPrefixWithoutSearchParams]
  }

  // First try the 'children' parallel route if it exists
  // when starting from the "root", this corresponds with the main page component
  const parallelRoutesKeys = Object.keys(parallelRoutes).filter(

Params: string
): [CacheNode, string, string] | null {
  const isLastItem = Object.keys(parallelRoutes).length === 0
  if (isLastItem) {
    // Returns the entire Cache Node of the segment whose head we will render.
    return [c


 type { FlightRouterState } from '../../../../shared/lib/app-router-types'
import { isInterceptionRouteAppPath } from '../../../../shared/lib/router/utils/interception-routes'

export function hasInterceptionRouteInCurrentTree([
  segment,
  parallelRoutes,
]: FlightRouterState): boolean {
  // If we have a dynamic segment, it's marked as an interception route by the presence of the `i` suffix.
  if (
    Array.isArray(segment) &&
    (segment[2] === 'di(..)(..)' ||
      segment[2] === 'ci(..)(..)' ||

gment is not an array, apply the existing string-based check
  if (typeof segment === 'string' && isInterceptionRouteAppPath(segment)) {
    return true
  }

  // Iterate through parallelRoutes if they exist
  if (parallelRoutes) {
    for (const key in pa


'
import { extractPathFromFlightRouterState } from '../compute-changed-path'
import {
  FreshnessPolicy,
  spawnDynamicRequests,
  startPPRNavigation,
  type NavigationRequestAccumulation,
} from '../ppr-navigations'
import type { FlightRouterState } from '../../../../shared/lib/app-router-types'
import {
  completeHardNavigation,
  completeTraverseNavigation,
  convertServerPatchToFullTree,
} from '../../segment-cache/navigation'
import { UnknownDynamicStaleTime } from '../../segment-cache/bfcache'

export

 longer contains the `FlightRouterState`.
  // We will copy over the internal state on pushState/replaceState events, but if a history entry
  // occurred before hydration, or if the user navigated to a hash using a regular anchor link,
  // the history st

 function restoreReducer(
  state: ReadonlyReducerState,
  action: RestoreAction
): ReducerState {
  // This action is used to restore the router state from the history state.
  // However, it's possible that the history state no


rom-url'
import {
  ACTION_REFRESH,
  type ServerPatchAction,
  type ReducerState,
  type ReadonlyReducerState,
  ScrollBehavior,
} from '../router-reducer-types'
import {
  completeHardNavigation,
  navigateToKnownRoute,
} from '../../segment-cache/navigation'
import { refreshReducer } from './refresh-reducer'
import { FreshnessPolicy } from '../ppr-navigations'

export function serverPatchReducer(
  state: ReadonlyReducerState,
  action: ServerPatchAction
): ReducerState {
  // A "retry" is a navigation t

  const retryMpa = action.mpa
  const retryUrl = new URL(action.url, location.origin)
  const retrySeed = action.seed
  const navigateType = action.navigateType
  if (retryMpa || retrySeed === null) {
    // If the server did not send back data during the

hat happens due to a route mismatch. It's
  // similar to a refresh, because we will omit any existing dynamic data on
  // the page. But we seed the retry navigation with the exact tree that the
  // server just responded with.


egradeBoundary from './graceful-degrade-boundary'
import { ErrorBoundary, type ErrorBoundaryProps } from '../error-boundary'
import { isBot } from '../../../shared/lib/router/utils/is-bot'

const isBotUserAgent =
  typeof window !== 'undefined' && isBot(window.navigator.userAgent)

export default function RootErrorBoundary({
  children,
  errorComponent,
  errorStyles,
  errorScripts,
}: ErrorBoundaryProps & { children: React.ReactNode }): JSX.Element {
  if (isBotUserAgent) {
    // Preserve existing DOM/H

r UI
    // and to keep the original SSR output intact.
    return <GracefulDegradeBoundary>{children}</GracefulDegradeBoundary>
  }

  return (
    <ErrorBoundary
      errorComponent={errorComponent}
      errorStyles={errorStyles}
      errorScripts={er

TML for bots to avoid replacing content with an erro


h (typeof arg) {
    case 'object':
      if (arg === null) {
        return 'null'
      } else if (Array.isArray(arg)) {
        let result = '['
        if (depth < 1) {
          for (let i = 0; i < arg.length; i++) {
            if (result !== '[') {
              result += ','
            }
            if (Object.prototype.hasOwnProperty.call(arg, i)) {
              result += formatObject(arg[i], depth + 1)
            }
          }
        } else {
          result += arg.length > 0 ? '...' : ''

for (let i = 0; i < keys.length; i++) {
            const key = keys[i]
            const desc = Object.getOwnPropertyDescriptor(arg, 'key')
            if (desc && !desc.get && !desc.set) {
              const jsonKey = JSON.stringify(key)
              i

     }
        result += ']'
        return result
      } else if (arg instanceof Error) {
        return arg + ''
      } else {
        const keys = Object.keys(arg)
        let result = '{'
        if (depth < 1) {


 createHrefFromUrl } from './create-href-from-url'

describe('createHrefFromUrl', () => {
  it('returns a string', () => {
    const url = new URL('https://example.com/')
    expect(createHrefFromUrl(url)).toBe('/')
  })

  it('adds hash', () => {
    const url = new URL('https://example.com/#hash')
    expect(createHrefFromUrl(url)).toBe('/#hash')
  })

  it('adds searchParams', () => {
    const url = new URL('https://example.com/?a=1&b=2')
    expect(createHrefFromUrl(url)).toBe('/?a=1&b=2')
  })

  it('

ps://example.com/path')
    expect(createHrefFromUrl(url)).toBe('/path')
  })

  it('adds pathname, searchParams, and hash', () => {
    const url = new URL('https://example.com/path?a=1&b=2#hash')
    expect(createHrefFromUrl(url)).toBe('/path?a=1&b=2#has

adds pathname', () => {
    const url = new URL('htt


laywright/test'
import type { NextFixture } from './next-fixture'
import type { NextOptions, NextOptionsConfig } from './next-options'
import type { NextWorkerFixture } from './next-worker-fixture'
import { applyNextWorkerFixture } from './next-worker-fixture'
import { applyNextFixture } from './next-fixture'
import { defaultPlaywrightConfig } from './default-config'

export { defaultPlaywrightConfig }

export * from '@playwright/test'

// Export this second so it overrides the one from `@playwright/test`
e

se.PlaywrightTestConfig<T>
): base.PlaywrightTestConfig<T> {
  if (config.webServer !== undefined) {
    // Playwright doesn't merge the `webServer` field as we'd expect, so remove our default if the user specifies one.
    const { webServer, ...partialDef

xport function defineConfig<T extends NextOptionsConfig, W>(
  config: base.PlaywrightTestConfig<T, W>
): base.PlaywrightTestConfig<T, W>
export function defineConfig<T extends NextOptionsConfig = NextOptionsConfig>(
  config: ba


fineConfig } from './index'
import type { NextFixture } from './next-fixture'
// eslint-disable-next-line import/no-extraneous-dependencies
import { type RequestHandler, handleRequest } from 'msw'
// eslint-disable-next-line import/no-extraneous-dependencies
import { Emitter } from 'strict-event-emitter'

// eslint-disable-next-line import/no-extraneous-dependencies
export * from 'msw'
export * from '@playwright/test'
export type { NextFixture }
export { defineConfig }

export interface MswFixture {
  use:

  const handlers: RequestHandler[] = [...mswHandlers]
      const emitter = new Emitter()

      next.onFetch(async (request) => {
        const requestId = Math.random().toString(16).slice(2)
        let isUnhandled = false
        let isPassthrough = fal

(...handlers: RequestHandler[]) => void
}

export const test = base.extend<{
  msw: MswFixture
  mswHandlers: RequestHandler[]
}>({
  mswHandlers: [[], { option: true }],

  msw: [
    async ({ next, mswHandlers }, use) => {


st'
import type { NextWorkerFixture, FetchHandler } from './next-worker-fixture'
import type { NextOptions } from './next-options'
import type { FetchHandlerResult } from '../proxy'
import { handleRoute } from './page-route'
import { reportFetch } from './report'

export interface NextFixture {
  onFetch: (handler: FetchHandler) => void
}

class NextFixtureImpl implements NextFixture {
  public readonly testId: string
  private fetchHandlers: FetchHandler[] = []

  constructor(
    private testInfo: TestInf

<void> {
    const testHeaders = {
      'Next-Test-Proxy-Port': String(this.worker.proxyPort),
      'Next-Test-Data': this.testId,
    }

    await this.page
      .context()
      .route('**', (route) =>
        handleRoute(route, this.page, testHeaders

o,
    private options: NextOptions,
    private worker: NextWorkerFixture,
    private page: Page
  ) {
    this.testId = testInfo.testId
    worker.onFetch(this.testId, this.handleFetch.bind(this))
  }

  async setup(): Promise


rResult, ProxyServer } from '../proxy'
import { createProxyServer } from '../proxy'

export type FetchHandler = (
  request: Request
) => FetchHandlerResult | Promise<FetchHandlerResult>

export interface NextWorkerFixture {
  proxyPort: number
  onFetch: (testId: string, handler: FetchHandler) => void
  cleanupTest: (testId: string) => void
}

class NextWorkerFixtureImpl implements NextWorkerFixture {
  public proxyPort: number = 0
  private proxyServer: ProxyServer | null = null
  private proxyFetchMap =

r
  }

  teardown(): void {
    if (this.proxyServer) {
      this.proxyServer.close()
      this.proxyServer = null
    }
  }

  cleanupTest(testId: string): void {
    this.proxyFetchMap.delete(testId)
  }

  onFetch(testId: string, handler: FetchHandler

new Map<string, FetchHandler>()

  async setup(): Promise<void> {
    const server = await createProxyServer({
      onFetch: this.handleProxyFetch.bind(this),
    })

    this.proxyPort = server.port
    this.proxyServer = serve


ghtRequest,
} from '@playwright/test'
import type { FetchHandler } from './next-worker-fixture'

function continueRoute(
  route: Route,
  request: PlaywrightRequest,
  testHeaders: Record<string, string>
): Promise<void> {
  return route.continue({
    headers: {
      ...request.headers(),
      ...testHeaders,
    },
  })
}

export async function handleRoute(
  route: Route,
  page: Page,
  testHeaders: Record<string, string>,
  fetchHandler: FetchHandler | null
) {
  const request = route.request()

  /

wup requests will be intercepted
  // on the server.
  const pageOrigin = new URL(page.url()).origin
  const requestOrigin = new URL(request.url()).origin
  if (pageOrigin === requestOrigin) {
    return continueRoute(route, request, testHeaders)
  }

  if

/ Continue the navigation and non-fetch requests.
  if (request.isNavigationRequest() || request.resourceType() !== 'fetch') {
    return continueRoute(route, request, testHeaders)
  }

  // Continue the local requests. The follo


ure'
import { step } from './step'

async function parseBody(
  r: Pick<Request, 'headers' | 'json' | 'text' | 'arrayBuffer' | 'formData'>
): Promise<Record<string, string>> {
  const contentType = r.headers.get('content-type')
  let error: string | undefined
  let text: string | undefined
  let json: unknown
  let formData: FormData | undefined
  let buffer: ArrayBuffer | undefined
  if (contentType?.includes('text')) {
    try {
      text = await r.text()
    } catch (e) {
      error = 'failed to parse

ata = await r.formData()
    } catch (e) {
      error = 'failed to parse formData'
    }
  } else {
    try {
      buffer = await r.arrayBuffer()
    } catch (e) {
      error = 'failed to parse arrayBuffer'
    }
  }
  return {
    ...(error ? { error }

text'
    }
  } else if (contentType?.includes('json')) {
    try {
      json = await r.json()
    } catch (e) {
      error = 'failed to parse json'
    }
  } else if (contentType?.includes('form-data')) {
    try {
      formD


mport type { TestInfo } from '@playwright/test'
import { test } from '@playwright/test'

export interface StepProps {
  category: string
  title: string
  apiName?: string
  params?: Record<string, string | number | boolean | null | undefined>
}

type Complete = (result: { error?: any }) => void

export async function step<T>(
  _testInfo: TestInfo,
  props: StepProps,
  handler: (complete: Complete) => Promise<Awaited<T>>
): Promise<Awaited<T>> {
  let result: Awaited<T>
  let reportedError: any
  try {

esult = await handler(({ error }) => {
        reportedError = error
        if (reportedError) {
          throw reportedError
        }
      })
    })
  } catch (error) {
    if (error !== reportedError) {
      throw error
    }
  }
  return result!
}

  await test.step(props.title, async () => {
      r


rects', () => {
    it('handles redirect', async () => {
      const response = await unstable_getResponseFromNextConfig({
        url: 'https://nextjs.org/test',
        nextConfig: {
          async redirects() {
            return [
              { source: '/test', destination: '/test2', permanent: false },
            ]
          },
        },
      })
      expect(response.status).toEqual(307)
      expect(response.headers.get('location')).toEqual(
        'https://nextjs.org/test2'
      )
    })

n [
              {
                source: '/test/:slug',
                destination: '/test2/:slug',
                permanent: false,
              },
            ]
          },
        },
      })
      expect(response.status).toEqual(307)
      expec

 it('handles redirect with params', async () => {
      const response = await unstable_getResponseFromNextConfig({
        url: 'https://nextjs.org/test/foo',
        nextConfig: {
          async redirects() {
            retur


nation,
} from '../../../shared/lib/router/utils/prepare-destination'
import { PHASE_PRODUCTION_BUILD } from '../../../shared/lib/constants'
import { buildCustomRoute } from '../../../lib/build-custom-route'
import loadCustomRoutes from '../../../lib/load-custom-routes'
import { normalizeConfig, type NextConfig } from '../../../server/config-shared'
import { NextResponse } from '../../../server/web/exports'
import { getRedirectStatus } from '../../../lib/redirect-status'
import type {
  ManifestHeaderRoute,

rom './utils'
import { parsedUrlQueryToParams } from '../../../server/route-modules/app-route/helpers/parsed-url-query-to-params'

/**
 * Tries to match the current request against the provided route. If there is
 * a match, it returns the params extracted

  ManifestRedirectRoute,
  ManifestRewriteRoute,
} from '../../../build'
import type { BaseNextRequest } from '../../../server/base-http'
import type { Params } from '../../../server/request/params'
import { constructRequest } f


ovided', () => {
    expect(
      unstable_doesMiddlewareMatch({
        config: {
          matcher: undefined,
        },
        url: '/test',
      })
    ).toEqual(true)
  })

  it('matches only valid paths in the config', () => {
    const config = {
      matcher: '/test',
    }
    expect(
      unstable_doesMiddlewareMatch({
        config,
        url: '/test',
      })
    ).toEqual(true)
    expect(
      unstable_doesMiddlewareMatch({
        config,
        url: '/test?q=1',
      })
    ).to

, '/test/(.*)', '/test2/:path+'],
    }
    expect(
      unstable_doesMiddlewareMatch({
        config,
        url: '/test',
      })
    ).toEqual(true)
    expect(
      unstable_doesMiddlewareMatch({
        config,
        url: '/test/slug',
      })

Equal(true)
    expect(
      unstable_doesMiddlewareMatch({
        config,
        url: '/other-path',
      })
    ).toEqual(false)
  })

  it('matches regular expressions', () => {
    const config = {
      matcher: ['/test'


{ IncomingHttpHeaders } from 'http'
import { getMiddlewareMatchers } from '../../../build/analysis/get-page-static-info'
import { getMiddlewareRouteMatcher } from '../../../shared/lib/router/utils/middleware-route-matcher'
import type { NextConfig } from '../../../server/config-shared'
import { parseUrl } from '../../../lib/url'
import { constructRequest } from './utils'
import type { MiddlewareConfigMatcherInput } from '../../../build/segment-config/middleware/middleware-config'

export interface Middlewar

to assert that middleware is matching (and therefore executing)
 * only when it should be.
 */
export function unstable_doesMiddlewareMatch({
  config,
  url,
  headers,
  cookies,
  nextConfig,
}: {
  config: MiddlewareSourceConfig
  url: string
  headers

eSourceConfig {
  matcher?: MiddlewareConfigMatcherInput
}

/**
 * Checks whether the middleware config will match the provide URL and request
 * information such as headers and cookies. This function is useful for
 * unit tests


pHeaders } from 'http'
import { MockedRequest } from '../../../server/lib/mock-request'
import { NodeNextRequest } from '../../../server/base-http/node'
import type { BaseNextRequest } from '../../../server/base-http'
import type { NextResponse } from '../../../server/web/exports'
import { parseUrl } from '../../../lib/url'

export function constructRequest({
  url,
  headers = {},
  cookies = {},
}: {
  url: string
  headers?: IncomingHttpHeaders
  cookies?: Record<string, string>
}): BaseNextRequest {
  i

e}=${value}`)
        .join(';'),
    }
  }
  return new NodeNextRequest(new MockedRequest({ url, headers, method: 'GET' }))
}

/**
 * Returns the URL of the redirect if the response is a redirect response or
 * returns null if the response is not.
 */
exp

f (!headers) {
    headers = {}
  }
  if (!headers.host) {
    headers.host = parseUrl(url)?.host
  }
  if (cookies) {
    headers = {
      ...headers,
      cookie: Object.entries(cookies)
        .map(([name, value]) => `${nam


 {
  HTTP_ERROR_FALLBACK_ERROR_CODE,
  type HTTPAccessFallbackError,
} from './http-access-fallback/http-access-fallback'

/**
 * This function allows you to render the [not-found.js file](https://nextjs.org/docs/app/api-reference/file-conventions/not-found)
 * within a route segment as well as inject a tag.
 *
 * `notFound()` can be used in
 * [Server Components](https://nextjs.org/docs/app/building-your-application/rendering/server-components),
 * [Route Handlers](https://nextjs.org/docs/app/building-your

s" content="noindex" />` meta tag and set the status code to 404.
 * - In a Route Handler or Server Action, it will serve a 404 to the caller.
 *
 * Read more: [Next.js Docs: `notFound`](https://nextjs.org/docs/app/api-reference/functions/not-found)
 */

c

-application/routing/route-handlers), and
 * [Server Actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations).
 *
 * - In a Server Component, this will insert a `<meta name="robot


refetchTask,
  cancelPrefetchTask,
  reschedulePrefetchTask,
  isPrefetchTaskDirty,
} from './segment-cache/scheduler'
import { startTransition } from 'react'

type LinkElement = HTMLAnchorElement | SVGAElement

type Element = LinkElement | HTMLFormElement

// Properties that are shared between Link and Form instances. We use the same
// shape for both to prevent a polymorphic de-opt in the VM.
type LinkOrFormInstanceShared = {
  router: AppRouterInstance
  fetchStrategy: PrefetchTaskFetchStrategy

  isVisi

sk | null
}

export type FormInstance = LinkOrFormInstanceShared & {
  prefetchHref: string
  setOptimisticLinkStatus: null
}

type PrefetchableLinkInstance = LinkOrFormInstanceShared & {
  prefetchHref: string
  setOptimisticLinkStatus: (status: { pending

ble: boolean

  // The most recently initiated prefetch task. It may or may not have
  // already completed. The same prefetch task object can be reused across
  // multiple prefetches of the same link.
  prefetchTask: PrefetchTa