sive error reporting including:
 * - Next.js global errors (e.g., next.config validation errors)
 * - Browser runtime errors with source-mapped stack traces
 * - Build errors from webpack/turbopack compilation
 *
 * For browser errors, it leverages the HMR infrastructure for server-to-browser communication.
 *
 * Flow:
 *   MCP client → server generates request ID → HMR message to browser →
 *   browser queries error overlay state → HMR response back → server performs source mapping →
 *   combined with glo

_TO_BROWSER,
  type HmrMessageSentToBrowser,
} from '../../dev/hot-reloader-types'
import { formatErrors } from './utils/format-errors'
import {
  createBrowserRequest,
  handleBrowserPageResponse,
  DEFAULT_BROWSER_REQUEST_TIMEOUT_MS,
} from './utils/brow

bal errors → formatted output.
 */
import type { McpServer } from 'next/dist/compiled/@modelcontextprotocol/sdk/server/mcp'
import type { OverlayState } from '../../../next-devtools/dev-overlay/shared'
import {
  HMR_MESSAGE_SENT


ng the path to the Next.js development log file.
 *
 * This tool returns the path to the {nextConfig.distDir}/logs/next-development.log file
 * that contains browser console logs and other development information.
 */
import type { McpServer } from 'next/dist/compiled/@modelcontextprotocol/sdk/server/mcp'
import { stat } from 'fs/promises'
import { join } from 'path'
import { mcpTelemetryTracker } from '../mcp-telemetry-tracker'

export function registerGetLogsTool(server: McpServer, distDir: string) {
  se

etry
      mcpTelemetryTracker.recordToolCall('mcp/get_logs')

      try {
        const logFilePath = join(distDir, 'logs', 'next-development.log')

        // Check if the log file exists
        try {
          await stat(logFilePath)
        } catch (e

rver.registerTool(
    'get_logs',
    {
      description:
        'Get the path to the Next.js development log file. Returns the file path so the agent can read the logs directly.',
    },
    async () => {
      // Track telem


../../build/rendering-mode'

// Helper function to create a mock PrerenderManifest
function createMockPrerenderManifest(
  dynamicRoutes: Record<string, DynamicPrerenderManifestRoute> = {}
): PrerenderManifest {
  return {
    version: 4,
    routes: {},
    dynamicRoutes,
    notFoundRoutes: [],
    preview: {
      previewModeId: 'test-preview-id',
      previewModeEncryptionKey: 'test-encryption-key',
      previewModeSigningKey: 'test-signing-key',
    },
  }
}

// Helper function to create a mock Dynam

   fallbackRevalidate: false,
    fallbackExpire: undefined,
    fallbackHeaders: undefined,
    fallbackStatus: undefined,
    fallbackRouteParams: undefined,
    fallbackRootParams: undefined,
    fallbackSourceRoute: undefined,
    prefetchDataRoute: un

icPrerenderManifestRoute
function createMockDynamicRoute(
  overrides: Partial<DynamicPrerenderManifestRoute> = {}
): DynamicPrerenderManifestRoute {
  return {
    dataRoute: null,
    dataRouteRegex: null,
    fallback: null,


nal'
import { readFileSync } from 'fs'

jest.mock('fs')

describe('loadManifest', () => {
  const cache = new Map<string, unknown>()

  afterEach(() => {
    jest.resetAllMocks()
    cache.clear()
  })

  it('should load the manifest from the file system when not cached', () => {
    const mockManifest = { key: 'value' }
    ;(readFileSync as jest.Mock).mockReturnValue(JSON.stringify(mockManifest))

    let result = loadManifest('path/to/manifest', false)
    expect(result).toEqual(mockManifest)
    expect(

ct(result).toEqual(mockManifest)
    expect(readFileSync).toHaveBeenCalledTimes(2)
    expect(readFileSync).toHaveBeenCalledWith('path/to/manifest', 'utf8')
    expect(cache.has('path/to/manifest')).toBe(false)
  })

  it('should return the cached manifest

readFileSync).toHaveBeenCalledTimes(1)
    expect(readFileSync).toHaveBeenCalledWith('path/to/manifest', 'utf8')
    expect(cache.has('path/to/manifest')).toBe(false)

    result = loadManifest('path/to/manifest', false)
    expe


er'
import { NextServerSpan } from './lib/trace/constants'
import { formatUrl } from '../shared/lib/router/utils/format-url'
import type { ServerFields } from './lib/router-utils/setup-dev-bundler'
import type { ServerInitResult } from './lib/render-server'
import { AsyncCallbackSet } from './lib/async-callback-set'
import {
  RouterServerContextSymbol,
  routerServerGlobal,
} from './lib/router-utils/router-server-context'

let ServerImpl: typeof NextNodeServer

const getServerImpl = async () => {
  if (Se

 ServerOptions | DevServerOptions,
  // This is assigned in this server abstraction.
  'conf'
> &
  Partial<Pick<ServerOptions | DevServerOptions, 'conf'>>

export type NextBundlerOptions = {
  /** @deprecated Use `turbopack` instead */
  turbo?: boolean

rverImpl === undefined) {
    ServerImpl = (
      await Promise.resolve(
        require('./next-server') as typeof import('./next-server')
      )
    ).default
  }
  return ServerImpl
}

export type NextServerOptions = Omit<


L: string
) => ModernSourceMapPayload | undefined
// Find a source map using the bundler's API.
// This is only a fallback for when Node.js fails to due to bugs e.g. https://github.com/nodejs/node/issues/52102
// TODO: Remove once all supported Node.js versions are fixed.
// TODO(veil): Set from Webpack as well
let bundlerFindSourceMapPayload: FindSourceMapPayload = () => undefined

export function setBundlerFindSourceMapImplementation(
  findSourceMapImplementation: FindSourceMapPayload
): void {
  bundler

colors: boolean
) => string | null

let codeFrameRenderer: CodeFrameRenderer | undefined

export function setCodeFrameRenderer(renderer: CodeFrameRenderer): void {
  codeFrameRenderer = renderer
}

function getOriginalCodeFrame(
  frame: IgnorableStackFram

FindSourceMapPayload = findSourceMapImplementation
}

// Code frame renderer - injected by dev/build to avoid hard dependency on native bindings
type CodeFrameRenderer = (
  frame: IgnorableStackFrame,
  source: string | null,


{ RenderOpts } from './render'

import { nonNullable } from '../lib/non-nullable'

type PostProcessorFunction =
  | ((html: string) => Promise<string>)
  | ((html: string) => string)

async function postProcessHTML(
  content: string,
  renderOpts: Pick<RenderOpts, 'optimizeCss' | 'distDir' | 'assetPrefix'>
) {
  const postProcessors: Array<PostProcessorFunction> = [
    process.env.NEXT_RUNTIME !== 'edge' && renderOpts.optimizeCss
      ? async (html: string) => {
          // eslint-disable-next-line impo

rue,
            reduceInlineStyles: false,
            path: renderOpts.distDir,
            publicPath: `${renderOpts.assetPrefix}/_next/`,
            preload: 'media',
            fonts: false,
            logLevel:
              process.env.CRITTERS_L

rt/no-extraneous-dependencies
          const Critters = require('critters') as typeof import('critters')
          // @ts-expect-error -- interopRequireDefault
          const cssOptimizer = new Critters({
            ssrMode: t


../shared/lib/constants'

import React, { type JSX } from 'react'
import ReactDOMServerPages from 'next/dist/server/ReactDOMServerPages'
import { StyleRegistry, createStyleRegistry } from 'styled-jsx'
import {
  GSP_NO_RETURNED_VALUE,
  GSSP_COMPONENT_MEMBER_ERROR,
  GSSP_NO_RETURNED_VALUE,
  STATIC_STATUS_PAGE_GET_INITIAL_PROPS_ERROR,
  SERVER_PROPS_GET_INIT_PROPS_CONFLICT,
  SERVER_PROPS_SSG_CONFLICT,
  SSG_GET_INITIAL_PROPS_CONFLICT,
  UNSTABLE_REVALIDATE_RENAME_ERROR,
  HTML_CONTENT_TYPE_HEADER,
  JSON_

zable-props'
import { defaultHead } from '../shared/lib/head'
import { HeadManagerContext } from '../shared/lib/head-manager-context.shared-runtime'
import Loadable from '../shared/lib/loadable.shared-runtime'
import { LoadableContext } from '../shared/lib

CONTENT_TYPE_HEADER,
} from '../lib/constants'
import {
  NEXT_BUILTIN_DOCUMENT,
  SERVER_PROPS_ID,
  STATIC_PROPS_ID,
  STATIC_STATUS_PAGES,
} from '../shared/lib/constants'
import { isSerializableProps } from '../lib/is-seriali


and webpack/. It's required to use the internal ncc webpack version.
// This is needed for userland plugins to attach to the same webpack instance as Next.js'.
// Individually compiled modules are as defined for the compilation in bundles/webpack/packages/*.

// This module will only be loaded once per process.
const path = require('path') as typeof import('path')
const mod = require('module') as typeof import('module')
const originalRequire = mod.prototype.require
const resolveFilename =
  // @ts-expect-er

verrides: Record<string, string> = {}

try {
  Object.assign(defaultOverrides, {
    'styled-jsx': path.dirname(resolve('styled-jsx/package.json')),
    'styled-jsx/style': resolve('styled-jsx/style'),
    'styled-jsx/style.js': resolve('styled-jsx/style')

ror
  mod._resolveFilename

let resolve: typeof require.resolve = process.env.NEXT_MINIMAL
  ? // @ts-ignore
    __non_webpack_require__.resolve
  : require.resolve

export const hookPropertyMap = new Map()

export const defaultO


m 'http'
import type RenderResult from './render-result'
import type { CacheControl } from './lib/cache-control'

import { isResSent } from '../shared/lib/utils'
import { generateETag } from './lib/etag'
import fresh from 'next/dist/compiled/fresh'
import { getCacheControlHeader } from './lib/cache-control'
import { HTML_CONTENT_TYPE_HEADER } from '../lib/constants'

export function sendEtagResponse(
  req: IncomingMessage,
  res: ServerResponse,
  etag: string | undefined
): boolean {
  if (etag) {
    /**

 Expires, and Vary. https://tools.ietf.org/html/rfc7232#section-4.1
     */
    res.setHeader('ETag', etag)
  }

  if (fresh(req.headers, { etag })) {
    res.statusCode = 304
    res.end()
    return true
  }

  return false
}

export async function sendR

     * The server generating a 304 response MUST generate any of the
     * following header fields that would have been sent in a 200 (OK)
     * response to the same request: Cache-Control, Content-Location, Date,
     * ETag,


rom './base-http'
import { isNodeNextResponse } from './base-http/helpers'

import { pipeToNodeResponse } from './pipe-readable'
import { splitCookiesString } from './web/utils'

/**
 * Sends the response on the underlying next response object.
 *
 * @param req the underlying request object
 * @param res the underlying response object
 * @param response the response to send
 */
export async function sendResponse(
  req: BaseNextRequest,
  res: BaseNextResponse,
  response: Response,
  waitUntil?: Promise<un

tResponse(res)
  ) {
    // Copy over the response status.
    res.statusCode = response.status
    res.statusMessage = response.statusText

    // TODO: this is not spec-compliant behavior and we should not restrict
    // headers that are allowed to appe

known>
): Promise<void> {
  if (
    // The type check here ensures that `req` is correctly typed, and the
    // environment variable check provides dead code elimination.
    process.env.NEXT_RUNTIME !== 'edge' &&
    isNodeNex


hould return nothing for a non-dynamic route', () => {
    const { getParamsFromRouteMatches } = getServerUtils({
      page: '/',
      basePath: '',
      rewrites: {},
      i18n: undefined,
      pageIsDynamic: false,
      caseSensitive: false,
    })

    const params = getParamsFromRouteMatches('nxtPslug=hello-world')
    expect(params).toEqual(null)
  })

  it('should return the params from the route matches', () => {
    const { getParamsFromRouteMatches } = getServerUtils({
      page: '/[slug]',

 'hello-world' })
  })

  it('should handle optional params', () => {
    const { getParamsFromRouteMatches } = getServerUtils({
      page: '/[slug]/[[...optional]]',
      basePath: '',
      rewrites: {},
      i18n: undefined,
      pageIsDynamic: true

      basePath: '',
      rewrites: {},
      i18n: undefined,
      pageIsDynamic: true,
      caseSensitive: false,
    })

    const params = getParamsFromRouteMatches('nxtPslug=hello-world')
    expect(params).toEqual({ slug:


nts'

export function isBlockedPage(page: string): boolean {
  return BLOCKED_PAGES.includes(page)
}

type AnyFunc<T> = (this: T, ...args: any) => any
export function debounce<T, F extends AnyFunc<T>>(
  fn: F,
  ms: number,
  maxWait = Infinity
) {
  let timeoutId: undefined | NodeJS.Timeout

  // The time the debouncing function was first called during this debounce queue.
  let startTime = 0
  // The time the debouncing function was last called.
  let lastCall = 0

  // The arguments and this context of

   const now = Date.now()
    const diff = lastCall + ms - now

    // If the diff is non-positive, then we've waited at least `ms`
    // milliseconds since the last call. Or if we've waited for longer than the
    // max wait time, we must call the debou

the last call to the debouncing function.
  let args: Parameters<F>, context: T

  // A helper used to that either invokes the debounced function, or
  // reschedules the timer if a more recent call was made.
  function run() {


nifest } from '../load-components'
import type { NextFontManifest } from '../../build/webpack/plugins/next-font-manifest-plugin'
import { normalizeDataPath } from '../../shared/lib/page-path/normalize-data-path'
import { pathHasPrefix } from '../../shared/lib/router/utils/path-has-prefix'
import {
  addRequestMeta,
  getRequestMeta,
  type NextIncomingMessage,
} from '../request-meta'
import { patchSetHeaderWithCookieSupport } from '../lib/patch-set-header'
import { normalizePagePath } from '../../shared/li

./use-cache/handlers'
import { interopDefault } from '../app-render/interop-default'
import { RouteKind } from '../route-kind'
import type { BaseNextRequest } from '../base-http'
import type { I18NConfig, NextConfigRuntime } from '../config-shared'
import

b/page-path/normalize-page-path'
import { isStaticMetadataRoute } from '../../lib/metadata/is-metadata-route'
import { IncrementalCache } from '../lib/incremental-cache'
import { initializeCacheHandlers, setCacheHandler } from '.


om '../../route-definitions/pages-api-route-definition'
import type { PageConfig } from '../../../types'
import type { ParsedUrlQuery } from 'querystring'
import { wrapApiHandler, type __ApiPreviewProps } from '../../api-utils'
import type { RouteModuleOptions } from '../route-module'

import { RouteModule, type RouteModuleHandleContext } from '../route-module'
import { apiResolver } from '../../api-utils/node/api-resolver'
import type { RevalidateFn } from '../../lib/router-utils/router-server-context'

ty

port('../../../build/templates/pages-api')

type PagesAPIUserlandModule = {
  /**
   * The exported handler method.
   */
  readonly default: PagesAPIHandleFn

  /**
   * The exported page config.
   */
  readonly config?: PageConfig
}

type PagesAPIRouteH

pe PagesAPIHandleFn = (
  req: IncomingMessage,
  res: ServerResponse
) => Promise<void>

/**
 * The PagesAPIModule is the type of the module exported by the bundled Pages
 * API module.
 */
export type PagesAPIModule = typeof im


import { addRequestMeta, type NextParsedUrlQuery } from '../../request-meta'
import type { LoaderTree } from '../../lib/app-dir-module'
import type { PrerenderManifest } from '../../../build'

import {
  renderToHTMLOrFlight,
  type AppSharedContext,
} from '../../app-render/app-render'
import {
  RouteModule,
  type RouteModuleOptions,
  type RouteModuleHandleContext,
} from '../route-module'
import * as vendoredContexts from './vendored/contexts/entrypoints'
import type { BaseNextRequest, BaseNextRespons

erender-manifest-matcher'
import type { DeepReadonly } from '../../../shared/lib/deep-readonly'
import {
  NEXT_ROUTER_PREFETCH_HEADER,
  NEXT_ROUTER_SEGMENT_PREFETCH_HEADER,
  NEXT_ROUTER_STATE_TREE_HEADER,
  NEXT_URL,
  RSC_HEADER,
} from '../../../clien

e } from '../../base-http'
import type { ServerComponentsHmrCache } from '../../response-cache'
import type { OpaqueFallbackRouteParams } from '../../request/fallback-params'
import { PrerenderManifestMatcher } from './helpers/pr


om 'react/jsx-dev-runtime'
import * as ReactJsxRuntime from 'react/jsx-runtime'
import * as ReactCompilerRuntime from 'react/compiler-runtime'

function getAltProxyForBindingsDEV(
  type: 'Turbopack' | 'Webpack',
  pkg:
    | 'react-server-dom-turbopack/server'
    | 'react-server-dom-turbopack/static'
    | 'react-server-dom-webpack/server'
    | 'react-server-dom-webpack/static'
) {
  if (process.env.NODE_ENV === 'development') {
    const altType = type === 'Turbopack' ? 'Webpack' : 'Turbopack'
    const

act but the current process is referencing '${prop}' from the ${altType} bindings (${altPkg}). This is likely a bug in our integration of the Next.js server runtime.`
          )
        },
      }
    )
  }
}

let ReactServerDOMTurbopackServer, ReactServe

 altPkg = pkg.replace(new RegExp(type, 'gi'), altType.toLowerCase())

    return new Proxy(
      {},
      {
        get(_, prop: string) {
          throw new Error(
            `Expected to use ${type} bindings (${pkg}) for Re


readFileSync } from 'fs'
import { runInNewContext } from 'vm'
import { deepFreeze } from '../shared/lib/deep-freeze'

const sharedCache = new Map<string, unknown>()

/**
 * Load a manifest file from the file system. Optionally cache the manifest in
 * memory to avoid reading the file multiple times using the provided cache or
 * defaulting to a shared module cache. The manifest is frozen to prevent
 * modifications if it is cached.
 *
 * @param path the path to the manifest file
 * @param shouldCache whethe

tion loadManifest<T extends object>(
  path: string,
  shouldCache?: boolean,
  cache?: Map<string, unknown>,
  skipParse?: boolean
): DeepReadonly<T>
export function loadManifest<T extends object>(
  path: string,
  shouldCache?: boolean,
  cache?: Map<st

r to cache the manifest in memory
 * @param cache the cache to use for storing the manifest
 * @returns the manifest object
 */
export function loadManifest<T extends object>(
  path: string,
  shouldCache: false
): T
export func


ta, setRequestMeta } from './request-meta'
import {
  PAGES_MANIFEST,
  BUILD_ID_FILE,
  MIDDLEWARE_MANIFEST,
  PREFETCH_HINTS,
  PRERENDER_MANIFEST,
  ROUTES_MANIFEST,
  CLIENT_PUBLIC_FILES_PATH,
  APP_PATHS_MANIFEST,
  SERVER_DIRECTORY,
  NEXT_FONT_MANIFEST,
  UNDERSCORE_NOT_FOUND_ROUTE_ENTRY,
  FUNCTIONS_CONFIG_MANIFEST,
} from '../shared/lib/constants'
import { findDir } from '../lib/find-pages-dir'
import { NodeNextRequest, NodeNextResponse } from './base-http/node'
import { sendRenderResult } from './

teManifest,
  LoadedRenderOpts,
  RouteHandler,
  NextEnabledDirectories,
  BaseRequestHandler,
} from './base-server'
import BaseServer from './base-server'
import { getMaybePagePath, getPagePath } from './require'
import { denormalizePagePath } from '../

send-payload'
import { parseUrl } from '../shared/lib/router/utils/parse-url'
import * as Log from '../build/output/log'

import type {
  Options,
  FindComponentsResult,
  MiddlewareRoutingItem,
  RequestContext,
  NormalizedRou


port { DetachedPromise } from '../lib/detached-promise'
import { getTracer } from './lib/trace/tracer'
import { NextNodeServerSpan } from './lib/trace/constants'
import { getClientComponentLoaderMetrics } from './client-component-renderer-logger'

export function isAbortError(e: any): e is Error & { name: 'AbortError' } {
  return e?.name === 'AbortError' || e?.name === ResponseAbortedName
}

const HAS_CLIENT_COMPONENT_METRICS_ENABLED =
  'performance' in globalThis && process.env.NEXT_OTEL_PERFORMANCE_PREF

  // https://nodejs.org/api/stream.html#stream_event_drain
  let drained = new DetachedPromise<void>()
  function onDrain() {
    drained.resolve()
  }
  res.on('drain', onDrain)

  // If the finish event fires, it means we shouldn't block and wait for the

IX

function createWriterFromResponse(
  res: ServerResponse,
  waitUntilForEnd?: Promise<unknown>
): WritableStream<Uint8Array> {
  let started = false

  // Create a promise that will resolve once the response has drained. See


rt type {
  ResponseCacheEntry,
  ServerComponentsHmrCache,
} from './response-cache'
import type { PagesDevOverlayBridgeType } from '../next-devtools/userspace/pages/pages-dev-overlay-setup'
import type { OpaqueFallbackRouteParams } from './request/fallback-params'
import type { IncrementalCache } from './lib/incremental-cache'
import type { RevalidateFn } from './lib/router-utils/router-server-context'
import type { NextRequest } from './web/exports'

// FIXME: (wyattjoh) this is a temporary solution to a

T_META]?: RequestMeta
}

/**
 * The callback function to call when a response cache entry was generated or
 * looked up in the cache. When it returns true, the server assumes that the
 * handler has already responded to the request and will not do so itsel

llow us to pass data between bundled modules
export const NEXT_REQUEST_META = Symbol.for('NextInternalRequestMeta')

export type NextIncomingMessage = (
  | BaseNextRequest
  | IncomingMessage
  | NextRequest
) & {
  [NEXT_REQUES


{ IncomingMessage, ServerResponse } from 'http'
import send from 'next/dist/compiled/send'

// TODO: Remove this once "send" has updated the "mime", or next.js use custom version of "mime"
// Although "mime" has already add avif in version 2.4.7, "send" is still using mime@1.6.0
send.mime.define({
  'image/avif': ['avif'],
  'image/x-icns': ['icns'],
  'image/jxl': ['jxl'],
  'image/heic': ['heic'],
})

export function serveStatic(
  req: IncomingMessage,
  res: ServerResponse,
  path: string,
  opts?: Para

No directory access')
        err.code = 'ENOENT'
        reject(err)
      })
      .on('error', reject)
      .pipe(res)
      .on('finish', resolve)
  })
}

export const getContentType: (extWithoutDot: string) => string | null =
  'getType' in send.mime

meters<typeof send>[2]
): Promise<void> {
  return new Promise((resolve, reject) => {
    send(req, path, opts)
      .on('directory', () => {
        // We don't allow directories to be read.
        const err: any = new Error('


ale-path'
import { getPathMatch } from '../shared/lib/router/utils/path-match'
import { getNamedRouteRegex } from '../shared/lib/router/utils/route-regex'
import { getRouteMatcher } from '../shared/lib/router/utils/route-matcher'
import {
  matchHas,
  prepareDestination,
} from '../shared/lib/router/utils/prepare-destination'
import { removeTrailingSlash } from '../shared/lib/router/utils/remove-trailing-slash'
import { normalizeRscURL } from '../shared/lib/router/utils/app-paths'
import {
  NEXT_CACHE_REV

ttpHeaders, IncomingMessage } from 'http'
import { decodeQueryPathParameter } from './lib/decode-query-path-parameter'
import type { DeepReadonly } from '../shared/lib/deep-readonly'
import { parseReqUrl } from '../lib/url'
import { formatUrl } from '../sh

ALIDATE_TAG_TOKEN_HEADER,
  NEXT_CACHE_REVALIDATED_TAGS_HEADER,
  NEXT_INTERCEPTION_MARKER_PREFIX,
  NEXT_QUERY_PARAM_PREFIX,
} from '../lib/constants'
import { normalizeNextQueryParam } from './web/utils'
import type { IncomingH


env.NEXT_RUNTIME === 'edge') {
  module.exports = require('next/dist/server/route-modules/app-page/module.js')
} else {
  if (process.env.__NEXT_EXPERIMENTAL_REACT) {
    if (process.env.NODE_ENV === 'development') {
      if (process.env.TURBOPACK) {
        module.exports = require('next/dist/compiled/next-server/app-page-turbo-experimental.runtime.dev.js')
      } else {
        module.exports = require('next/dist/compiled/next-server/app-page-experimental.runtime.dev.js')
      }
    } else {
      if (

rimental.runtime.prod.js')
      }
    }
  } else {
    if (process.env.NODE_ENV === 'development') {
      if (process.env.TURBOPACK) {
        module.exports = require('next/dist/compiled/next-server/app-page-turbo.runtime.dev.js')
      } else {

process.env.TURBOPACK) {
        module.exports = require('next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js')
      } else {
        module.exports = require('next/dist/compiled/next-server/app-page-expe


sage } from 'http'

import {
  NEXT_ROUTER_PREFETCH_HEADER,
  NEXT_ROUTER_SEGMENT_PREFETCH_HEADER,
  RSC_HEADER,
} from '../../../client/components/app-router-headers'
import type { BaseNextRequest } from '../../base-http'
import { isRSCRequestHeader } from '../../lib/is-rsc-request'
import { parseReqUrl } from '../../../lib/url'
import { formatUrl } from '../../../shared/lib/router/utils/format-url'
import { addRequestMeta } from '../../request-meta'

function getHeaderValue(
  value: string | string[] | u

 const isRscRequest = isRSCRequestHeader(req.headers[RSC_HEADER])
  if (!isRscRequest) {
    return
  }

  addRequestMeta(req as IncomingMessage, 'isRSCRequest', true)

  const isPrefetchRequest =
    getHeaderValue(req.headers[NEXT_ROUTER_PREFETCH_HEADER]

ndefined
): string | undefined {
  if (Array.isArray(value)) {
    return value[0]
  }
  return value
}

export function applyAppPageRscRequestMetaFromHeaders(
  req: Pick<IncomingMessage | BaseNextRequest, 'headers'>
): void {


rs. It sets up the environment
// for later imports to work properly.

// expose AsyncLocalStorage on global for react usage if it isn't already provided by the environment
if (typeof (globalThis as any).AsyncLocalStorage !== 'function') {
  const { AsyncLocalStorage } =
    require('async_hooks') as typeof import('async_hooks')
  ;(globalThis as any).AsyncLocalStorage = AsyncLocalStorage
}

if (typeof (globalThis as any).WebSocket !== 'function') {
  Object.defineProperty(globalThis, 'WebSocket', {
    con

require('next/dist/compiled/ws') as typeof import('next/dist/compiled/ws')
      ).WebSocket
    },
    set(value) {
      Object.defineProperty(globalThis, 'WebSocket', {
        configurable: true,
        writable: true,
        value,
      })
    },

figurable: true,
    get() {
      return (


port {
  isAbortError,
  pipeToNodeResponse,
  pipeNodeReadableToNodeResponse,
} from './pipe-readable'
import type { RenderResumeDataCache } from './resume-data-cache/resume-data-cache'
import { InvariantError } from '../shared/lib/invariant-error'
import type {
  HTML_CONTENT_TYPE_HEADER,
  JSON_CONTENT_TYPE_HEADER,
  TEXT_PLAIN_CONTENT_TYPE_HEADER,
} from '../lib/constants'
import type { RSC_CONTENT_TYPE_HEADER } from '../client/components/app-router-headers'

type ContentTypeOption =
  | typeof RSC_CONT

PE_HEADER // For simplified errors

export type AppPageRenderResultMetadata = {
  flightData?: Buffer
  cacheControl?: CacheControl
  staticBailoutInfo?: {
    stack?: string
    description?: string
  }

  /**
   * The postponed state if the render had po

ENT_TYPE_HEADER // For App Page RSC responses
  | typeof HTML_CONTENT_TYPE_HEADER // For App Page, Pages HTML responses
  | typeof JSON_CONTENT_TYPE_HEADER // For API routes, Next.js data requests
  | typeof TEXT_PLAIN_CONTENT_TY


 type { BaseNextRequest } from './base-http'
import type { ParsedUrlQuery } from 'querystring'

import { getRequestMeta } from './request-meta'
import { stringify as stringifyQs } from 'querystring'

// since initial query values are decoded by querystring.parse
// we need to re-encode them here but still allow passing through
// values from rewrites/redirects
export const stringifyQuery = (req: BaseNextRequest, query: ParsedUrlQuery) => {
  const initialQuery = getRequestMeta(req, 'initQuery') || {}
  cons

 => {
          // `value` always refers to a query value, even if it's nested in an array
          return Array.isArray(initialQueryVal)
            ? initialQueryVal.includes(value)
            : initialQueryVal === value
        })
      ) {
        //

t initialQueryValues = Object.values(initialQuery)

  return stringifyQs(query, undefined, undefined, {
    encodeURIComponent(value) {
      if (
        value in initialQuery ||
        initialQueryValues.some((initialQueryVal)


./../../client/components/app-router-headers'
import { parseReqUrl } from '../../../lib/url'
import { getRequestMeta } from '../../request-meta'
import { RSCPathnameNormalizer } from '../../normalizers/request/rsc'
import { SegmentPrefixRSCPathnameNormalizer } from '../../normalizers/request/segment-prefix-rsc'
import {
  applyAppPageRscRequestMetaFromHeaders,
  normalizeAppPageRequestUrl,
} from './normalize-request-url'

type TestRequest = {
  headers: Record<string, string | string[]>
  url: string
}

de

l = parseReqUrl(req.url)!

    parsedUrl.pathname = new RSCPathnameNormalizer().normalize(
      parsedUrl.pathname!
    )
    req.headers[RSC_HEADER] = '1'

    normalizeAppPageRequestUrl(req, parsedUrl.pathname!)

    expect(parsedUrl.pathname).toBe('/do

scribe('normalizeAppPageRequestUrl', () => {
  it('rewrites req.url for regular RSC requests', () => {
    const req: TestRequest = {
      headers: {},
      url: '/docs/frameworks/frontend.rsc?foo=bar',
    }
    const parsedUr


/ This file should be imported before any others. It sets up the environment
// for later imports to work properly.

import './node-environment-baseline'
// Import as early as possible so that unexpected errors in other extensions are properly formatted.
// Has to come after baseline since error-inspect requires AsyncLocalStorage that baseline provides.
import './node-environment-extensions/error-inspect'

// console file needs to go first because we want to be in a dimmed scope before
// deciding if we oug

ns/unhandled-rejection.external'
import './node-environment-extensions/random'
import './node-environment-extensions/date'
import './node-environment-extensions/web-crypto'
import './node-environment-extensions/node-crypto'
import './node-environment-exten

ht to write the log to file.
import './node-environment-extensions/console-file'
import './node-environment-extensions/console-exit'
import './node-environment-extensions/console-dim.external'

import './node-environment-extensio


ler) {
        controller.close()
      },
    })
  }

  // If we only have 1 stream we fast path it by returning just this stream
  if (streams.length === 1) {
    return streams[0]
  }

  const { readable, writable } = new TransformStream()

  // We always initiate pipeTo immediately. We know we have at least 2 streams
  // so we need to avoid closing the writable when this one finishes.
  let promise = streams[0].pipeTo(writable, { preventClose: true })

  let i = 1
  for (; i < streams.length - 1; i++)

s at least two streams so the lastStream here will always be defined
  const lastStream = streams[i]
  promise = promise.then(() => lastStream.pipeTo(writable))

  // Catch any errors from the streams and ignore them, they will be handled
  // by whatever

{
    const nextStream = streams[i]
    promise = promise.then(() =>
      nextStream.pipeTo(writable, { preventClose: true })
    )
  }

  // We can omit the length check because we halted before the last stream and there
  // i


c with:
 *   - packages/create-next-app/helpers/generate-agent-files.ts
 *   - packages/next-codemod/lib/agents-md.ts
 */

import fs from 'fs'
import path from 'path'

export const AGENT_RULES_START_MARKER = '<!-- BEGIN:nextjs-agent-rules -->'
export const AGENT_RULES_END_MARKER = '<!-- END:nextjs-agent-rules -->'

/**
 * Markers written by the pre-bundled-docs version of `agents-md`.
 * Stripped on upsert so projects that ran the old codemod end up with
 * a single current block instead of two stale-and-cu

T_MARKER}
# This is NOT the Next.js you know

This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in \`node_modules/next/dist/docs/\` before writing any code. Heed deprec

rrent blocks.
 */
const LEGACY_AGENT_RULES_START_MARKER = '<!-- NEXT-AGENTS-MD-START -->'
const LEGACY_AGENT_RULES_END_MARKER = '<!-- NEXT-AGENTS-MD-END -->'

function buildAgentRulesBlock(): string {
  return `${AGENT_RULES_STAR


pe { LocaleAnalysisResult } from './i18n-provider'

describe('I18NProvider', () => {
  const config = {
    defaultLocale: 'en',
    locales: ['en', 'fr', 'en-CA'],
    domains: [
      {
        domain: 'example.com',
        defaultLocale: 'en',
        locales: ['en-CA'],
      },
      {
        domain: 'example.fr',
        defaultLocale: 'fr',
      },
    ],
  }
  const provider = new I18NProvider(config)

  describe('detectDomainLocale', () => {
    it.each<{
      domain: string | undefined
      d

        expected: domainLocale,
      })),

      // Verify not-found domains.
      {
        domain: 'example.de',
        detectedLocale: undefined,
        expected: undefined,
      },

      // Verify that the other detected locale will support the

etectedLocale: string | undefined
      expected: DomainLocale | undefined
    }>([
      // Verify domains.
      ...config.domains.map((domainLocale) => ({
        domain: domainLocale.domain,
        detectedLocale: undefined,


interface LocaleAnalysisResult {
  /**
   * The pathname without the locale prefix (if any).
   */
  pathname: string

  /**
   * The detected locale. If no locale was detected, this will be `undefined`.
   */
  detectedLocale?: string

  /**
   * True if the locale was inferred from the default locale.
   */
  inferredFromDefault: boolean
}

type LocaleAnalysisOptions = {
  /**
   * When provided, it will be used as the default locale if the locale
   * cannot be inferred from the pathname.
   */
  default

rivate readonly lowerCaseLocales: ReadonlyArray<string>
  private readonly lowerCaseDomains?: ReadonlyArray<
    DomainLocale & {
      // The configuration references a domain with an optional port, but the
      // hostname is always the domain without t

Locale?: string
}

/**
 * The I18NProvider is used to match locale aware routes, detect the locale from
 * the pathname and hostname and normalize the pathname by removing the locale
 * prefix.
 */
export class I18NProvider {
  p


request/fallback-params'
import { getImplicitTags } from './implicit-tags'

describe('getImplicitTags()', () => {
  it.each<{
    page: string
    pathname: string
    fallbackRouteParams: null | OpaqueFallbackRouteParams
    expectedTags: string[]
  }>([
    {
      page: '/',
      pathname: '/',
      fallbackRouteParams: null,
      expectedTags: ['_N_T_/layout', '_N_T_/', '_N_T_/index'],
    },
    {
      page: '',
      pathname: '/',
      fallbackRouteParams: null,
      expectedTags: ['_N_T_/layou

s: null,
      expectedTags: ['_N_T_/layout', '_N_T_/page'],
    },
    {
      page: '/page',
      pathname: '/',
      fallbackRouteParams: null,
      expectedTags: ['_N_T_/layout', '_N_T_/page', '_N_T_/', '_N_T_/index'],
    },
    {
      page: '/pag

t', '_N_T_/', '_N_T_/index'],
    },
    {
      page: '/',
      pathname: '',
      fallbackRouteParams: null,
      expectedTags: ['_N_T_/layout'],
    },
    {
      page: '/page',
      pathname: '',
      fallbackRouteParam


ms } from '../request/fallback-params'
import { getCacheHandlerEntries } from '../use-cache/handlers'
import { encodeCacheTag } from './encode-cache-tag'
import { createLazyResult, type LazyResult } from './lazy-result'

export interface ImplicitTags {
  /**
   * For legacy usage, the implicit tags are passed to the incremental cache
   * handler in `get` calls.
   */
  readonly tags: string[]

  /**
   * Modern cache handlers don't receive implicit tags. Instead, the implicit
   * tags' expirations are sto

ng the expiration
   * values if no caches are read at all.
   */
  readonly expirationsByCacheKind: Map<string, LazyResult<number>>
}

const getDerivedTags = (pathname: string): string[] => {
  const derivedTags: string[] = [`/layout`]

  // we automatica

red in the work unit store, and used to compare
   * with a cache entry's timestamp.
   *
   * Note: This map contains lazy results so that we can evaluate them when the
   * first cache entry is read. It allows us to skip fetchi


ithub.com/nodejs/node/blob/9fc57006c27564ed7f75eee090eca86786508f51/lib/internal/net.js#L19-L29
// License included below:
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of

ial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVE

the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substant


 type LazyResult<TValue> = PromiseLike<TValue> & { value?: TValue }
export type ResolvedLazyResult<TValue> = PromiseLike<TValue> & { value: TValue }

/**
 * Calls the given function only when the returned promise-like object is
 * awaited. Afterwards, it provides the resolved value synchronously as `value`
 * property.
 */
export function createLazyResult<TValue>(
  fn: () => Promise<TValue> | TValue
): LazyResult<TValue> {
  let pendingResult: Promise<TValue> | undefined

  const result: LazyResult<TValue>

) => {
          // The externally awaited result will be rejected via `onrejected`. We
          // don't need to handle it here. But we do want to avoid an unhandled
          // rejection.
        })

      return pendingResult.then(onfulfilled, onrejec

 = {
    then(onfulfilled, onrejected) {
      if (!pendingResult) {
        pendingResult = Promise.resolve(fn())
      }

      pendingResult
        .then((value) => {
          result.value = value
        })
        .catch((


t keys', () => {
      expect(cache.get('nonexistent')).toBeUndefined()
    })

    it('should check if key exists with has()', () => {
      cache.set('key1', 'value1')
      expect(cache.has('key1')).toBe(true)
      expect(cache.has('nonexistent')).toBe(false)
    })

    it('should update existing keys', () => {
      cache.set('key1', 'value1')
      cache.set('key1', 'value2')
      expect(cache.get('key1')).toBe('value2')
      expect(cache.size).toBe(1)
    })

    it('should track cache size correc

 () => {
    let cache: LRUCache<string>

    beforeEach(() => {
      cache = new LRUCache<string>(3)
    })

    it('should evict least recently used item when capacity exceeded', () => {
      cache.set('key1', 'value1')
      cache.set('key2', 'value2'

tly', () => {
      expect(cache.size).toBe(0)
      cache.set('key1', 'value1')
      expect(cache.size).toBe(1)
      cache.set('key2', 'value2')
      expect(cache.size).toBe(2)
    })
  })

  describe('LRU Eviction Behavior',


ic size: number
  public prev: LRUNode<T> | SentinelNode<T> | null = null
  public next: LRUNode<T> | SentinelNode<T> | null = null

  constructor(key: string, data: T, size: number) {
    this.key = key
    this.data = data
    this.size = size
  }
}

/**
 * Sentinel node used for head/tail boundaries.
 * These nodes don't contain actual cache data but simplify list operations.
 */
class SentinelNode<T> {
  public prev: LRUNode<T> | SentinelNode<T> | null = null
  public next: LRUNode<T> | SentinelNode<T>

 * - Hash map provides O(1) key-to-node lookup
 * - Sentinel head/tail nodes simplify edge case handling
 * - Size-based eviction supports custom size calculation functions
 *
 * Data Structure Layout:
 * HEAD <-> [most recent] <-> ... <-> [least recent]

| null = null
}

/**
 * LRU (Least Recently Used) Cache implementation using a doubly-linked list
 * and hash map for O(1) operations.
 *
 * Algorithm:
 * - Uses a doubly-linked list to maintain access order (most recent at head)


ck-request'

describe('MockedRequest', () => {
  it('should have the correct properties', () => {
    const req = new MockedRequest({
      url: '/hello',
      method: 'POST',
      headers: {
        'x-foo': 'bar',
      },
    })

    expect(req.url).toBe('/hello')
    expect(req.method).toBe('POST')
    expect(req.headers).toEqual({
      'x-foo': 'bar',
    })
  })
})

describe('MockedResponse', () => {
  it('should merge headers correctly when calling writeHead', () => {
    const res = new MockedRes

 'foo, bar',
    })

    res.writeHead(200, ['x-foo', 'foo, bar', 'x-bar', 'bar, foo'])
    expect(res.getHeaders()).toEqual({
      'x-foo': 'foo, bar',
      'x-bar': 'bar, foo',
    })

    res.writeHead(200, ['x-foo', ['bar', 'foo'], 'x-bar', ['foo', '

ponse({})

    res.setHeader('x-foo', 'bar')
    res.setHeader('x-bar', 'foo')

    res.writeHead(200, { 'x-foo': 'bar, foo', 'x-bar': 'foo, bar' })
    expect(res.getHeaders()).toEqual({
      'x-foo': 'bar, foo',
      'x-bar':


od: string
  readable?: Stream.Readable
  socket?: Socket | null
}

export class MockedRequest extends Stream.Readable implements IncomingMessage {
  public url: string
  public readonly statusCode?: number | undefined
  public readonly statusMessage?: string | undefined
  public readonly headers: IncomingHttpHeaders
  public readonly method: string

  // This is hardcoded for now, but can be updated to be configurable if needed.
  public readonly httpVersion = '1.0'
  public readonly httpVersionMajor = 1

  // `remoteAddress` property.
  public socket: Socket = new Proxy<TLSSocket>({} as TLSSocket, {
    get: (_target, prop) => {
      if (prop !== 'encrypted' && prop !== 'remoteAddress') {
        throw new Error('Method not implemented')
      }

      i

 public readonly httpVersionMinor = 0

  private bodyReadable?: Stream.Readable

  // If we don't actually have a socket, we'll just use a mock one that
  // always returns false for the `encrypted` property and undefined for the


e('parseStack', () => {
  it('returns empty array for empty string', () => {
    expect(parseStack('')).toEqual([])
  })

  it('parses a basic stack frame', () => {
    const stack = `Error: boom
    at myFunc (file:///app/foo.ts:10:5)`
    const frames = parseStack(stack)
    expect(frames[0]).toEqual({
      file: 'file:///app/foo.ts',
      methodName: 'myFunc',
      arguments: [],
      line1: 10,
      column1: 5,
    })
  })

  it('rewrites /_next/static/ URLs to distDir', () => {
    const stack = `

   )
  })

  it('rewrites /_next/static/immutable/ URLs to distDir', () => {
    const stack = `Error
    at fn (http://localhost:3000/_next/static/immutable/chunks/app.js:1:1)`
    const [frame] = parseStack(stack, '/home/user/project/.next')
    expect(f

Error
    at fn (http://localhost:3000/_next/static/chunks/app.js:1:1)`
    const [frame] = parseStack(stack, '/home/user/project/.next')
    expect(frame.file).toBe(
      'file:///home/user/project/.next/static/chunks/app.js'


xt/dist/compiled/stacktrace-parser'

const regexNextStatic = /\/_next(\/static\/.+)/

export interface StackFrame {
  file: string | null
  methodName: string
  arguments: string[]
  /** 1-based */
  line1: number | null
  /** 1-based */
  column1: number | null
}

export function parseStack(
  stack: string,
  distDir = process.env.__NEXT_DIST_DIR
): StackFrame[] {
  if (!stack) return []

  // throw away eval information that stacktrace-parser doesn't support
  // adapted from https://github.com/stacktrac

place(/eval code/g, 'eval')
          .replace(/\(eval at [^()]* \(/, '(file://')
          .replace(/\),.*$/g, ')')
      }

      return line
    })
    .join('\n')

  const frames = parse(stack)
  return frames.map((frame) => {
    try {
      const url

ejs/error-stack-parser/blob/9f33c224b5d7b607755eb277f9d51fcdb7287e24/error-stack-parser.js#L59C33-L59C62
  stack = stack
    .split('\n')
    .map((line) => {
      if (line.includes('(eval ')) {
        line = line
          .re


/work-unit-async-storage.external'
import type { WorkStore } from '../app-render/work-async-storage.external'
import type { IncrementalCache } from './incremental-cache'
import { createPatchedFetcher } from './patch-fetch'

describe('createPatchedFetcher', () => {
  it('should not buffer a streamed response', async () => {
    const mockFetch: jest.MockedFunction<typeof fetch> = jest.fn()
    let streamChunk: () => void

    const readableStream = new ReadableStream({
      start(controller) {
        contr

ResolvedValue(new Response(readableStream))

    const workAsyncStorage = new AsyncLocalStorage<WorkStore>()

    const workUnitAsyncStorage = new AsyncLocalStorage<WorkUnitStore>()

    const patchedFetch = createPatchedFetcher(mockFetch, {
      // workU

oller.enqueue(new TextEncoder().encode('stream start'))
        streamChunk = () => {
          controller.enqueue(new TextEncoder().encode('stream end'))
          controller.close()
        }
      },
    })

    mockFetch.mock


ined | number {
  try {
    let normalizedRevalidate: number | undefined = undefined

    if (revalidateVal === false) {
      normalizedRevalidate = INFINITE_CACHE
    } else if (
      typeof revalidateVal === 'number' &&
      !isNaN(revalidateVal) &&
      revalidateVal > -1
    ) {
      normalizedRevalidate = revalidateVal
    } else if (typeof revalidateVal !== 'undefined') {
      throw new Error(
        `Invalid revalidate value "${revalidateVal}" on "${route}", must be a non-negative number or fa

{
      throw err
    }
    return undefined
  }
}

export function validateTags(tags: any[], description: string) {
  const validTags: string[] = []
  const invalidTags: Array<{
    tag: any
    reason: string
  }> = []

  for (let i = 0; i < tags.length;

lse`
      )
    }
    return normalizedRevalidate
  } catch (err: any) {
    // handle client component error from attempting to check revalidate value
    if (err instanceof Error && err.message.includes('Invalid revalidate'))


type NextIncomingMessage } from '../request-meta'

const PATCHED_SET_HEADER = Symbol('next.patchSetHeaderWithCookieSupport')

type PatchableResponse = {
  setHeader(key: string, value: string | string[]): PatchableResponse
  headersSent?: boolean
  [PATCHED_SET_HEADER]?: true
}

/**
 * Ensure cookies set in middleware are merged and not overridden by API
 * routes/getServerSideProps.
 *
 * @param req Incoming request
 * @param res Outgoing response
 */
export function patchSetHeaderWithCookieSupport(
  req:

eader = (
    name: string,
    value: string | string[]
  ): PatchableResponse => {
    // When renders /_error after page is failed, it could attempt to set
    // headers after headers.
    if ('headersSent' in res && res.headersSent) {
      return res

 NextIncomingMessage,
  res: PatchableResponse
) {
  if (res[PATCHED_SET_HEADER]) {
    return
  }

  const setHeader = res.setHeader.bind(res)

  Object.defineProperty(res, PATCHED_SET_HEADER, {
    value: true,
  })

  res.setH


STPONED_STATE_SIZE,
  parseMaxPostponedStateSize,
} from '../../shared/lib/size-limit'
import type { SizeLimit } from '../../types'

const INVALID_MAX_POSTPONED_STATE_SIZE_ERROR_MESSAGE =
  'maxPostponedStateSize must be a valid number (bytes) or filesize format string (e.g., "5mb")'

export type PostponedRequestBodyChunk = Buffer | Uint8Array | string

export function getMaxPostponedStateSize(
  configuredMaxPostponedStateSize: SizeLimit | undefined
): {
  maxPostponedStateSize: SizeLimit
  maxPostponedSta

  )

  if (maxPostponedStateSizeBytes === undefined) {
    throw new Error(INVALID_MAX_POSTPONED_STATE_SIZE_ERROR_MESSAGE)
  }

  return { maxPostponedStateSize, maxPostponedStateSizeBytes }
}

export function getPostponedStateExceededErrorMessage(
  maxPo

teSizeBytes: number
} {
  const maxPostponedStateSize =
    configuredMaxPostponedStateSize ?? DEFAULT_MAX_POSTPONED_STATE_SIZE
  const maxPostponedStateSizeBytes = parseMaxPostponedStateSize(
    configuredMaxPostponedStateSize


import next from '../next'
import type { Span } from '../../trace'
import type { ServerResponse } from 'http'
import type { OnCacheEntryHandler } from '../request-meta'
import { interopDefault } from '../../lib/interop-default'
import { formatDynamicImportPath } from '../../lib/format-dynamic-import-path'
import type { ConfiguredExperimentalFeature } from '../config'

export type ServerInitResult = {
  requestHandler: RequestHandler
  upgradeHandler: UpgradeHandler
  server: NextServer
  // Make an effort

sed for logging after server is ready
  experimentalFeatures: ConfiguredExperimentalFeature[]
  // Whether cache components is enabled
  cacheComponents: boolean
  // Whether AGENTS.md / CLAUDE.md auto-generation is enabled (default true)
  agentRules?: bo

 to close upgraded HTTP requests (e.g. Turbopack HMR websockets)
  closeUpgraded: () => void
  // The distDir from config, used by the parent process for telemetry/trace
  distDir: string
  // Experimental features from config, u


./router-utils/filesystem'
import { proxyRequest } from './router-utils/proxy-request'
import { isAbortError, pipeToNodeResponse } from '../pipe-readable'
import { getResolveRoutes } from './router-utils/resolve-routes'
import { addRequestMeta, getRequestMeta } from '../request-meta'
import { pathHasPrefix } from '../../shared/lib/router/utils/path-has-prefix'
import { removePathPrefix } from '../../shared/lib/router/utils/remove-path-prefix'
import setupCompression from 'next/dist/compiled/compression'
imp

{
  PHASE_PRODUCTION_SERVER,
  PHASE_DEVELOPMENT_SERVER,
  UNDERSCORE_NOT_FOUND_ROUTE,
} from '../../shared/lib/constants'
import { RedirectStatusCode } from '../../client/components/redirect-status-code'
import { DevBundlerService } from './dev-bundler-se

ort { signalFromNodeResponse } from '../web/spec-extension/adapters/next-request'
import { isPostpone } from './router-utils/is-postpone'
import { parseUrl as parseUrlUtil } from '../../shared/lib/router/utils/parse-url'

import


sage } from 'http'
import type { BaseNextRequest } from '../base-http'
import type { NextRequest } from '../web/exports'
import { ACTION_HEADER } from '../../client/components/app-router-headers'

export function getServerActionRequestMetadata(
  req: IncomingMessage | BaseNextRequest | NextRequest
): {
  actionId: string | null
  isURLEncodedAction: boolean
  isMultipartAction: boolean
  isFetchAction: boolean
  isPossibleServerAction: boolean
} {
  let actionId: string | null
  let contentType: string | n

tentType = req.headers['content-type'] ?? null
  }

  // We don't actually support URL encoded actions, and the action handler will bail out if it sees one.
  // But we still want it to flow through to the action handler, to prevent changes in behavior whe

ull

  if (req.headers instanceof Headers) {
    actionId = req.headers.get(ACTION_HEADER) ?? null
    contentType = req.headers.get('content-type')
  } else {
    actionId = (req.headers[ACTION_HEADER] as string) ?? null
    con


rames.
function ignoreList(frames: StackFrame[]) {
  ignoreListAnonymousStackFramesIfSandwiched(
    frames,
    (frame) => frame !== null && frame.file === '<anonymous>',
    (frame) => frame !== null && frame.ignored,
    (frame) => (frame === null ? '' : frame.methodName),
    (frame) => {
      frame!.ignored = true
    }
  )
}

test('hides small sandwiches', () => {
  const frames: StackFrame[] = [
    { ignored: true, file: 'file1.js', methodName: 'Page' },
    { ignored: false, file: '<anonymous>', m

e: '<anonymous>', methodName: 'JSON.parse' },
    { ignored: true, file: 'file2.js', methodName: 'render' },
  ])
})

test('hides big sandwiches', () => {
  const frames: StackFrame[] = [
    { ignored: true, file: 'file1.js', methodName: 'Page' },
    { i

ethodName: 'JSON.parse' },
    { ignored: true, file: 'file2.js', methodName: 'render' },
  ]

  ignoreList(frames)

  expect(frames).toEqual([
    { ignored: true, file: 'file1.js', methodName: 'Page' },
    { ignored: true, fil


SourceMap =
  process.env.NEXT_RUNTIME === 'edge'
    ? noSourceMap
    : (require('module') as typeof import('module')).findSourceMap

/**
 * https://tc39.es/source-map/#index-map
 */
interface IndexSourceMapSection {
  offset: {
    line: number
    column: number
  }
  map: BasicSourceMapPayload
}

// TODO(veil): Upstream types
/** https://tc39.es/ecma426/#sec-index-source-map */
interface IndexSourceMap {
  version: number
  file: string
  sections: IndexSourceMapSection[]
}

/** https://tc39.es/ecma426

 sourceRoot?: string
  // TODO: Move to https://github.com/jridgewell/sourcemaps which is actively maintained
  /** WARNING: `sources[number]` can be `null`. */
  sources: Array<string>
  names: Array<string>
  mappings: string
  ignoreList?: number[]
}

e

/#sec-source-map-format */
export interface BasicSourceMapPayload {
  version: number
  // TODO: Move to https://github.com/jridgewell/sourcemaps which is actively maintained
  /** WARNING: `file` is optional. */
  file: string


LOPMENT_SERVER,
} from '../../shared/lib/constants'
import {
  ensureAgentRulesForDev,
  getEnvInfo,
  logExperimentalInfo,
  logStartInfo,
} from './app-info-log'
import { validateTurboNextConfig } from '../../lib/turbopack-warning'
import {
  type Span,
  trace,
  flushAllTraces,
  exportTraceState,
  initializeTraceState,
} from '../../trace'
import { isIPv6 } from './is-ipv6'
import { AsyncCallbackSet } from './async-callback-set'
import type { NextServer } from '../next'
import { durationToString } fro

Port(port: number): Promise<string | null> {
  const timeoutMs = 250
  const processLookupController = new AbortController()

  const pidPromise = new Promise<string | null>((resolve) => {
    const handleError = (error: Error) => {
      debug('Failed to

m '../../build/duration-to-string'

const debug = setupDebug('next:start-server')
let startServerSpan: Span | undefined

/**
 * Get the process ID (PID) of the process using the specified port
 */
async function getProcessIdUsing


shared/lib/router/utils/is-bot'
import type { BaseNextRequest } from '../base-http'

let cachedPattern: string | undefined
let cachedRegex: RegExp | undefined

export function shouldServeStreamingMetadata(
  userAgent: string,
  htmlLimitedBots: string | undefined
): boolean {
  const pattern = htmlLimitedBots || HTML_LIMITED_BOT_UA_RE_STRING
  if (cachedPattern !== pattern) {
    cachedPattern = pattern
    cachedRegex = new RegExp(pattern, 'i')
  }
  // Only block metadata for HTML-limited bots
  if (user

false
  }
  return true
}

// When the request UA is a html-limited bot, we should do a dynamic render.
// In this case, postpone state is not sent.
export function isHtmlBotRequest(req: {
  headers: BaseNextRequest['headers']
}): boolean {
  const ua = re

Agent && cachedRegex!.test(userAgent)) {
    return


 './to-route'

describe('toRoute Function', () => {
  it('should remove trailing slash', () => {
    const result = toRoute('/example/')
    expect(result).toBe('/example')
  })

  it('should remove trailing `/index`', () => {
    const result = toRoute('/example/index')
    expect(result).toBe('/example')
  })

  it('should return `/` when input is `/index`', () => {
    const result = toRoute('/index')
    expect(result).toBe('/')
  })

  it('should return `/` when input is `/index/`', () => {
    const r

/')
  })

  it('should return `/` when input is only a slash', () => {
    const result = toRoute('/')
    expect(result).toBe('/')
  })

  it('should return `/` when input is empty', () => {
    const result = toRoute('')
    expect(result).toBe('/')
  })

esult = toRoute('/index/')
    expect(result).toBe('


nizeArgs,
  getParsedNodeOptions,
} from './utils'

const originalNodeOptions = process.env.NODE_OPTIONS

afterAll(() => {
  process.env.NODE_OPTIONS = originalNodeOptions
})

describe('tokenizeArgs', () => {
  it('splits arguments by spaces', () => {
    const result = tokenizeArgs('--spaces "thing with spaces" --normal 1234')

    expect(result).toEqual([
      '--spaces',
      'thing with spaces',
      '--normal',
      '1234',
    ])
  })

  it('supports quoted values', () => {
    const result = toke

h "spaces"',
      '--normal',
      '1234',
    ])
  })
})

describe('formatNodeOptions', () => {
  it('wraps values with spaces in quotes', () => {
    const result = formatNodeOptions({
      spaces: 'thing with spaces',
      spacesAndQuotes: 'thing wi

nizeArgs(
      '--spaces "thing with spaces" --spacesAndQuotes "thing with \\"spaces\\"" --normal 1234'
    )

    expect(result).toEqual([
      '--spaces',
      'thing with spaces',
      '--spacesAndQuotes',
      'thing wit


sage)
  } else {
    console.error(message)
  }

  return process.exit(code)
}

export type NodeOptions = Record<string, string | boolean | undefined>

const parseNodeArgs = (args: string[]): NodeOptions => {
  const { values, tokens } = parseArgs({ args, strict: false, tokens: true })

  // For the `NODE_OPTIONS`, we support arguments with values without the `=`
  // sign. We need to parse them manually.
  let orphan = null
  for (let i = 0; i < tokens.length; i++) {
    const token = tokens[i]

    if (to

option is orphaned, and we can assign it.
    if (token.kind === 'option') {
      orphan = typeof token.value === 'undefined' ? token : null
      continue
    }

    // If the token isn't a positional one, then we can't assign it to the found
    // orph

ken.kind === 'option-terminator') {
      break
    }

    // When we encounter an option, if it's value is undefined, we should check
    // to see if the following tokens are positional parameters. If they are,
    // then the


t { isCsrfOriginAllowed } from '../../app-render/csrf-protection'

const allowedDevOriginsDocs =
  'https://nextjs.org/docs/app/api-reference/config/next-config-js/allowedDevOrigins'

function getBlockedResourcePath(req: IncomingMessage): string {
  return parseUrl(req.url ?? '')?.pathname ?? req.url ?? '/_next/*'
}

function formatBlockedCrossSiteMessage(
  source: string | undefined,
  resourcePath: string
): string {
  const lines = [
    `Blocked cross-origin request to Next.js dev resource ${resourcePa

r an opaque/sandboxed origin
  // - hostname string: we parsed an allowlistable host from Origin/Referer
  // - `undefined` (and effectively empty string): the request did not include a usable host
  if (source === 'null') {
    lines.push(
      '',

th}${getBlockedSourceDescription(source)}.`,
    'Cross-origin access to Next.js dev resources is blocked by default for safety.',
  ]

  // `source` has 3 meanings here:
  // - `'null'`: browser explicitly sent `Origin: null` fo


ildDataRoute } from './build-data-route'

describe('buildDataRoute', () => {
  it('should build a dynamic data route', () => {
    const dataRoute = buildDataRoute('/[...slug]', '123')
    expect(dataRoute).toMatchInlineSnapshot(`
     {
       "dataRouteRegex": "^/_next/data/123/(.+?)\\.json$",
       "namedDataRouteRegex": "^/_next/data/123/(?<nxtPslug>.+?)\\.json$",
       "page": "/[...slug]",
       "routeKeys": {
         "nxtPslug": "nxtPslug",
       },
     }
    `)
  })

  it('should build a stati

taRoute('/about', '123')
    expect(dataRoute).toMatchInlineSnapshot(`
     {
       "dataRouteRegex": "^/_next/data/123/about\\.json$",
       "namedDataRouteRegex": undefined,
       "page": "/about",
       "routeKeys": undefined,
     }
    `)
  })
})


from '../../../shared/lib/isomorphic/path'
import { normalizePagePath } from '../../../shared/lib/page-path/normalize-page-path'
import { isDynamicRoute } from '../../../shared/lib/router/utils/is-dynamic'
import { getNamedRouteRegex } from '../../../shared/lib/router/utils/route-regex'
import { normalizeRouteRegex } from '../../../lib/load-custom-routes'
import { escapeStringRegexp } from '../../../shared/lib/escape-regexp'

export function buildDataRoute(page: string, buildId: string) {
  const pagePath =

ndefined

  if (isDynamicRoute(page)) {
    const routeRegex = getNamedRouteRegex(dataRoute, {
      prefixRouteKeys: true,
      includeSuffix: true,
      excludeOptionalTrailingSlash: true,
    })

    dataRouteRegex = normalizeRouteRegex(routeRegex.re.

 normalizePagePath(page)
  const dataRoute = path.posix.join('/_next/data', buildId, `${pagePath}.json`)

  let dataRouteRegex: string
  let namedDataRouteRegex: string | undefined
  let routeKeys: { [named: string]: string } | u


ort path from '../../../shared/lib/isomorphic/path'
import { normalizePagePath } from '../../../shared/lib/page-path/normalize-page-path'
import { getNamedRouteRegex } from '../../../shared/lib/router/utils/route-regex'
import {
  RSC_SEGMENT_SUFFIX,
  RSC_SEGMENTS_DIR_SUFFIX,
} from '../../../lib/constants'

export const SEGMENT_PATH_KEY = 'nextSegmentPath'

export type PrefetchSegmentDataRoute = {
  source: string
  destination: string
  routeKeys: { [key: string]: string }
}

export function buildPrefetc

Path}${RSC_SEGMENT_SUFFIX}`
  )

  const { namedRegex, routeKeys } = getNamedRouteRegex(destination, {
    prefixRouteKeys: true,
    includePrefix: true,
    includeSuffix: true,
    excludeOptionalTrailingSlash: true,
    backreferenceDuplicateKeys: true

hSegmentDataRoute(
  page: string,
  segmentPath: string
): PrefetchSegmentDataRoute {
  const pagePath = normalizePagePath(page)

  const destination = path.posix.join(
    `${pagePath}${RSC_SEGMENTS_DIR_SUFFIX}`,
    `${segment


ver/web/spec-extension/revalidate'
       export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
       export { io } from 'next/dist/server/request/io'

         /**
          * Cache this \`"use cache"\` for a timespan defined by the \`"default"\` profile.
          * \`\`\`
          *   stale:      3600 seconds (1 hour)
          *   revalidate: 900 seconds (15 minutes)
          *   expire:     86400 seconds (1 day)
          * \`\`\`
          *
          * T

affic for 1 day it will expire. The next request will recompute it.
          */
         export function cacheLife(profile: "default"): void

         /**
          * Cache this \`"use cache"\` for a timespan defined by the \`"hours"\` profile.

his cache may be stale on clients for 1 hour before checking with the server.
          * If the server receives a new request after 15 minutes, start revalidating new values in the background.
          * If this entry has no tr


} from '../route-matches/route-match'
import type { RouteDefinition } from '../route-definitions/route-definition'
import type { Params } from '../request/params'

import { isDynamicRoute } from '../../shared/lib/router/utils'
import {
  getRouteMatcher,
  type RouteMatchFn,
} from '../../shared/lib/router/utils/route-matcher'
import { getRouteRegex } from '../../shared/lib/router/utils/route-regex'

type RouteMatchResult = {
  params?: Params
}

export class RouteMatcher<D extends RouteDefinition = RouteDe

cate matches on routes.
   */
  public duplicated?: Array<RouteMatcher>

  constructor(public readonly definition: D) {
    if (isDynamicRoute(definition.pathname)) {
      this.dynamic = getRouteMatcher(getRouteRegex(definition.pathname))
    }
  }

  /**

finition> {
  private readonly dynamic?: RouteMatchFn

  /**
   * When set, this is an array of all the other matchers that are duplicates of
   * this one. This is used by the managers to warn the users about possible
   * dupli


onstants'
import type { CollectedCacheResult } from '../use-cache/use-cache-wrapper'

/**
 * A generic cache store type that provides a subset of Map functionality
 */
type CacheStore<T> = Pick<
  Map<string, T>,
  'entries' | 'keys' | 'size' | 'get' | 'set' | 'has' | typeof Symbol.iterator
>

/**
 * A cache store specifically for fetch cache values
 */
export type FetchCacheStore = CacheStore<CachedFetchValue>

/**
 * A cache store for encrypted bound args of inline server functions.
 */
export type Encryp

 for "use cache" entries
 */
export interface UseCacheCacheStoreSerialized {
  entry: {
    value: string
    tags: string[]
    stale: number
    timestamp: number
    expire: number
    revalidate: number
  }
  hasExplicitRevalidate: boolean | undefined

tedBoundArgsCacheStore = CacheStore<string>

/**
 * An in-memory-only cache store for decrypted bound args of inline server
 * functions.
 */
export type DecryptedBoundArgsCacheStore = CacheStore<string>

/**
 * Serialized format


tream-utils/node-web-streams-helper'
import { inflateSync } from 'node:zlib'

const isCacheComponentsEnabled = process.env.__NEXT_CACHE_COMPONENTS === 'true'

function createMockedCache() {
  const cache = createPrerenderResumeDataCache()

  // Should be included during serialization.
  cache.cache.set(
    'success',
    Promise.resolve({
      entry: {
        value: streamFromString('value'),
        tags: [],
        stale: 0,
        timestamp: 0,
        expire: 300,
        revalidate: 1,
      },

ic-expire',
    Promise.resolve({
      entry: {
        value: streamFromString('value'),
        tags: [],
        stale: 0,
        timestamp: 0,
        expire: 299,
        revalidate: 1,
      },
      hasExplicitRevalidate: true,
      hasExplicitEx

    hasExplicitRevalidate: true,
      hasExplicitExpire: true,
      readRootParamNames: undefined,
      dynamicNestedCacheError: undefined,
    })
  )

  // Should be omitted during serialization.
  cache.cache.set(
    'dynam


t {
  createBrowserRequest,
  handleBrowserPageResponse,
  DEFAULT_BROWSER_REQUEST_TIMEOUT_MS,
} from './utils/browser-communication'
import type {
  PageMetadata,
  PageSegment,
  SegmentTrieData,
} from '../../../shared/lib/mcp-page-metadata-types'
import type { SegmentTrieNode } from '../../../next-devtools/dev-overlay/segment-explorer-trie'
import { mcpTelemetryTracker } from '../mcp-telemetry-tracker'

export function registerGetPageMetadataTool(
  server: McpServer,
  sendHmrMessage: (message: HmrMess

 active browser sessions.',
      inputSchema: {},
    },
    async (_request) => {
      // Track telemetry
      mcpTelemetryTracker.recordToolCall('mcp/get_page_metadata')

      try {
        const connectionCount = getActiveConnectionCount()
        i

ageSentToBrowser) => void,
  getActiveConnectionCount: () => number
) {
  server.registerTool(
    'get_page_metadata',
    {
      description:
        'Get runtime metadata about what contributes to the current page render from


ate with the browser.
 * This module provides a common infrastructure for request-response
 * communication between MCP endpoints and browser sessions via HMR.
 */

import { nanoid } from 'next/dist/compiled/nanoid'
import type {
  HMR_MESSAGE_SENT_TO_BROWSER,
  HmrMessageSentToBrowser,
} from '../../../dev/hot-reloader-types'

export const DEFAULT_BROWSER_REQUEST_TIMEOUT_MS = 5000

export type BrowserResponse<T> = {
  url: string
  data: T
}

type PendingRequest<T> = {
  responses: BrowserResponse<T>[]
  e

wserRequest<T>(
  messageType: HMR_MESSAGE_SENT_TO_BROWSER,
  sendHmrMessage: (message: HmrMessageSentToBrowser) => void,
  getActiveConnectionCount: () => number,
  timeoutMs: number
): Promise<BrowserResponse<T>[]> {
  const connectionCount = getActiveCo

xpectedCount: number
  resolve: (value: BrowserResponse<T>[]) => void
  reject: (reason?: unknown) => void
  timeout: NodeJS.Timeout
}

const pendingRequests = new Map<string, PendingRequest<unknown>>()

export function createBro


ool discovers routes by scanning the filesystem directly. It finds all route
 * files in the app/ and pages/ directories and converts them to route paths.
 *
 * Returns routes grouped by router type:
 * - appRouter: App Router pages and route handlers
 * - pagesRouter: Pages Router pages and API routes
 *
 * Dynamic route segments appear as [id], [slug], or [...slug] patterns. This tool
 * does NOT expand getStaticParams - it only shows the route patterns as defined in
 * the filesystem.
 */
import type { M

lete } from '../../../server/config-shared'
import z from 'next/dist/compiled/zod'

export function registerGetRoutesTool(
  server: McpServer,
  options: {
    projectPath: string
    nextConfig: NextConfigComplete
    pagesDir: string | undefined
    app

cpServer } from 'next/dist/compiled/@modelcontextprotocol/sdk/server/mcp'
import { mcpTelemetryTracker } from '../mcp-telemetry-tracker'
import { discoverRoutes } from '../../../build/route-discovery'
import type { NextConfigComp


../build/swc/types'
import stripAnsi from 'next/dist/compiled/strip-ansi'

/** Convert a StyledString tree to Markdown. */
function styledStringToMarkdown(s: StyledString): string {
  switch (s.type) {
    case 'text':
      return s.value
    case 'code':
      return `\`${s.value}\``
    case 'strong':
      return `**${s.value}**`
    case 'line':
      return s.value.map(styledStringToMarkdown).join('')
    case 'stack':
      return s.value.map(styledStringToMarkdown).join('\n')
    default:
      retu

ine: number; column: number }
      /** 1-indexed */
      end: { line: number; column: number }
    }
  }
  /** Code frame with ANSI codes stripped */
  codeFrame?: string
}

/**
 * Transform raw Turbopack issues into a clean format for MCP consumers:
 *

rn ''
  }
}

export interface FormattedIssue {
  severity: string
  filePath: string
  title: string
  description?: string
  detail?: string
  source?: {
    filePath: string
    range?: {
      /** 1-indexed */
      start: { l


 const ENCODED_TAGS = {
  // opening tags do not have the closing `>` since they can contain other attributes such as `<body className=''>`
  OPENING: {
    // <html
    HTML: new Uint8Array([60, 104, 116, 109, 108]),
    // <head
    HEAD: new Uint8Array([60, 104, 101, 97, 100]),
    // <body
    BODY: new Uint8Array([60, 98, 111, 100, 121]),
  },
  CLOSED: {
    // </head>
    HEAD: new Uint8Array([60, 47, 104, 101, 97, 100, 62]),
    // </body>
    BODY: new Uint8Array([60, 47, 98, 111, 100, 121, 62]),

/ Only the match the prefix cause the suffix can be different wether it's xml compatible or not ">" or "/>"
    // <meta name="«nxt-icon»"
    // This is a special mark that will be replaced by the icon insertion script tag.
    ICON_MARK: new Uint8Array([


pack/loaders/next-app-loader'
import { DEFAULT_SEGMENT_KEY } from '../../shared/lib/segment'

/**
 * LoaderTree is generated in next-app-loader.
 */
export type LoaderTree = [
  segment: string,
  parallelRoutes: { [parallelRouterKey: string]: LoaderTree },
  modules: AppDirModules,
  /**
   * At build time, for each dynamic segment, we compute the list of static
   * sibling segments that exist at the same URL path level. This is used by
   * the client router to determine if a prefetch can be reused.
   *

gs: ['sale']
   *
   * This accounts for route groups, which may place sibling routes in
   * different parts of the file system tree but at the same URL level.
   *
   * A value of `null` means the static siblings are unknown (e.g., in webpack
   * dev mo

   * For example, given the following file structure:
   *   /app/(group1)/products/sale/page.tsx -> /products/sale
   *   /app/(group2)/products/[id]/page.tsx -> /products/[id]
   *
   * The [id] segment would have staticSiblin


ort { CACHE_ONE_YEAR_SECONDS } from '../../lib/constants'

/**
 * The revalidate option used internally for pages. A value of `false` means
 * that the page should not be revalidated. A number means that the page
 * should be revalidated after the given number of seconds (this also includes
 * `1` which means to revalidate after 1 second). A value of `0` is not a valid
 * value for this option.
 */
export type Revalidate = number | false

export interface CacheControl {
  revalidate: Revalidate
  expire: nu

`, stale-while-revalidate=${expire - revalidate}`
      : ''

  if (revalidate === 0) {
    return 'private, no-cache, no-store, max-age=0, must-revalidate'
  } else if (typeof revalidate === 'number') {
    return `s-maxage=${revalidate}${swrHeader}`
  }

mber | undefined
}

export function getCacheControlHeader({
  revalidate,
  expire,
}: CacheControl): string {
  const swrHeader =
    typeof revalidate === 'number' &&
    expire !== undefined &&
    revalidate < expire
      ?


gistry<WeakRef<ReadableStream>> | undefined

if (globalThis.FinalizationRegistry) {
  registry = new FinalizationRegistry((weakRef: WeakRef<ReadableStream>) => {
    const stream = weakRef.deref()
    if (stream && !stream.locked) {
      stream.cancel('Response object has been garbage collected').then(noop)
    }
  })
}

/**
 * Clones a response by teeing the body so we can return two independent
 * ReadableStreams from it. This avoids the bug in the undici library around
 * response cloning.
 *
 * After c

es of the original response.
 */
export function cloneResponse(original: Response): [Response, Response] {
  // If the response has no body, then we can just return the original response
  // twice because it's immutable.
  if (!original.body) {
    return

loning, the original response's body will be consumed and closed.
 *
 * @see https://github.com/vercel/next.js/pull/73274
 *
 * @param original - The original response to clone.
 * @returns A tuple containing two independent clon


of fetch>
  let dedupeFetch: ReturnType<typeof createDedupeFetch>

  beforeEach(() => {
    // Create a fresh mock for each test
    originalFetch = jest.fn()
    dedupeFetch = createDedupeFetch(originalFetch)

    // Clear all mocks between tests
    jest.clearAllMocks()
  })

  describe('deduplication behavior', () => {
    it('should dedupe identical GET requests', async () => {
      const mockResponse = new Response('test response', { status: 200 })
      originalFetch.mockResolvedValue(mockResponse)

romise2])

      // Should only call original fetch once
      expect(originalFetch).toHaveBeenCalledTimes(1)
      expect(originalFetch).toHaveBeenCalledWith(
        'https://example.com/api',
        undefined
      )

      // Both responses should be

      // Make two identical requests
      const promise1 = dedupeFetch('https://example.com/api')
      const promise2 = dedupeFetch('https://example.com/api')

      const [response1, response2] = await Promise.all([promise1, p


es/react/src/ReactFetch.js
 */
import * as React from 'react'
import { cloneResponse } from './clone-response'
import { InvariantError } from '../../shared/lib/invariant-error'

const simpleCacheKey = '["GET",[],null,"follow",null,null,null,null]' // generateCacheKey(new Request('https://blank'));

// Headers that should not affect deduplication
// traceparent and tracestate are used for distributed tracing and should not affect cache keys
const headersToExcludeInCacheKey = new Set(['traceparent', 'tracesta

from the first request.
  // Notably we currently don't consider non-standard (or future) options.
  // This might not be safe. TODO: warn for non-standard extensions differing.
  // IF YOU CHANGE THIS UPDATE THE simpleCacheKey ABOVE.

  const filteredHead

te'])

function generateCacheKey(request: Request): string {
  // We pick the fields that goes into the key used to dedupe requests.
  // We don't include the `cache` field, because we end up using whatever
  // caching resulted


ry character outside printable ASCII so a tag value can be
 * safely serialized as part of the `x-next-cache-tags` HTTP header.
 *
 * Node's `validateHeaderValue` rejects any code unit outside `\t\x20-\x7e`, so
 * a matched route path or user-supplied tag containing a non-ASCII character
 * (Hebrew, Arabic, Chinese, emoji, …) would otherwise throw `ERR_INVALID_CHAR`
 * and crash ISR on every affected request.
 *
 * This is applied at the public boundaries — tag construction
 * (`getImplicitTags`, `validateT

dHdrChars` table —
 * `\t` plus printable ASCII through `~`. Anything outside that is rejected
 * by `validateHeaderValue`, so we encode runs of those characters and leave
 * everything else (`,`, `/`, `%`, `[`, `]`, `_`, `-`, `\t`, …) byte-for-byte
 * unc

ags`) and invalidation input (`revalidatePath`,
 * `revalidateTag`, `updateTag`) — so storage, comparison, and the wire all see
 * the same canonical ASCII-safe form.
 *
 * The character class `[\t\x20-\x7e]` mirrors Node's `vali


ze } from 'path'
import { promises as fsPromises } from 'fs'
import { warn } from '../../build/output/log'
import { cyan } from '../../lib/picocolors'
import { isMetadataRouteFile } from '../../lib/metadata/is-metadata-route'
import { escapeStringRegexp } from '../../shared/lib/escape-regexp'
import type { PageExtensions } from '../../build/page-extensions-type'

async function isTrueCasePagePath(pagePath: string, pagesDir: string) {
  const pageSegments = normalize(pagePath).split(sep).filter(Boolean)
  co

ntDirEntries.includes(segment)
  })

  return (await Promise.all(segmentExistsPromises)).every(Boolean)
}

/**
 * Finds a page file with the given parameters. If the page is duplicated with
 * multiple extensions it will throw, otherwise it will return the

nst segmentExistsPromises = pageSegments.map(async (segment, i) => {
    const segmentParentDir = join(pagesDir, ...pageSegments.slice(0, i))
    const parentDirEntries = await fsPromises.readdir(segmentParentDir)
    return pare


index of Uint8Array `b` within Uint8Array `a`.
 */
export function indexOfUint8Array(a: Uint8Array, b: Uint8Array) {
  if (b.length === 0) return 0
  if (a.length === 0 || b.length > a.length) return -1

  // Use Node's native implementation when available.
  if (typeof Buffer !== 'undefined') {
    const haystack = Buffer.isBuffer(a)
      ? a
      : Buffer.from(a.buffer, a.byteOffset, a.byteLength)
    return haystack.indexOf(b)
  }

  // start iterating through `a`
  for (let i = 0; i <= a.length - b.le

iteration early and iterate to next index of `a`.
      if (a[i + j] !== b[j]) {
        completeMatch = false
        break
      }
    }

    if (completeMatch) {
      return i
    }
  }

  return -1
}

/**
 * Check if two Uint8Arrays are strictly equiv

ngth; i++) {
    let completeMatch = true
    // from index `i`, iterate through `b` and check for mismatch
    for (let j = 0; j < b.length; j++) {
      // if the values do not match, then this isn't a complete match, exit `b`


 callback, and execute any *new* revalidations added during its runtime. */
export async function withExecuteRevalidates<T>(
  store: WorkStore | undefined,
  callback: () => Promise<T>
): Promise<T> {
  if (!store) {
    return callback()
  }
  // If we executed any revalidates during the request, then we don't want to execute them again.
  // save the state so we can check if anything changed after we're done running callbacks.
  const savedRevalidationState = cloneRevalidationState(store)
  try {
    ret

tate(store)
    )
    await executeRevalidates(store, newRevalidates)
  }
}

type RevalidationState = Required<
  Pick<
    WorkStore,
    'pendingRevalidatedTags' | 'pendingRevalidates' | 'pendingRevalidateWrites'
  >
>

function cloneRevalidationState(st

urn await callback()
  } finally {
    // Check if we have any new revalidates, and if so, wait until they are all resolved.
    const newRevalidates = diffRevalidationState(
      savedRevalidationState,
      cloneRevalidationS


import type { AppRouteRouteModule } from './app-route/module'
import type { AppPageRouteModule } from './app-page/module'
import type { PagesRouteModule } from './pages/module'
import type { PagesAPIRouteModule } from './pages-api/module'

import type { RouteModule } from './route-module'

import { RouteKind } from '../route-kind'

export function isAppRouteRouteModule(
  routeModule: RouteModule
): routeModule is AppRouteRouteModule {
  return routeModule.definition.kind === RouteKind.APP_ROUTE
}

export f

eModule is PagesRouteModule {
  return routeModule.definition.kind === RouteKind.PAGES
}

export function isPagesAPIRouteModule(
  routeModule: RouteModule
): routeModule is PagesAPIRouteModule {
  return routeModule.definition.kind === RouteKind.PAGES_API

unction isAppPageRouteModule(
  routeModule: RouteModule
): routeModule is AppPageRouteModule {
  return routeModule.definition.kind === RouteKind.APP_PAGE
}

export function isPagesRouteModule(
  routeModule: RouteModule
): rout


 from 'next/dist/compiled/@modelcontextprotocol/sdk/server/mcp'
import { mcpTelemetryTracker } from '../mcp-telemetry-tracker'

export function registerGetProjectMetadataTool(
  server: McpServer,
  projectPath: string,
  getDevServerUrl: () => string | undefined
) {
  server.registerTool(
    'get_project_metadata',
    {
      description:
        'Returns the the metadata of this Next.js project, including project path, dev server URL, etc.',
      inputSchema: {},
    },
    async (_request) => {

    text: JSON.stringify({
                  error:
                    'Unable to determine the absolute path of the Next.js project.',
                }),
              },
            ],
          }
        }

        const devServerUrl = getDevServerUrl

// Track telemetry
      mcpTelemetryTracker.recordToolCall('mcp/get_project_metadata')

      try {
        if (!projectPath) {
          return {
            content: [
              {
                type: 'text',


from 'next/dist/compiled/zod'
import { promises as fs } from 'fs'
import { join } from 'path'
import { mcpTelemetryTracker } from '../mcp-telemetry-tracker'

const INLINE_ACTION_PREFIX = '$$RSC_SERVER_ACTION_'

interface ActionEntry {
  workers?: Record<string, any>
  layer?: Record<string, string>
  filename: string
  exportedName: string
}

interface ServerReferenceManifest {
  node: Record<string, ActionEntry>
  edge: Record<string, ActionEntry>
  encryptionKey: string
}

export function registerGetActio

 and export name for the action.',
      inputSchema: {
        actionId: z.string(),
      },
    },
    async (request) => {
      // Track telemetry
      mcpTelemetryTracker.recordToolCall('mcp/get_server_action_by_id')

      try {
        const { act

nByIdTool(server: McpServer, distDir: string) {
  server.registerTool(
    'get_server_action_by_id',
    {
      description:
        'Locates a Server Action by its ID in the server-reference-manifest.json. Returns the filename


is read-only and cannot be modified once created.
 */
export interface RenderResumeDataCache {
  /**
   * Discriminator. `false` means this cache is read-only and cannot be filled
   * with new entries. Used by `ResumeDataCache` consumers to narrow the union
   * via standard discriminated-union narrowing (e.g. `if
   * (resumeDataCache.mutable)`).
   */
  readonly mutable: false

  /**
   * A read-only Map store for values cached by the 'use cache' React hook.
   * The 'set' operation is omitted to enforce

acheStore, 'set'>

  /**
   * A read-only Map store for encrypted bound args of inline server functions.
   * The 'set' operation is omitted to enforce immutability.
   */
  readonly encryptedBoundArgs: Omit<EncryptedBoundArgsCacheStore, 'set'>

  /**
   *

 immutability.
   */
  readonly cache: Omit<UseCacheCacheStore, 'set'>

  /**
   * A read-only Map store for cached fetch responses.
   * The 'set' operation is omitted to enforce immutability.
   */
  readonly fetch: Omit<FetchC


ype { NextConfigRuntime } from '../config-shared'

import { randomUUID } from 'crypto'
import * as fs from 'fs'
import * as path from 'path'
import { getStorageDirectory } from '../cache-dir'

// Keep the uuid in memory as it should never change during the lifetime of the server.
let workspaceUUID: string | null = null

export function isChromeDevtoolsWorkspaceUrl(
  pathname: string | undefined
): boolean {
  return pathname === '/.well-known/appspecific/com.chrome.devtools.json'
}

export async function h

      await getChromeDevtoolsWorkspace(opts.dir, config.distDir),
      null,
      2
    )
  )
}

/**
 * https://developer.chrome.com/docs/devtools/workspaces#generate-json
 */
interface ChromeDevtoolsWorkspace {
  workspace: {
    uuid: string
    root:

andleChromeDevtoolsWorkspaceRequest(
  response: ServerResponse,
  opts: { dir: string },
  config: NextConfigRuntime
): Promise<void> {
  response.setHeader('Content-Type', 'application/json')
  response.end(
    JSON.stringify(


bundler'
import type { WorkerRequestHandler } from './types'

import { LRUCache } from './lru-cache'
import { createRequestResponseMocks } from './mock-request'
import {
  HMR_MESSAGE_SENT_TO_BROWSER,
  type HmrMessageSentToBrowser,
  type NextJsHotReloaderInterface,
} from '../dev/hot-reloader-types'

/**
 * The DevBundlerService provides an interface to perform tasks with the
 * bundler while in development.
 */
export class DevBundlerService {
  public appIsrManifestInner: InstanceType<typeof LRUCache<bo

rsToBrowser: NextJsHotReloaderInterface['sendErrorsToBrowser']

  constructor(
    private readonly bundler: DevBundler,
    private readonly handler: WorkerRequestHandler
  ) {
    this.appIsrManifestInner = new LRUCache(
      8_000,

      function leng

olean>>
  public close: NextJsHotReloaderInterface['close']
  public setCacheStatus: NextJsHotReloaderInterface['setCacheStatus']
  public setReactDebugChannel: NextJsHotReloaderInterface['setReactDebugChannel']
  public sendErro


 * FNV-1a Hash implementation
 * @author Travis Webb (tjwebb) <me@traviswebb.com>
 *
 * Ported from https://github.com/tjwebb/fnv-plus/blob/master/index.js
 *
 * Simplified, optimized and add modified for 52 bit, which provides a larger hash space
 * and still making use of Javascript's 53-bit integer space.
 */
export const fnv1a52 = (str: string) => {
  const len = str.length
  let i = 0,
    t0 = 0,
    v0 = 0x2325,
    t1 = 0,
    v1 = 0x8422,
    t2 = 0,
    v2 = 0x9ce4,
    t3 = 0,
    v3 = 0xcbf2


 from 'react-dom'
import * as ReactJsxDevRuntime from 'react/jsx-dev-runtime'
import * as ReactJsxRuntime from 'react/jsx-runtime'
import * as ReactCompilerRuntime from 'react/compiler-runtime'

import * as ReactDOMServer from 'react-dom/server'

function getAltProxyForBindingsDEV(
  type: 'Turbopack' | 'Webpack',
  pkg: 'react-server-dom-turbopack/client' | 'react-server-dom-webpack/client'
) {
  if (process.env.NODE_ENV === 'development') {
    const altType = type === 'Turbopack' ? 'Webpack' : 'Turbopack

kg}) for React but the current process is referencing '${prop}' from the ${altType} bindings (${altPkg}). This is likely a bug in our integration of the Next.js server runtime.`
          )
        },
      }
    )
  }
}

let ReactServerDOMTurbopackClient,

'
    const altPkg = pkg.replace(new RegExp(type, 'gi'), altType.toLowerCase())

    return new Proxy(
      {},
      {
        get(_, prop: string) {
          throw new Error(
            `Expected to use ${type} bindings (${p


h (e.g. "/blog/hello-world") to its matching Next.js route
 * specifier (e.g. "/blog/[slug]") using the dev router's own live route table.
 *
 * The `matchers` argument is a thin view of `fsChecker` from the router-server
 * process — the same data structure `resolve-routes.ts` iterates on every
 * incoming HTTP request — so first-match ordering and live route updates are
 * inherited for free.
 */
export interface RouteMatcherView {
  appFiles: ReadonlySet<string>
  pageFiles: ReadonlySet<string>
  dynamic

athname: string } {
  let pathname = path
  const q = pathname.indexOf('?')
  if (q >= 0) pathname = pathname.slice(0, q)
  const h = pathname.indexOf('#')
  if (h >= 0) pathname = pathname.slice(0, h)
  if (!pathname.startsWith('/')) pathname = '/' + path

Routes: ReadonlyArray<{
    page: string
    match: (pathname: string) => false | object
  }>
}

export function resolvePathToRoute(
  path: string,
  matchers: RouteMatcherView
): { routeSpecifier: string } | { notFound: true; p


'../../build/output/log'
import { bold, purple, strikethrough } from '../../lib/picocolors'
import type { ConfiguredExperimentalFeature } from '../config'
import { experimentalSchema } from '../config-schema'
import { detectAgent } from '../../telemetry/detect-agent'
import {
  hasAgentRulesInstalled,
  writeAgentFiles,
  type AgentFilesResult,
} from './generate-agent-files'

// Re-export the type for consumers
export type { ConfiguredExperimentalFeature }

/**
 * Logs basic startup info that doesn't requi

]
  logBundler: boolean
}) {
  let versionSuffix = ''
  const parts = []

  if (logBundler) {
    if (process.env.TURBOPACK) {
      parts.push('Turbopack')
    } else if (process.env.NEXT_RSPACK) {
      parts.push('Rspack')
    } else {
      parts.push(

re config.
 * Called before "Ready in X" to show immediate feedback.
 */
export function logStartInfo({
  networkUrl,
  appUrl,
  envInfo,
  logBundler,
}: {
  networkUrl: string | null
  appUrl: string | null
  envInfo?: string[


 from '../route-definitions/locale-route-definition'
import type { LocaleRouteMatch } from '../route-matches/locale-route-match'
import { RouteMatcher } from './route-matcher'

export type LocaleMatcherMatchOptions = {
  /**
   * If defined, this indicates to the matcher that the request should be
   * treated as locale-aware. If this is undefined, it means that this
   * application was not configured for additional locales.
   */
  i18n?: LocaleAnalysisResult
}

export class LocaleRouteMatcher<
  D extend

ynamic routes,
   * so it must contain the pathname part as well.
   */
  public get identity(): string {
    return `${this.definition.pathname}?__nextLocale=${this.definition.i18n?.locale}`
  }

  /**
   * Match will attempt to match the given pathname a

s LocaleRouteDefinition = LocaleRouteDefinition,
> extends RouteMatcher<D> {
  /**
   * Identity returns the identity part of the matcher. This is used to compare
   * a unique matcher to another. This is also used when sorting d


t { getErrorSource } from '../../../../shared/lib/error-source'
import type {
  OriginalStackFramesRequest,
  OriginalStackFramesResponse,
} from '../../../../next-devtools/server/shared'

type StackFrameForFormatting = {
  file: string | null
  methodName: string
  line1: number | null
  column1: number | null
}

type StackFrameResolver = (
  request: OriginalStackFramesRequest
) => Promise<OriginalStackFramesResponse>

// Dependency injection for stack frame resolver
let stackFrameResolver: StackFrameReso

f (!stackFrameResolver) {
    throw new Error(
      'Stack frame resolver not initialized. This is a bug in Next.js.'
    )
  }
  return stackFrameResolver(request)
}

interface StackFrame {
  file: string
  methodName: string
  line: number | null
  colu

lver | undefined

export function setStackFrameResolver(fn: StackFrameResolver) {
  stackFrameResolver = fn
}

async function resolveStackFrames(
  request: OriginalStackFramesRequest
): Promise<OriginalStackFramesResponse> {
  i


me = process.env.__NEXT_PRIVATE_CPU_PROFILE
const isCpuProfileEnabled = process.env.NEXT_CPU_PROF || privateCpuProfileName
const cpuProfileDir = process.env.NEXT_CPU_PROF_DIR

let session: import('inspector').Session | null = null
let profileSaved = false

if (isCpuProfileEnabled) {
  const { Session } = require('inspector') as typeof import('inspector')

  session = new Session()
  session.connect()

  session.post('Profiler.enable')
  session.post('Profiler.start')

  process.on('exit', () => {
    saveCp

 session.connect()).
 */
export function saveCpuProfile(): void {
  if (!session || profileSaved || !isCpuProfileEnabled) {
    return
  }
  profileSaved = true

  const fs = require('fs') as typeof import('fs')
  const path = require('path') as typeof imp

uProfile()
  })
}

/**
 * Save the CPU profile to disk.
 *
 * This is synchronous despite the callback-based API because inspector's
 * session.post() executes its callback synchronously when connected to
 * the same process (via


'fs'
import { LRUCache } from './lru-cache'

/**
 * Module-level LRU singleton for disk cache eviction.
 * Initialized once on first `set()`, shared across all consumers.
 * Once resolved, the promise stays resolved — subsequent calls just await the cached result.
 */
let _diskLRUPromise: Promise<LRUCache<number>> | null = null

/**
 * Initialize or return the module-level LRU for disk cache eviction.
 * Concurrent calls are deduplicated via the shared promise.
 *
 * @param cacheDir - The directory where ca

xDiskSize: number | undefined,
  readEntries: (
    cacheDir: string
  ) => Promise<Array<{ key: string; size: number; expireAt: number }>>,
  evictEntry: (cacheDir: string, cacheKey: string) => Promise<void>
): Promise<LRUCache<number>> {
  if (!_diskLRUP

ched files are stored
 * @param maxDiskSize - Maximum disk cache size in bytes
 * @param readEntries - Callback to scan existing cache entries (format-agnostic)
 */
export async function getOrInitDiskLRU(
  cacheDir: string,
  ma


definitions'

describe('create-env-definitions', () => {
  it('should create env definitions', async () => {
    const loadedEnvFiles = [
      {
        path: '.env.local',
        contents: '',
        env: {
          FROM_ENV_LOCAL: 'FROM_ENV_LOCAL',
        },
      },
      {
        path: '.env.development.local',
        contents: '',
        env: {
          FROM_ENV_DEV_LOCAL: 'FROM_ENV_DEV_LOCAL',
        },
      },
      {
        path: 'next.config.js',
        contents: '',
        env: {

      "// Type definitions for Next.js environment variables
      declare global {
        namespace NodeJS {
          interface ProcessEnv {
            /** Loaded from \`.env.local\` */
            FROM_ENV_LOCAL?: string
            /** Loaded from \`

       FROM_NEXT_CONFIG: 'FROM_NEXT_CONFIG',
        },
      },
    ]
    const definitionStr = await createEnvDefinitions({
      distDir: '/dist',
      loadedEnvFiles,
    })
    expect(definitionStr).toMatchInlineSnapshot(`


m '../../shared/lib/i18n/detect-domain-locale'
import { formatNextPathnameInfo } from '../../shared/lib/router/utils/format-next-pathname-info'
import { getHostname } from '../../shared/lib/get-hostname'
import { getNextPathnameInfo } from '../../shared/lib/router/utils/get-next-pathname-info'

interface Options {
  base?: string | URL
  headers?: OutgoingHttpHeaders
  forceLocale?: boolean
  nextConfig?: {
    basePath?: string
    i18n?: I18NConfig | null
    trailingSlash?: boolean
  }
  i18nProvider?: I

ase && String(base))
  if (REGEX_LOCALHOST_HOSTNAME.test(parsed.hostname)) {
    parsed.hostname = 'localhost'
  }
  return parsed
}

const Internal = Symbol('NextURLInternal')

export class NextURL {
  private [Internal]: {
    basePath: string
    buildI

18NProvider
}

const REGEX_LOCALHOST_HOSTNAME =
  /^(?:127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}|\[::1\]|localhost)$/

function parseURL(url: string | URL, base?: string | URL) {
  const parsed = new URL(String(url), b


EXT_RSC_UNION_QUERY,
  RSC_HEADER,
} from '../../client/components/app-router-headers'
import { ensureInstrumentationRegistered } from './globals'
import { createRequestStoreForAPI } from '../async-storage/request-store'
import { workUnitAsyncStorage } from '../app-render/work-unit-async-storage.external'
import { createWorkStore } from '../async-storage/work-store'
import { workAsyncStorage } from '../app-render/work-async-storage.external'
import { NEXT_ROUTER_PREFETCH_HEADER } from '../../client/componen

from './web-on-close'
import { getEdgePreviewProps } from './get-edge-preview-props'
import { getBuiltinRequestContext } from '../after/builtin-request-context'
import { getImplicitTags } from '../lib/implicit-tags'
import { isRSCRequestHeader } from '../l

ts/app-router-headers'
import { getTracer } from '../lib/trace/tracer'
import type { TextMapGetter } from 'next/dist/compiled/@opentelemetry/api'
import { MiddlewareSpan } from '../lib/trace/constants'
import { CloseController }


ss PageSignatureError extends Error {
  constructor({ page }: { page: string }) {
    super(`The middleware "${page}" accepts an async API directly with the form:

  export function middleware(request, event) {
    return NextResponse.redirect('/new-location')
  }

  Read more: https://nextjs.org/docs/messages/middleware-new-signature
  `)
  }
}

export class RemovedPageError extends Error {
  constructor() {
    super(`The request.page has been deprecated in favour of \`URLPattern\`.
  Read more: https

docs/messages/middleware-request-page
  `)
  }
}

export class RemovedUAError extends Error {
  constructor() {
    super(`The request.ua has been removed in favour of \`userAgent\` function.
  Read more: https://nextjs.org/docs/messages/middleware-parse-u


es'

declare const _ENTRIES: any

export async function getEdgeInstrumentationModule(): Promise<
  InstrumentationModule | undefined
> {
  const instrumentation =
    '_ENTRIES' in globalThis &&
    _ENTRIES.middleware_instrumentation &&
    (await _ENTRIES.middleware_instrumentation)

  return instrumentation
}

let instrumentationModulePromise: Promise<any> | null = null
async function registerInstrumentation() {
  // Ensure registerInstrumentation is not called in production build
  if (process.env.NEXT_

ation?.register) {
    try {
      await instrumentation.register()
    } catch (err: any) {
      err.message = `An error occurred while loading instrumentation hook: ${err.message}`
      throw err
    }
  }
}

export async function edgeInstrumentationOn

PHASE === 'phase-production-build') return
  if (!instrumentationModulePromise) {
    instrumentationModulePromise = getEdgeInstrumentationModule()
  }
  const instrumentation = await instrumentationModulePromise
  if (instrument


./../../shared/lib/router/utils/escape-path-delimiters'
import { DecodeError } from '../../../shared/lib/utils'

/**
 * We only encode path delimiters for path segments from
 * getStaticPaths so we need to attempt decoding the URL
 * to match against and only escape the path delimiters
 * this allows non-ascii values to be handled e.g.
 * Japanese characters.
 * */
function decodePathParams(pathname: string): string {
  // TODO: investigate adding this handling for non-SSG
  // pages so non-ascii names also

map((seg) => {
      try {
        seg = escapePathDelimiters(decodeURIComponent(seg), true)
      } catch (_) {
        // An improperly encoded URL was provided
        throw new DecodeError('Failed to decode path param(s).')
      }
      return seg

 work there.
  return pathname
    .split('/')
    .


m '../../../lib/load-custom-routes'
import { modifyRouteRegex } from '../../../lib/redirect-status'
import { FileType, fileExists } from '../../../lib/file-exists'
import { recursiveReadDir } from '../../../lib/recursive-readdir'
import { isDynamicRoute } from '../../../shared/lib/router/utils'
import { escapeStringRegexp } from '../../../shared/lib/escape-regexp'
import { getPathMatch } from '../../../shared/lib/router/utils/path-match'
import {
  getNamedRouteRegex,
  getRouteRegex,
} from '../../../share

 '../../../shared/lib/i18n/normalize-locale-path'
import { removePathPrefix } from '../../../shared/lib/router/utils/remove-path-prefix'
import { getMiddlewareRouteMatcher } from '../../../shared/lib/router/utils/middleware-route-matcher'
import {
  APP_PA

d/lib/router/utils/route-regex'
import { getRouteMatcher } from '../../../shared/lib/router/utils/route-matcher'
import { pathHasPrefix } from '../../../shared/lib/router/utils/path-has-prefix'
import { normalizeLocalePath } from