 type { Instant } from 'next'
import { cookies } from 'next/headers'
import assert from 'node:assert'

import { Suspense } from 'react'

export const unstable_instant: Instant = {
  level: 'experimental-error',
  unstable_samples: [
    {
      cookies: [
        { name: 'testCookie', value: 'testValue' },
        { name: 'missingCookie', value: null },
      ],
    },
  ],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <p>
        When

stCookies() {
  const cookieStore = await cookies()

  const testCookie = cookieStore.get('testCookie')
  assert.deepStrictEqual(testCookie, {
    name: 'testCookie',
    value: 'testValue',
  })

  const missingCookie = cookieStore.get('missingCookie')

validated in build, the page should receive the cookies specified
        in the sample.

      <Suspense fallback={
Loading...
}>
        <TestCookies />
      </Suspense>

  )
}

async function Te


'
import { ensureThrows } from '../../../../ensure-error'

export const unstable_instant = { level: 'experimental-error' }
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <p>
        This page reads a cookie that is not declared in the sample, so it
        should fail validation with an exhaustiveness error. It catches the
        error thrown by the cookie access, but validation should still fail.
      </p>
      <Suspense fallback={<di

/Suspense>
    </main>
  )
}

async function TestCookies() {
  const cookieStore = await cookies()

  try {
    ensureThrows(
      () => cookieStore.get('undeclaredCookie'),
      `Expected get() to throw for undeclared cookies`
    )
  } catch (err) {

v>Loading...</div>}>
        <TestCookies />
      <


eaders } from 'next/headers'
import { Suspense } from 'react'
import { ensureThrows } from '../../../../ensure-error'

export const unstable_instant = {
  level: 'experimental-error',
  unstable_samples: [{ headers: [] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <p>
        This page reads a header that is not declared in the sample, so it
        should fail validation with an exhaustiveness error.
      </p>
      <Suspense fal

ading...</div>}>
        <TestHeaders />
      </Suspense>
    </main>
  )
}

async function TestHeaders() {
  const headerStore = await headers()
  ensureThrows(
    () => headerStore.has('undeclaredHeader'),
    `Expected has() to throw for undeclared he


ort type { Instant } from 'next'
import { headers } from 'next/headers'
import assert from 'node:assert'

import { Suspense } from 'react'

export const unstable_instant: Instant = {
  level: 'experimental-error',
  unstable_samples: [
    {
      headers: [
        ['testHeader', 'testValue'],
        ['missingHeader', null],
      ],
    },
  ],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <p>
        When validated in build, the pa

rStore = await headers()

  const testHeader = headerStore.get('testHeader')
  assert.equal(testHeader, 'testValue')

  const missingHeader = headerStore.get('missingHeader')
  assert.equal(missingHeader, undefined)
  assert.equal(headerStore.has('missingH

ge should receive the headers specified
        in the sample.

      <Suspense fallback={
Loading...
}>
        <TestHeaders />
      </Suspense>

  )
}

async function TestHeaders() {
  const heade


mport { headers } from 'next/headers'
import { Suspense } from 'react'
import { ensureThrows } from '../../../../ensure-error'

export const unstable_instant = {
  level: 'experimental-error',
  unstable_samples: [{ headers: [] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <p>
        This page reads a header that is not declared in the sample, so it
        should fail validation with an exhaustiveness error. It catches the

st headerStore = await headers()

  try {
    ensureThrows(
      () => headerStore.get('undeclaredHeader'),
      `Expected get() to throw for undeclared headers`
    )
  } catch (err) {
    // We swallow the error. It should still be reported and fail th

error thrown by the header access, but validation should still fail.

      <Suspense fallback={
Loading...
}>
        <TestHeaders />
      </Suspense>

  )
}

async function TestHeaders() {
  con


mport { headers } from 'next/headers'
import { Suspense } from 'react'
import { ensureThrows } from '../../../../ensure-error'

export const unstable_instant = {
  level: 'experimental-error',
  unstable_samples: [{ headers: [] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <p>
        This page reads a header that is not declared in the sample, so it
        should fail validation with an exhaustiveness error.
      </p>
      <Sus

tHeaders />
      </Suspense>
    </main>
  )
}

async function TestHeaders() {
  const headersStore = await headers()
  ensureThrows(
    () => headersStore.get('undeclaredHeader'),
    `Expected get() to throw for undeclared headers`
  )
  return null
}

pense fallback={
Loading...
}>
        <Tes


nse } from 'react'

export const unstable_instant = {
  level: 'experimental-error',
  unstable_samples: [{ cookies: [{ name: 'auth', value: '1' }] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (

        This page wraps all runtime/dynamic components in Suspense, so it should
        pass validation.

      <Suspense fallback={
Loading...
}>
        <Runtime />
      </Suspense>
      <Suspense fallback={
L

se>

  )
}

async function Runtime() {
  const c = await cookies()
  return
cookie: {c.get('auth')?.value}

}

async function Dynamic() {
  await connection()
  return
Dynamic content</div

oading...</div>}>
        <Dynamic />
      </Suspen


('preferred-region', () => {
  const { next, isNextStart } = nextTestSetup({
    files: __dirname,
  })

  it('should return success from Node.js API route', async () => {
    const res = await next.fetch('/api/test')
    expect(res.status).toBe(200)

    const data = await res.json()
    expect(data).toEqual({ status: 'success' })
  })

  it('should return success from Edge API route', async () => {
    const res = await next.fetch('/api/test-edge')
    expect(res.status).toBe(200)

    const data = await

igManifest
      let middlewareManifest

      try {
        // Check Functions Config Manifest (for Node.js runtime)
        functionsConfigManifest = JSON.parse(
          await next.readFile('.next/server/functions-config-manifest.json')
        )

res.json()
    expect(data).toEqual({ status: 'success', runtime: 'edge' })
  })

  it('should include preferredRegion in functions config manifest for nodejs runtime', async () => {
    if (isNextStart) {
      let functionsConf


rs'
import { Suspense } from 'react'
import { DebugRenderKind } from '../../../../shared'

export const unstable_instant = {
  // We're intentionally testing error behavior at runtime.
  // Build-time validation catches it and prevents that.
  unstable_disableValidation: true,
  unstable_samples: [{ cookies: [] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p id="intro">
        This page performs sync IO

the error in a runtime prefetch

      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchable />
      </Suspense>

  )
}

async function RuntimePrefetchable() {
  await cookies()
  retur

after a cookies() call, so we should only see


 from 'next/link'
import { useState } from 'react'

type PaginationConfig = {
  start: number
  end: number
}

export default function LinkCancellationPage() {
  const [areLinksVisible, setLinksVisibility] = useState(false)
  const [showMoreLinks, setShowMoreLinks] = useState(false)

  return (
    <>
      <p>
        This page is used to test that a prefetch scheduled when a Link enters
        the viewport is cancelled when the Link exits. The visibility toggle
        does not affect whether the links a

!areLinksVisible)}
        />
        {areLinksVisible ? 'Hide' : 'Show'} Links
      </label>
      <ul id="links-container" hidden={!areLinksVisible}>
        <Links start={1} end={7} />
        {showMoreLinks ? (
          <Links start={8} end={10} />

re mounted, only whether they are
        visible (using the `hidden` attribute).
      </p>
      <label>
        <input
          type="checkbox"
          checked={areLinksVisible}
          onChange={() => setLinksVisibility(


'react'
import { cachedDelay, DebugRenderKind, uncachedIO } from '../../../../shared'
import { connection } from 'next/server'

export const unstable_instant = {
  unstable_samples: [{ params: { id: 'test' } }],
}
export const unstable_prefetch = 'force-runtime'

type Params = { id: string }

export default async function Page({ params }: { params: Promise<Params> }) {
  return (
    <main>
      <DebugRenderKind />
      <p>
        This page uses params (passed to a private cache) and some uncached IO,

ync function RuntimePrefetchable({ params }: { params: Promise<Params> }) {
  const id = await privateCache(params)
  return (

{`Param: ${id}`}

      <Suspense

so parts of it should be runtime-prefetchable.

      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchable params={params} />
      </Suspense>

  )
}

as


pense } from 'react'
import { cachedDelay, DebugRenderKind, uncachedIO } from '../../../shared'
import { connection } from 'next/server'

export const unstable_instant = true
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (

      <DebugRenderKind />

        This page uses Date.now (in a private cache) and some uncached IO, so
        parts of it should be runtime-prefetchable.

      <Suspense fallback={<div style={{ color: 'g

dding: '1em' }}>

{`Timestamp: ${now}`}

      <Suspense fallback={
Loading 2...
}>
        <Dynamic />
      </Suspense>

  )
}

async function privateCache() {
  'use cache: priva

rey' }}>Loading 1...
}>
        <RuntimePrefetchable />
      </Suspense>

  )
}

async function RuntimePrefetchable() {
  const now = await privateCache()
  return (
    <div style={{ border: '1px solid blue', pa


next/headers'
import { Suspense } from 'react'
import { cachedDelay, DebugRenderKind, uncachedIO } from '../../../shared'
import { connection } from 'next/server'

export const unstable_instant = {
  unstable_samples: [{ cookies: [{ name: 'testCookie', value: 'testValue' }] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p>
        This page uses cookies (from inside a private cache) and some uncached

ormData: FormData) => {
          'use server'
          const cookieStore = await cookies()
          const cookieValue = formData.get('cookie') as string | null
          if (cookieValue) {
            cookieStore.set('testCookie', cookieValue)

IO, so parts of it should be runtime-prefetchable.

      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchable />
      </Suspense>
      <form
        action={async (f


next/headers'
import { Suspense } from 'react'
import { cachedDelay, DebugRenderKind, uncachedIO } from '../../../shared'
import { connection } from 'next/server'

export const unstable_instant = {
  unstable_samples: [{ headers: [['host', 'test-host']] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p>
        This page uses headers (from inside a private cache) and some uncached
        IO, so parts of it

const headerValue = await privateCache()
  return (

{`Header: ${headerValue}`}

      <Suspense fallback={
Loading 2...
}

should be runtime-prefetchable.

      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchable />
      </Suspense>

  )
}

async function RuntimePrefetchable() {


import { cookies } from 'next/headers'
import { Suspense } from 'react'
import { cachedDelay, DebugRenderKind } from '../../../shared'

export const unstable_instant = {
  unstable_samples: [{ cookies: [{ name: 'testCookie', value: 'testValue' }] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p>
        This page uses cookies and no uncached IO, So it should be completely
        prefetchable with a runtim

= await cookies()
  const cookieValue = cookieStore.get('testCookie')?.value ?? null
  await cachedDelay([__filename, cookieValue])
  return (

{`Cookie: ${cookieVal

e prefetch.

      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchable />
      </Suspense>

  )
}

async function RuntimePrefetchable() {
  const cookieStore


ders } from 'next/headers'
import { Suspense } from 'react'
import { cachedDelay, DebugRenderKind, uncachedIO } from '../../../shared'
import { connection } from 'next/server'

export const unstable_instant = {
  unstable_samples: [{ headers: [['host', 'test-host']] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p>
        This page uses headers and some uncached IO, so parts of it should be
        runtim

tore = await headers()
  const headerValue = headersStore.get('host') === null ? 'missing' : 'present'
  await cachedDelay([__filename, headerValue])
  return (

{`H

e-prefetchable.

      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchable />
      </Suspense>

  )
}

async function RuntimePrefetchable() {
  const headersS


kies } from 'next/headers'
import { Suspense } from 'react'
import { cachedDelay, DebugRenderKind } from '../../../shared'

export const unstable_instant = {
  unstable_samples: [{ cookies: [{ name: 'testCookie', value: 'testValue' }] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p>
        This page uses cookies (from a private cache) and no uncached IO, So it
        should be completely prefetchable wi

ookies() // Guard from being statically prerendered, which would make the cache hang

  // We've already awaited cookies, but we still want to make sure
  // that the cache doesn't consider them a hanging promise
  const cookieValue = await publicCache(

th a runtime prefetch.

      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchable />
      </Suspense>

  )
}

async function RuntimePrefetchable() {
  await c


'react'
import { cachedDelay, DebugRenderKind } from '../../../../shared'
import { connection } from 'next/server'
import { cookies } from 'next/headers'

export const unstable_instant = {
  unstable_samples: [{ params: { id: 'test' } }],
}
export const unstable_prefetch = 'force-runtime'

type Params = { id: string }

export default async function Page({ params }: { params: Promise<Params> }) {
  return (
    <main>
      <DebugRenderKind />
      <p>
        This page passes dynamic params to a public cac

arams={params} />
      </Suspense>
    </main>
  )
}

async function RuntimePrefetchable({ params }: { params: Promise<Params> }) {
  await cookies() // Guard from being statically prerendered, which would make the cache hang

  const id = await publicCac

he, and uses some
        uncached IO, so parts of it should be prefetchable with a runtime
        prefetch.

      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchable p


mport { Suspense } from 'react'
import { cachedDelay, DebugRenderKind } from '../../../shared'
import { cacheLife } from 'next/cache'

export const unstable_instant = true
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p id="intro">
        This page uses a short-lived private cache (with cacheLife("seconds")),
        which should not be included in a static prefetch, but should be
        included in a runtime

ense>
    </main>
  )
}

async function ShortLivedCache() {
  'use cache: private'
  cacheLife('seconds')
  await cachedDelay([__filename])

  return (
    <div style={{ border: '1px solid blue', padding: '1em' }}>
      Short-lived cached content
      <d

prefetch, because it has a long enough stale time
        (≥ RUNTIME_PREFETCH_DYNAMIC_STALE, 30s)

      <Suspense fallback={
Loading...
}>
        <ShortLivedCache />
      </Susp


 { Suspense } from 'react'
import { cachedDelay, DebugRenderKind } from '../../../shared'
import { cacheLife } from 'next/cache'

export const unstable_instant = true
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p id="intro">
        This page uses a short-lived public cache (expire < DYNAMIC_EXPIRE,
        5min), which should not be included in a static prefetch, but should be
        included in a runtim

pense>
    </main>
  )
}

async function ShortLivedCache() {
  'use cache'
  cacheLife({
    stale: 60, // > RUNTIME_PREFETCH_DYNAMIC_STALE
    revalidate: 2 * 60,
    expire: 3 * 60, // < DYNAMIC_EXPIRE
  })
  await cachedDelay([__filename])

  return (

e prefetch, because it has a long enough stale time
        (≥ RUNTIME_PREFETCH_DYNAMIC_STALE, 30s)

      <Suspense fallback={
Loading...
}>
        <ShortLivedCache />
      </Sus


ort { Suspense } from 'react'
import { cachedDelay, DebugRenderKind } from '../../../shared'
import { cacheLife } from 'next/cache'

export const unstable_instant = true
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p id="intro">
        This page uses a short-lived private cache (staleTime <
        RUNTIME_PREFETCH_DYNAMIC_STALE, which is 30s), which should not be
        included in a runtime prefetch

    stale: 5,
    // the rest of the settings don't matter for private caches,
    // because they are not persisted server-side
  })
  await cachedDelay([__filename])

  return (
    <div style={{ border: '1px solid blue', padding: '1em' }}>
      Short-l

      <Suspense fallback={
Loading...
}>
        <CachedButShortLived />
      </Suspense>

  )
}

async function CachedButShortLived() {
  'use cache: private'
  cacheLife({


 { cookies } from 'next/headers'
import { Suspense } from 'react'
import { cachedDelay, DebugRenderKind } from '../../../shared'
import { ErrorBoundary } from '../../../../components/error-boundary'

export const unstable_instant = {
  // We're intentionally testing error behavior at runtime.
  // Build-time validation catches it and prevents that.
  unstable_disableValidation: true,
  unstable_samples: [{ cookies: [{ name: 'user-agent', value: null }] }],
}
export const unstable_prefetch = 'force-runtime'

tion (and not during prerendering /
        prefetching)

      <Suspense fallback={
Loading 1...
}>
        <ErrorBoundary>
          <One />
        </ErrorBoundary>
      </Suspense>

  )
}

async

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p id="intro">
        This page errors after a cookies call, so we should only see the error
        in a runtime prefetch or a naviga


 } from '../../../../shared'

export const unstable_instant = {
  // We're intentionally testing error behavior at runtime.
  // Build-time validation catches it and prevents that.
  unstable_disableValidation: true,
  unstable_samples: [{ cookies: [] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p id="intro">
        This page performs sync IO after awaiting a private cache, so we should
        only see

uspense fallback={
Loading 1...
}>
        <RuntimePrefetchable />
      </Suspense>

  )
}

async function RuntimePrefetchable() {
  await privateCache()
  return
Timestamp: {Date.now()}</d

 the error in a runtime prefetch
      </p>
      <S


./../../../shared'

type Params = { id: string }

export const unstable_instant = {
  // We're intentionally testing error behavior at runtime.
  // Build-time validation catches it and prevents that.
  unstable_disableValidation: true,
  unstable_samples: [{ cookies: [] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page({ params }: { params: Promise<Params> }) {
  return (
    <main>
      <DebugRenderKind />
      <p id="intro">
        This page performs sync IO af

he error in a runtime prefetch

      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchable params={params} />
      </Suspense>

  )
}

async function RuntimePrefetchable({ params }: { pa

ter awaiting params, so we should only see
        t


ver', async () => {
    let act: ReturnType<typeof createRouterAct>
    const browser = await next.browser('/cancellation', {
      beforePageLoad(p: Playwright.Page) {
        act = createRouterAct(p)
      },
    })

    const checkbox = await browser.elementByCss('input[type="checkbox"]')
    await act(
      async () => {
        // Reveal the links to start prefetching, but block the responses from
        // reaching the client. This will initiate prefetches for the route
        // trees, but it won'

.
        const link2 = await browser.elementByCss('a[href="/cancellation/2"]')
        await link2.hover()

        // Hover over a different link to increase its relative priority.
        const link5 = await browser.elementByCss('a[href="/cancellation/5

t start prefetching any segment data yet until the
        // trees have loaded.
        await act(async () => {
          await checkbox.click()
        }, 'block')

        // Hover over a link to increase its relative priority


'react'
import { cachedDelay, DebugRenderKind, uncachedIO } from '../../../shared'
import { connection } from 'next/server'

export const unstable_instant = {
  unstable_samples: [{ searchParams: { searchParam: 'value' } }],
}
export const unstable_prefetch = 'force-runtime'

type AnySearchParams = { [key: string]: string | string[] | undefined }

export default async function Page({
  searchParams,
}: {
  searchParams: Promise<AnySearchParams>
}) {
  return (
    <main>
      <DebugRenderKind />
      <p>

>
        <RuntimePrefetchable searchParams={searchParams} />
      </Suspense>
    </main>
  )
}

async function RuntimePrefetchable({
  searchParams,
}: {
  searchParams: Promise<AnySearchParams>
}) {
  const searchParam = await privateCache(searchParams

This page uses search params (passed to a private cache) and some
        uncached IO, so parts of it should be runtime-prefetchable.

      <Suspense fallback={
Loading 1...
}


 { cookies } from 'next/headers'
import { Suspense } from 'react'
import { cachedDelay, DebugRenderKind } from '../../../shared'

export const unstable_instant = {
  unstable_samples: [{ cookies: [{ name: 'testCookie', value: 'testValue' }] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p>
        This page uses cookies (from a private cache) and no uncached IO, So it
        should be completely prefetcha

onst cookieValue = await privateCache()
  return (

{`Cookie: ${cookieValue}`}

  )
}

async function privateCache() {
  'use cache: private'
  const

ble with a runtime prefetch.

      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchable />
      </Suspense>

  )
}

async function RuntimePrefetchable() {
  c


next/headers'
import { Suspense } from 'react'
import { cachedDelay, DebugRenderKind, uncachedIO } from '../../../shared'
import { connection } from 'next/server'

export const unstable_instant = {
  unstable_samples: [{ cookies: [{ name: 'testCookie', value: 'testValue' }] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p>
        This page uses cookies and some uncached IO, so parts of it should be

    'use server'
          const cookieStore = await cookies()
          const cookieValue = formData.get('cookie') as string | null
          if (cookieValue) {
            cookieStore.set('testCookie', cookieValue)
          }
        }}
      >

runtime-prefetchable.

      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchable />
      </Suspense>
      <form
        action={async (formData: FormData) => {


'react'
import { cachedDelay, DebugRenderKind } from '../../../shared'
import { connection } from 'next/server'
import { cookies } from 'next/headers'

export const unstable_instant = {
  unstable_samples: [{ searchParams: { searchParam: 'value' } }],
}
export const unstable_prefetch = 'force-runtime'

type AnySearchParams = { [key: string]: string | string[] | undefined }

export default async function Page({
  searchParams,
}: {
  searchParams: Promise<AnySearchParams>
}) {
  return (
    <main>
      <De

e={{ color: 'grey' }}>Loading 1...</div>}>
        <RuntimePrefetchable searchParams={searchParams} />
      </Suspense>
    </main>
  )
}

async function RuntimePrefetchable({
  searchParams,
}: {
  searchParams: Promise<AnySearchParams>
}) {
  await cook

bugRenderKind />
      <p>
        This page passes search params to a public cache, and uses some uncached
        IO, so parts of it should be prefetchable with a runtime prefetch.
      </p>
      <Suspense fallback={<div styl


mport { Suspense } from 'react'
import { cachedDelay, DebugRenderKind } from '../../../shared'
import { cacheLife } from 'next/cache'

export const unstable_instant = true
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p id="intro">
        This page uses a short-lived public cache (with cacheLife("seconds")),
        which should not be included in a static prefetch, but should be
        included in a runtime

nse>

  )
}

async function ShortLivedCache() {
  'use cache'
  cacheLife('seconds')
  await cachedDelay([__filename])

  return (

      Short-lived cached content
      <div id="cac

prefetch, because it has a long enough stale time
        (≥ RUNTIME_PREFETCH_DYNAMIC_STALE, 30s)

      <Suspense fallback={
Loading...
}>
        <ShortLivedCache />
      </Suspe


ort { DebugLinkAccordion } from '../../../components/link-accordion'

export default async function Page() {
  return (

Errors

thrown errors

          <DebugLinkAccordion href="/errors/error-after-cookies" />

sync IO

          <DebugLinkAccordion href="/errors/sync-io-after-runtime-api/cookies" />

          <DebugLinkAccordion href="/errors/sync-io-af

ter-runtime-api/search-params?foo=bar" />

          <DebugLinkAccordion href="/errors/sync-io-after-runtime-api/private-cache" />

          <DebugLinkAccordion href="/errors/sync-io-after-runtime-api/qu

ter-runtime-api/headers" />

          <DebugLinkAccordion href="/errors/sync-io-after-runtime-api/dynamic-params/123" />

          <DebugLinkAccordion href="/errors/sync-io-af


ort { Suspense } from 'react'
import { DebugRenderKind } from '../../../../shared'

type AnySearchParams = { [key: string]: string | string[] | undefined }

export const unstable_instant = {
  // We're intentionally testing error behavior at runtime.
  // Build-time validation catches it and prevents that.
  unstable_disableValidation: true,
  unstable_samples: [{ cookies: [] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page({
  searchParams,
}: {
  searchParams: Pro

/p>
      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchable searchParams={searchParams} />
      </Suspense>

  )
}

async function RuntimePrefetchable({
  searchParams,
}: {
  searchParams: Pro

mise<AnySearchParams>
}) {
  return (
    <main>
      <DebugRenderKind />
      <p id="intro">
        This page performs sync IO after awaiting searchParams, so we should
        only see the error in a runtime prefetch
      <


pense } from 'react'
import { cachedDelay, DebugRenderKind, uncachedIO } from '../../../../shared'
import { connection } from 'next/server'

export const unstable_instant = {
  unstable_samples: [{ params: { id: 'test' } }],
}
export const unstable_prefetch = 'force-runtime'

type Params = { id: string }

export default async function Page({ params }: { params: Promise<Params> }) {
  return (
    <main>
      <DebugRenderKind />
      <p>
        This page uses params and some uncached IO, so parts of it sh

ntimePrefetchable({ params }: { params: Promise<Params> }) {
  const { id } = await params
  await cachedDelay([__filename, id])
  return (

{`Param: ${id}`}

ould be
        runtime-prefetchable.

      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchable params={params} />
      </Suspense>

  )
}

async function Ru


pense } from 'react'
import { cachedDelay, DebugRenderKind } from '../../../shared'
import { connection } from 'next/server'

export const unstable_instant = {
  unstable_samples: [{ cookies: [{ name: 'testCookie', value: 'testValue' }] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p>
        This page passes cookies to a public cache, and uses some uncached IO,
        so parts of it should be prefetchab

        'use server'
          const cookieStore = await cookies()
          const cookieValue = formData.get('cookie') as string | null
          if (cookieValue) {
            cookieStore.set('testCookie', cookieValue)
          }
        }}
      >

le with a runtime prefetch.

      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchable />
      </Suspense>
      <form
        action={async (formData: FormData) => {


 { Suspense } from 'react'
import { cachedDelay, DebugRenderKind } from '../../../shared'
import { cacheLife } from 'next/cache'

export const unstable_instant = true
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p id="intro">
        This page uses a short-lived public cache (expire < DYNAMIC_EXPIRE,
        5min), which should not be included in a static prefetch, and should
        also not be included in

     </Suspense>
    </main>
  )
}

async function ShortLivedCache() {
  'use cache'
  cacheLife({
    stale: 20, // < RUNTIME_PREFETCH_DYNAMIC_STALE
    revalidate: 2 * 60,
    expire: 3 * 60, // < DYNAMIC_EXPIRE
  })
  await cachedDelay([__filename])

a runtime prefetch, because it has a short
        enough stale time (< RUNTIME_PREFETCH_DYNAMIC_STALE, 30s)

      <Suspense fallback={
Loading...
}>
        <ShortLivedCache />


rs'
import { Suspense } from 'react'
import { DebugRenderKind } from '../../../../shared'

export const unstable_instant = {
  // We're intentionally testing error behavior at runtime.
  // Build-time validation catches it and prevents that.
  unstable_disableValidation: true,
  unstable_samples: [{ cookies: [] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p id="intro">
        This page performs sync IO

the error in a runtime prefetch

      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchable />
      </Suspense>

  )
}

async function RuntimePrefetchable() {
  await headers()
  retur

after a headers() call, so we should only see


next/headers'
import { Suspense } from 'react'
import { cachedDelay, DebugRenderKind } from '../../../shared'
import { connection } from 'next/server'

export const unstable_instant = {
  unstable_samples: [{ headers: [['host', 'test-host']] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p>
        This page passes headers to a public cache, and uses some uncached IO,
        so parts of it should be prefe

  await headers() // Guard from being statically prerendered, which would make the cache hang

  // We've already awaited headers, but we still want to make sure
  // that the cache doesn't consider them a hanging promise
  const headerValue = await publi

tchable with a runtime prefetch.

      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchable />
      </Suspense>

  )
}

async function RuntimePrefetchable() {


le searchParams={searchParams} />
      </Suspense>
    </main>
  )
}

async function RuntimePrefetchable({
  searchParams,
}: {
  searchParams: Promise<AnySearchParams>
}) {
  const { searchParam } = await searchParams
  await cachedDelay([__filename, sea

This page uses search params and some uncached IO, so parts of it should
        be runtime-prefetchable.

      <Suspense fallback={
Loading 1...
}>
        <RuntimePrefetchab


mport { Suspense } from 'react'
import { cachedDelay, DebugRenderKind } from '../../../../shared'
import { cacheLife } from 'next/cache'

export const unstable_instant = {
  // We're intentionally testing error behavior at runtime.
  // Build-time validation catches it and prevents that.
  unstable_disableValidation: true,
  unstable_samples: [{ cookies: [] }],
}
export const unstable_prefetch = 'force-runtime'

export default async function Page() {
  return (
    <main>
      <DebugRenderKind />
      <p

ing 1...
}>
        <RuntimePrefetchable />
      </Suspense>

  )
}

async function RuntimePrefetchable() {
  await publicCache()
  return
Timestamp: {Date.now()}

}

async function publicCache() {
  'use cache'

id="intro">
        This page performs sync IO after awaiting a quickly-expiring public
        cache, so we should only see the error in a runtime prefetch
      </p>
      <Suspense fallback={<div style={{ color: 'grey' }}>Load


 {import('next').NextConfig}
 */
const nextConfig = {
  turbopack: {
    rules: {
      '*': [
        {
          // Exact match for text/javascript content type
          condition: { contentType: 'text/javascript' },
          loaders: [require.resolve('./js-loader.js')],
          as: '*.js',
        },
        {
          // Glob pattern match for text content types
          // Should not be applied to text/javascript due to the order of rules
          condition: { contentType: 'text/*' },

image-loader.js')],
          as: '*.js',
        },
      ],
    },
  },
  webpack: (config) => {
    config.module.rules.push(
      {
        mimetype: 'text/javascript',
        use: [{ loader: require.resolve('./js-loader.js') }],
        type: 'javas

loaders: [require.resolve('./text-loader.js')],
          as: '*.js',
        },
        {
          // Regex match for image content types
          condition: { contentType: /^image\// },
          loaders: [require.resolve('./


pense } from 'react'
import { cacheLife, cacheTag, revalidatePath, updateTag } from 'next/cache'
import { redirect } from 'next/navigation'
import { connection } from 'next/server'
import React from 'react'

async function getData() {
  'use cache'

  cacheLife({ revalidate: 6 })
  cacheTag('modern')

  return new Date().toISOString()
}

async function AsyncComp() {
  let data = await getData()

  return
{data}

}

export default async function Home() {
  await connection()

  return (
    <

teTag('modern')
          }}
        >
          Revalidate Tag
        </button>{' '}
        <button
          id="revalidate-path"
          formAction={async () => {
            'use server'

            revalidatePath('/')
          }}
        >

main>
      <Suspense fallback={
Loading...
}>
        <AsyncComp />
      </Suspense>
      <form>
        <button
          id="revalidate-tag"
          formAction={async () => {
            'use server'

            upda


/* eslint-env jest */
import path from 'path'
import { nextTestSetup, FileRef } from 'e2e-utils'

describe('app dir - with proxy in src dir', () => {
  const { next } = nextTestSetup({
    files: {
      'src/app': new FileRef(path.join(__dirname, 'app')),
      'next.config.js': new FileRef(path.join(__dirname, 'next.config.js')),
      'src/proxy.js': `
      import { NextResponse } from 'next/server'
      import { cookies } from 'next/headers'

      export async function proxy(request) {
        const

')
    await browser.addCookie({
      name: 'test-cookie',
      value: 'test-cookie-response',
    })
    await browser.refresh()

    const html = await browser.eval('document.documentElement.innerHTML')

    expect(html).toContain('test-cookie-response

cookie = (await cookies()).get('test-cookie')
        return NextResponse.json({ cookie })
      }
    `,
    },
  })

  it('works without crashing when using RequestStore', async () => {
    const browser = await next.browser('/


t.browser('/')
      expect(next.cliOutput).toMatch(
        /GET \/ 200 in .* \(next\.js:.*, proxy\.ts:.*, application-code:.*\)/
      )
    })
  }

  it('should filter correctly after proxy rewrite', async () => {
    const browser = await next.browser('/start')

    await browser.eval('window.beforeNav = 1')
    await browser.eval('window.next.router.push("/rewrite-to-app")')

    await check(async () => {
      return browser.eval('document.documentElement.innerHTML')
    }, /app-dir/)
  })

  describe

oJson: (res: Response) => res.json(),
    },
    {
      title: 'next/headers',
      path: '/headers',
      toJson: async (res: Response) => {
        const $ = cheerio.load(await res.text())
        return JSON.parse($('#headers').text())
      },
    }

.each([
    {
      title: 'Serverless Functions',
      path: '/api/dump-headers-serverless',
      toJson: (res: Response) => res.json(),
    },
    {
      title: 'Edge Functions',
      path: '/api/dump-headers-edge',
      t


{ unstable_cache } from 'next/cache'
import { headers as nextHeaders } from 'next/headers'

const getCachedValue = unstable_cache(
  async () => Math.random().toString(),
  ['proxy-cache-probe']
)

/**
 * @param {import('next/server').NextRequest} request
 */
export async function proxy(request) {
  const headersFromRequest = new Headers(request.headers)
  // It should be able to import and use `headers` inside proxy
  const headersFromNext = await nextHeaders()
  headersFromRequest.set('x-from-proxy', 'hel

 ) {
    throw new Error('Expected headers from client to match')
  }

  // Cannot set draftMode in nodejs runtime
  // TODO: Investigate https://github.com/vercel/next.js/pull/85174
  // if (request.nextUrl.searchParams.get('draft')) {
  //   ;(await draf

lo-from-proxy')

  // make sure headers() from `next/headers` is behaving properly
  if (
    headersFromRequest.get('x-from-client') &&
    headersFromNext.get('x-from-client') !==
      headersFromRequest.get('x-from-client')


mport { nextTestSetup } from 'e2e-utils'
import { retry } from 'next-test-utils'

describe('instrumentation-order', () => {
  const { next } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
  })

  it('should work', async () => {
    await next.fetch('/')

    await retry(async () => {
      // `next.cliOutput` includes both `next build` and `next start` in the production test run
      // Because of that we have to split the output by `Ready in` and get the second part only
      const ser

on:register:timeout',
        'instrumentation:register:end',
        'global-side-effect:app-router-page',
      ]
      const searchedLines = cliOutputLines.filter((line) =>
        ORDERED_LOGS.includes(line.trim())
      )

      expect(searchedLines).

verLog = next.cliOutput.split('Ready in')[1]
      const cliOutputLines = serverLog.split('\n')

      const ORDERED_LOGS = [
        'instrumentation:side-effect',
        'instrumentation:register:begin',
        'instrumentati


Setup } from 'e2e-utils'

describe('next-config-ts-type-error-cjs', () => {
  // TODO: Remove this once we bump minimum Node.js version to v22
  if (!(process.features as any).typescript) {
    it.skip('requires `process.features.typescript` to feature detect Node.js native TS', () => {})
    return
  }

  const { next, isNextDev, skipped } = nextTestSetup({
    files: __dirname,
    skipStart: true,
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  it('should throw with type error on build

ait next.start()
      const $ = await next.render$('/')
      expect($('p').text()).toBe('foo')
    } else {
      const { cliOutput } = await next.build()
      await expect(cliOutput).toContain(
        `Type 'string' is not assignable to type 'number'.

 (CJS)', async () => {
    if (isNextDev) {
      aw


utils'

describe('next-config-ts-type-error-esm', () => {
  // TODO: Remove this once we bump minimum Node.js version to v22
  if (!(process.features as any).typescript) {
    it.skip('requires `process.features.typescript` to feature detect Node.js native TS', () => {})
    return
  }

  const { next, isNextDev, skipped } = nextTestSetup({
    files: __dirname,
    skipStart: true,
    skipDeployment: true,
    packageJson: {
      type: 'module',
    },
  })

  if (skipped) {
    return
  }

  it('should

    if (isNextDev) {
      await next.start()
      const $ = await next.render$('/')
      expect($('p').text()).toBe('foo')
    } else {
      const { cliOutput } = await next.build()
      await expect(cliOutput).toContain(
        `Type 'string' is no

throw with type error on build (ESM)', async () => {


import { nextTestSetup } from 'e2e-utils'

describe('next-config-ts-import-js-extensions-esm', () => {
  // TODO: Remove this once we bump minimum Node.js version to v22
  if (!(process.features as any).typescript) {
    it.skip('requires `process.features.typescript` to feature detect Node.js native TS', () => {})
    return
  }

  const { next } = nextTestSetup({
    files: __dirname,
    packageJson: {
      type: 'module',
    },
  })

  it('should import js extensions (ESM)', async () => {
    const $

ender$('/')
    const text = $('p').text()
    expect(text).toContain('jsESM')
    expect(text).toContain('cjs')
    expect(text).toContain('mjs')
    expect(text).toContain('cts')
    expect(text).toContain('mts')
    expect(text).toContain('ts')
  })
})


 this inside of retry in case button event handler
      // isn't ready yet
      await browser.elementById('increment-button-1').click()

      const counterDisplay1 = await browser.elementById('counter-display-1')
      expect(await counterDisplay1.text()).toBe('Count: 1')
    })
    await browser.elementById('increment-button-1').click()

    const counterDisplay1 = await browser.elementById('counter-display-1')
    expect(await counterDisplay1.text()).toBe('Count: 2')

    // Navigate to page 2. Accumul

2 = await browser.elementById('counter-display-2')
    await incrementButton2.click()
    await incrementButton2.click()
    await incrementButton2.click()
    await incrementButton2.click()
    await incrementButton2.click()
    await incrementButton2.cli

ate some state here, too.
    const linkToPage2 = await browser.elementByCss('a[href="/page/2"]')
    await linkToPage2.click()
    const incrementButton2 = await browser.elementById('increment-button-2')
    const counterDisplay


These tests
 * use the experimental.exposeTestingApiInProductionBuild flag to enable the
 * API in production mode for testing purposes.
 */

import { NextInstance, nextTestSetup } from 'e2e-utils'
import { instant } from '@next/playwright'
import type * as Playwright from 'playwright'
import { join } from 'node:path'

/**
 * Opens a browser and returns the underlying Playwright Page instance.
 *
 * We use this pattern so our test assertions look as close as possible to
 * what users would write with the ac

NextInstance,
  url: string,
  options?: { cookies?: Array<{ name: string; value: string }> }
): Promise<Playwright.Page> {
  let page: Playwright.Page
  await next.browser(url, {
    beforePageLoad(p) {
      page = p
      if (options?.cookies) {

tual Playwright helper package. The
 * Next.js test infra wraps Playwright with its own BrowserInterface, but
 * the Instant Navigation Testing API is designed to work with native Playwright.
 */
async function openPage(
  next:


on HomePage() {
  return (

Instant Navigation API Test

      <Link href="/target-page" id="link-to-target">
        Go to target page
      </Link>
      <Link
        href="/runtime-prefetch-target?myParam=testValue"
        id="link-to-runtime-prefetch"
      >
        Go to runtime prefetch target
      </Link>
      <Link
        href="/full-prefetch-target"
        prefetch={true}
        id="link-to-full-prefetch"
      >
        Go to full prefetch ta

   </Link>
      <Link href="/dynamic-params/hello" id="link-to-static-dynamic-params">
        Go to static dynamic params page
      </Link>
      <Link href="/ungenerated-params/anything" id="link-to-ungenerated-params">
        Go to ungenerated params

rget
      </Link>
      <Link href="/cookies-page" id="link-to-cookies-page">
        Go to cookies page
      </Link>
      <Link href="/dynamic-params/unknown" id="link-to-dynamic-params">
        Go to dynamic params page


t { Suspense } from 'react'

type SearchParams = { [key: string]: string | string[] | undefined }

export default function SearchParamsPage({
  searchParams,
}: {
  searchParams: Promise<SearchParams>
}) {
  return (

Search Params Page

      <Suspense
        fallback={

            Loading search params...

        }
      >
        <SearchParamContent searchParams={searchParams} /

ense>
    </div>
  )
}

async function SearchParamContent({
  searchParams,
}: {
  searchParams: Promise<SearchParams>
}) {
  const params = await searchParams
  const foo = params.foo

  return <div data-testid="search-param-content">foo: {foo ?? 'not set


{ Suspense } from 'react'
import { connection } from 'next/server'

export const unstable_instant = {
  unstable_samples: [{ searchParams: { myParam: 'testValue' } }],
}
export const unstable_prefetch = 'force-runtime'

type SearchParams = { [key: string]: string | string[] | undefined }

export default async function RuntimePrefetchTargetPage({
  searchParams,
}: {
  searchParams: Promise<SearchParams>
}) {
  return (

Runtime Prefetch Target

      <Suspense fallback={<div data-tes

/div>
        }
      >
        <DynamicContent />
      </Suspense>
    </div>
  )
}

async function RuntimePrefetchableContent({
  searchParams,
}: {
  searchParams: Promise<SearchParams>
}) {
  const params = await searchParams
  const myParam = params.

tid="outer-loading">Loading...
}>
        <RuntimePrefetchableContent searchParams={searchParams} />
      </Suspense>
      <Suspense
        fallback={

Loading dynamic content...<


import { Suspense } from 'react'

// Intentionally no generateStaticParams — this exercises the fallback-shell
// path for a dynamic route whose URL is not covered by static params.
export default function UngeneratedParamsPage({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  return (

Ungenerated Params Page

      <Suspense
        fallback={

Loading params...

        }

<ParamContent params={params} />
      </Suspense>

  )
}

async function ParamContent({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params

  return
slug: {slug}

}


 { Suspense } from 'react'

// Same shape as `ungenerated-params/[slug]` (no `generateStaticParams`), but
// this route opts into runtime prefetching. The prefetch therefore includes
// the resolved `slug`, so the param should be visible inside the instant
// scope instead of suspending.
export const unstable_instant: {
  unstable_samples: Array<{ params: { slug: string } }>
} = {
  unstable_samples: [{ params: { slug: 'anything' } }],
}
export const unstable_prefetch = 'force-runtime'

export default funct

Suspense
        fallback={
          <div data-testid="ungenerated-params-runtime-fallback">
            Loading params...
          </div>
        }
      >
        <ParamContent params={params} />
      </Suspense>
    </div>
  )
}

async function Param

ion UngeneratedParamsRuntimePage({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  return (

        Ungenerated Params Runtime Page

      <


nst hasAudienceHome = async () => {
          await check(
            () => browser.waitForElementByCss('#audience-home').text(),
            'Audience home'
          )
        }
        const hasDemographics = async () => {
          await check(
            () => browser.waitForElementByCss('#demographics').text(),
            'Demographics'
          )
        }
        const hasSubscribers = async () => {
          await check(
            () => browser.waitForElementByCss('#subscribers').text(),

}`
          )
        }

        // Initial page
        const step1 = async () => {
          await hasHome()
          await hasViewsHome()
          await hasAudienceHome()
          await checkUrlPath('')
        }

        await step1()

        cons

        'Subscribers'
          )
        }
        const checkUrlPath = async (path: string) => {
          await check(
            () => browser.url(),
            `${next.url}/parallel-tab-bar${path}${trailingSlash ? '/' : ''


k from 'next/link'

export default function Layout({ children, modal }) {
  return (

intercepting-siblings

        {children}

{modal}

links

          <Link href="/intercepting-siblings">/intercepting-siblings</Link>

          <Link href="/intercepting-sibl

cepting-siblings/1</Link>

          <Link href="/intercepting-siblings/2">/intercepting-siblings/2</Link>

          <Link href="/intercepting-siblings/3">/intercepting-siblings/3</Link>


Link from 'next/link'

function AudienceNav() {
  return (

        <Link id="home-link-audience" href="/parallel-tab-bar">
          Home
        </Link>

        <Link id="demographics-link" href="/parallel-tab-bar/demographics">
          Demographics
        </Link>

        <Link id="subscribers-link" href="/parallel-tab-bar/subscribers">
          Subscribers
        </Link>

  )
}

function ViewsNav() {
  return (

        </Link>
      </li>
      <li>
        <Link id="view-duration-link" href="/parallel-tab-bar/view-duration">
          View Duration
        </Link>
      </li>
    </ul>
  )
}
export default function Layout({ children, audience, views }) {
  retur

        <Link id="home-link-views" href="/parallel-tab-bar">
          Home
        </Link>

        <Link id="impressions-link" href="/parallel-tab-bar/impressions">
          Impressions


te (e.g., /groups/123) to a deeper route
    // (e.g., /groups/123/new) should trigger the modal interception.
    //
    // The bug was that the regex pattern used [^/]+ which only matched single segments,
    // so interception failed when the source route had multiple segments like /groups/123
    const browser = await next.browser('/groups/123')

    // Verify we're on the group page
    await retry(async () => {
      const text = await browser.elementByCss('body').text()
      expect(text).toContain('

(async () => {
      const modalText = await browser.elementById('modal').text()
      expect(modalText).toContain('Modal: New item for group 123')
    })

    // The children should still show the group page
    await retry(async () => {
      const child

Group 123')
      expect(text).toContain('New Item')
    })

    // Navigate from /groups/123 to /groups/123/new
    // This should trigger the modal interception
    await browser.elementById('new-link').click()

    await retry


stDataServer } from 'test-data-service/writer'
import { createTestLog } from 'test-log'

describe('avoid-popstate-flash', () => {
  if ((global as any).isNextDev || (global as any).isNextDeploy) {
    // this is skipped in dev because PPR is not enabled in dev
    // and in deploy we can't rely on this test data service existing
    test('should skip dev & deploy', () => {})
    return
  }

  const { next } = nextTestSetup({
    files: __dirname,
    skipStart: true,
  })

  let server
  afterEach(() => {

  server = createTestDataServer(async (key, res) => {
      TestLog.log('REQUEST: ' + key)
      if (autoresolveRequests) {
        res.resolve()
        return
      }
      if (pendingRequests.has(key)) {
        throw new Error('Request already pending

   server?.close()
  })

  test('does not flash back to partial PPR data during back/forward navigation', async () => {
    const TestLog = createTestLog()
    let autoresolveRequests = true
    let pendingRequests = new Map()


er-only'

import { unstable_noStore } from 'next/cache'

// NOTE: I've intentionally not yet moved these helpers into a shared module, to
// avoid early abstraction. I will if/when we start using them for other tests.
// They are based on the testing patterns we use all over the React codebase, so
// I'm reasonably confident in them.
const TEST_DATA_SERVICE_URL = process.env.TEST_DATA_SERVICE_URL
const ARTIFICIAL_DELAY = 3000

async function getTestData(key: string, isStatic: boolean): Promise<string> {
  c

inning up a
    // data server.
    await new Promise<void>((resolve) =>
      setTimeout(() => resolve(), ARTIFICIAL_DELAY)
    )
    if (!isStatic) {
      unstable_noStore()
    }
    return key
  }
  const response = await fetch(
    TEST_DATA_SERVICE_

onst searchParams = new URLSearchParams({
    key,
  })
  if (!TEST_DATA_SERVICE_URL) {
    // If environment variable is not set, resolve automatically after a delay.
    // This is so you can run the test app locally without sp


lient'

import { Component, createContext, use, useState } from 'react'

const ShouldFallbackThrowContext = createContext(false)

export function ShouldFallbackThrowContainer({ children }) {
  const [shouldFallbackThrow, setShouldFallbackThrow] = useState(false)
  return (
    <>
      <label>
        Throw if fallback appears
        <input
          id="should-fallback-throw"
          type="checkbox"
          checked={shouldFallbackThrow}
          onChange={(e) => setShouldFallbackThrow(e.target.checke

allback({ children }) {
  if (use(ShouldFallbackThrowContext)) {
    throw new Error('Unexpected fallback')
  }
  return children
}

class ErrorBoundary extends Component<{ children: React.ReactNode }> {
  state = { error: null }
  static getDerivedStateFr

d)}
        />
      </label>
      <ShouldFallbackThrowContext.Provider value={shouldFallbackThrow}>
        <ErrorBoundary>{children}</ErrorBoundary>
      </ShouldFallbackThrowContext.Provider>
    </>
  )
}

export function F


ribe.skip('search-params', () => {
  if ((global as any).isNextDev) {
    test('ppr is disabled in dev', () => {})
    return
  }

  const { next } = nextTestSetup({
    files: __dirname,
  })

  test(
    'updates page data during a nav even if no shared layouts have changed ' +
      '(e.g. updating a search param on the current page)',
    async () => {
      const browser = await next.browser('/')

      // Click a link that updates the current page's search params.
      const link = await browser.elem

firm that the page re-rendered with the new search params.
      const searchParamsContainer = await browser.elementById('search-params')
      expect(await searchParamsContainer.innerText()).toBe(
        'Search params: {"blazing":"good"}'
      )
    }

entByCss('a')
      await link.click()

      // Con


NAR-423): Migrate to Cache Components.
describe.skip('prefetch-navigation', () => {
  const { next, isNextDev } = nextTestSetup({
    files: __dirname,
  })

  if (isNextDev) {
    it('is skipped in dev because there are no prefetches', () => {})
    return
  }

  it('should render the prefetch without waiting for the RSC request', async () => {
    const rscRequestPromise = new Map<
      string,
      { resolve: () => Promise<void> }
    >()
    const browser = await next.browser('/catch-all/1', {
      b

const pathname = url.pathname

          if (headers['rsc'] === '1' && !headers['next-router-prefetch']) {
            // Create a promise that will be resolved by the later test code
            let resolvePromise: () => void
            const promise = n

eforePageLoad(page) {
        page.route('**/catch-all/**', async (route) => {
          const request = route.request()
          const headers = await request.allHeaders()
          const url = new URL(request.url())


stDataServer } from 'test-data-service/writer'
import { createTestLog } from 'test-log'

describe('stale-prefetch-entry', () => {
  if ((global as any).isNextDev || (global as any).isNextDeploy) {
    // this is skipped in dev because PPR is not enabled in dev
    // and in deploy we can't rely on this test data service existing
    test('should skip dev & deploy', () => {})
    return
  }

  const { next } = nextTestSetup({
    files: __dirname,
    skipStart: true,
  })

  let server
  afterEach(() => {

't contain dynamic holes. This
  // prevented the dynamic data from ever streaming in.
  test(
    'works if a prefetched route entry has become stale (too much ' +
      'time has elapsed since it was prefetched)',
    async () => {
      const TestLog =

   server?.close()
  })

  // This is a regression test where a condition that checked whether a cached
  // route entry was stale accidentally caused the router to treat prefetched
  // data as if it were complete data that didn


hit a separate lambda instance that won't share the same reference
  if (!isNextDeploy) {
    it('should submit the action and revalidate the page data', async () => {
      const browser = await next.browser('/')
      await check(() => browser.hasElementByCssSelector('#create-entry'), false)

      // there shouldn't be any data yet
      expect((await browser.elementsByCss('#entries li')).length).toBe(0)

      await browser.elementByCss("[href='/revalidate-modal']").click()

      await check(() => brow

xpect((await browser.elementsByCss('#entries li')).length).toBe(1)
      })

      await browser.elementById('create-entry').click()

      // we created an entry and called revalidate, so we should have 2 entries
      await retry(async () => {
        ex

ser.hasElementByCssSelector('#create-entry'), true)

      await browser.elementById('create-entry').click()

      // we created an entry and called revalidate, so we should have 1 entry
      await retry(async () => {
        e


ync function Home() {
  const data = await getData()
  const randomNumber = await fetch(
    'https://next-data-api-endpoint.vercel.app/api/random'
  ).then((res) => res.text())

  return (

      <Link href="/revalidate-modal">Open Revalidate Modal</Link>
      <Link href="/refresh-modal">Open Refresh Modal</Link>
      <Link href="/redirect-modal">Open Redirect Modal</Link>
      <Link href="/detail-page">Intercepted Detail Page</Link>

{randomNumber}</

id="clear-entries">Clear Entries</button>
      </form>

Current Data

          {data.map((item, index) => (

{item}

          ))}

div>
      <form action={clearData}>
        <button


use client'
import { useRouter } from 'next/navigation'
import { revalidateAction } from './action'

export default function Page() {
  const router = useRouter()

  const handleRevalidateSubmit = async () => {
    const result = await revalidateAction()
    if (result.success) {
      close()
    }
  }

  const close = () => {
    router.back()
  }

  return (

      <div className="flex justify-bet

       </button>
      </div>
      <form action={handleRevalidateSubmit}>
        <button
          type="submit"
          className="bg-sky-600 text-white p-2 rounded"
          id="modal-submit-button"
        >
          Revalidate Submit
        </bu

ween">

Modal

        <button
          type="button"
          id="modal-close-button"
          onClick={() => close()}
          className="bg-gray-100 border p-2 rounded"
        >
          close


import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { revalidateAction } from '../../@modal/modal/action'

export default function Page() {
  const router = useRouter()

  const handleRevalidateSubmit = async () => {
    const result = await revalidateAction()
    if (result.success) {
      close()
    }
  }

  const close = () => {
    router.back()
  }

  return (

      <h2 id="drawe

se
      </button>

Drawer

        <Link
          href="/nested-revalidate/modal"
          className="bg-sky-600 text-white p-2 rounded"
        >
          Open modal

r">Drawer

{Date.now()}

      <button
        type="button"
        id="drawer-close-button"
        onClick={() => close()}
        className="bg-gray-100 border p-2 rounded"
      >
        clo


utton } from '../../../../components/RefreshButton'
import { RevalidateButton } from '../../../../components/RevalidateButton'
import { UpdateSearchParamsButton } from '../../../../components/UpdateSearchParamsButton'

const getRandom = async () => Math.random()

export default async function Page(props) {
  const searchParams = await props.searchParams
  const params = await props.params
  const someProp = await getRandom()

  return (
    <dialog open>

{params.dynamic}

      <div style={{

          Modal Page
          {someProp}

        <RefreshButton />
        <RevalidateButton />
        <UpdateSearchParamsButton searchParams={searchParams} id="modal" />

display: 'flex', flexDirection: 'column' }}>


tTestSetup } from 'e2e-utils'

// TODO-APP: fix test as it's failing randomly
describe.skip('app-dir back button download bug', () => {
  describe('app-dir back button download bug', () => {
    const { next, skipped } = nextTestSetup({
      files: __dirname,
      skipDeployment: true,
    })

    if (skipped) {
      return
    }

    it('should redirect route when clicking link', async () => {
      const browser = await next.browser('/')
      const text = await browser
        .elementByCss('#to-post-

lick()
        .waitForElementByCss('#post-page')
        .text()
      expect(text).toBe('This is the post page')

      await browser.back()

      expect(await browser.waitForElementByCss('#home-page').text()).toBe(
        'Home!'
      )
    })
  })
}


from 'e2e-utils'
import { check } from 'next-test-utils'

describe('route-page-manifest-bug', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  // Recommended for tests that check HTML. Cheerio is a HTML parser that has a jQuery like API.
  it('should work when requesting route handler after page', async () => {
    const browser = await next.browser('/')
    expect(await browser.elementByCss('#page-title').text()).toBe(
      'Page that would break'
    )
    await browser.eval('wind

ody.textContent'),
      '{"url":"https://www.example.com"}'
    )
    await browser.refresh()
    await check(
      () => browser.eval('document.body.textContent'),
      '{"url":"https://www.example.com"}'
    )
    await browser.refresh()
    await che

ow.location.href = "/abc"')
    await check(
      () => browser.eval('document.body.textContent'),
      '{"url":"https://www.example.com"}'
    )
    await browser.refresh()
    await check(
      () => browser.eval('document.b


ignore
import { ImageResponse as ImageResponse2 } from '@vercel/og'

// Edge: Using @vercel/og external package, and should be aliased to "next/server" ImageResponse
// @ts-ignore
if (ImageResponse2.displayName !== ImageResponse.displayName)
  // @ts-ignore
  throw new Error('ImageResponse2 mismatch: ' + ImageResponse2.displayName)

export const alt = 'Twitter'
export const size = { width: 1600, height: 900 }

export default function twitter() {
  return new ImageResponse(
    (
      <div
        style={{

         display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          fontSize: 128,
          background: 'lavender',
        }}
      >
        Twitter Image
      </div>
    ),
    size
  )
}

export const runtime = 'ed


geResponse } from 'next/og'

export async function generateImageMetadata({ params }) {
  return [
    {
      contentType: 'image/png',
      size: { width: 48, height: 48 },
      id: 'small',
    },
    {
      contentType: 'image/png',
      size: { width: 72, height: 72 },
      id: 'medium',
    },
  ]
}

export default async function icon({ params, id }) {
  const { size } = await params
  const iconId = await id
  return new ImageResponse(
    (
      <div
        style={{
          width: '100%',

: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          fontSize: 88,
          background: '#fff',
          color: '#000',
        }}
      >
        Icon {size} {iconId}
      </div>
    )
  )
}


pe * as Playwright from 'playwright'
import { createRouterAct } from 'router-act'

describe('mismatching prefetch', () => {
  const { next, isNextDev } = nextTestSetup({
    files: __dirname,
  })
  if (isNextDev) {
    test('disabled in development', () => {})
    return
  }

  function relativeHref(href: string) {
    const url = new URL(href)
    return url.pathname + url.search + url.hash
  }

  it(
    'recovers when a navigation rewrites to a different route than the one ' +
      'that was prefetched

RouterAct(page)

      // Reveal the link to trigger a prefetch of page A.
      const toggle = await browser.elementByCss(
        'input[data-link-accordion="/mismatching-prefetch/dynamic-page/a?mismatch-rewrite=./b"]'
      )
      await act(async () =>

',
    async () => {
      let page: Playwright.Page
      const browser = await next.browser('/mismatching-prefetch', {
        beforePageLoad(p: Playwright.Page) {
          page = p
        },
      })
      const act = create


from 'e2e-utils'
import { retry } from 'next-test-utils'

describe('server patch - history entry', () => {
  const { next, isNextDev } = nextTestSetup({
    files: __dirname,
  })

  if (isNextDev) {
    test('skipped in dev mode', () => {})
    return
  }

  // When a navigation suspends and then triggers a server patch (tree
  // mismatch retry), the retry should preserve the original transition's
  // push/replace intent. Because the suspended transition hasn't committed
  // to the browser history yet,

st browser = await next.browser('/push-search-params')

    await retry(async () => {
      const homePage = await browser.elementById('home-page')
      expect(await homePage.text()).toContain('Home')
    })

    // Navigate to the same page with differen

the retry inherits its navigate type so
  // that pushState still runs when the entangled transitions eventually
  // commit together.
  it('server patch preserves the push intent of a suspended transition', async () => {
    con


Setup } from 'e2e-utils'

describe('next-config-ts-type-error-cjs', () => {
  // TODO: Remove this once we bump minimum Node.js version to v22
  if (!(process.features as any).typescript) {
    it.skip('requires `process.features.typescript` to feature detect Node.js native TS', () => {})
    return
  }

  const { next, isNextDev, skipped } = nextTestSetup({
    files: __dirname,
    skipStart: true,
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  it('should throw with type error on build

ait next.start()
      const $ = await next.render$('/')
      expect($('p').text()).toBe('foo')
    } else {
      const { cliOutput } = await next.build()
      await expect(cliOutput).toContain(
        `Type 'string' is not assignable to type 'number'.

 (CJS)', async () => {
    if (isNextDev) {
      aw


utils'

describe('next-config-ts-type-error-esm', () => {
  // TODO: Remove this once we bump minimum Node.js version to v22
  if (!(process.features as any).typescript) {
    it.skip('requires `process.features.typescript` to feature detect Node.js native TS', () => {})
    return
  }

  const { next, isNextDev, skipped } = nextTestSetup({
    files: __dirname,
    skipStart: true,
    skipDeployment: true,
    packageJson: {
      type: 'module',
    },
  })

  if (skipped) {
    return
  }

  it('should

    if (isNextDev) {
      await next.start()
      const $ = await next.render$('/')
      expect($('p').text()).toBe('foo')
    } else {
      const { cliOutput } = await next.build()
      await expect(cliOutput).toContain(
        `Type 'string' is no

throw with type error on build (ESM)', async () => {


 { nextTestSetup } from 'e2e-utils'
import { renderViaHTTP, startCleanStaticServer } from 'next-test-utils'
import { join } from 'path'
import { AddressInfo, Server } from 'net'

describe('use-cache-output-export', () => {
  const { next, isNextStart } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
    skipStart: process.env.NEXT_TEST_MODE !== 'dev',
  })

  if (process.env.__NEXT_CACHE_COMPONENTS === 'true') {
    return it.skip('for PPR', () => {
      // PPR is not compatible with `out

        'Server Actions are not supported with static export.'
      )

      server = await startCleanStaticServer(join(next.testDir, 'out'))
      const { port } = server.address() as AddressInfo
      html = await renderViaHTTP(port, '/')
    } else {

put: 'export'`.
    })
  }

  it('should work', async () => {
    let html: string
    let server: Server | undefined

    if (isNextStart) {
      const { cliOutput } = await next.build()

      expect(cliOutput).not.toInclude(


TADATA_BASE_WARN_STRING =
  'metadataBase property in metadata export is not set for resolving social open graph or twitter images,'

describe('app dir - metadata missing metadataBase', () => {
  const { next, isNextDev, skipped } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
    overrideFiles: {
      'app/layout.js': `
        export default function Layout({ children }) {
          return (
            <div>
              {children}
            </div>
          )
        }

ess.
  // If it's development mode, we get the logs after request
  function getCliOutput(logStartPosition: number) {
    return isNextDev ? next.cliOutput.slice(logStartPosition) : next.cliOutput
  }

  it('should not show warning in output in default bui

      export const metadata = {
          metadataBase: new URL('https://example.com'),
        }
      `,
    },
  })

  if (skipped) {
    return
  }

  // If it's start mode, we get the whole logs since they're from build proc


esume-data-cache', () => {
  const { next, isNextDev } = nextTestSetup({
    files: __dirname,
  })

  if (isNextDev) {
    it('is skipped', () => {})
    return
  }

  it.each([
    { name: 'use cache', id: 'random-number' },
    { name: 'fetch cache', id: 'another-random-number' },
  ])(
    'should have consistent data between static and dynamic renders with $name',
    async ({ id }) => {
      // First render the page statically, getting the random number from the
      // HTML.
      let $ = await nex

://localhost')

        url.searchParams.set(
          '_rsc',
          await computeCacheBustingSearchParam(
            '1',
            '/__PAGE__',
            undefined,
            undefined
          )
        )

        const rsc = await next

t.render$('/')
      const first = $(`p#${id}`).text()

      // Then get the Prefetch RSC and validate that it also contains the same
      // random number.
      await retry(async () => {
        const url = new URL('/', 'http


ort React, { Suspense } from 'react'
import { cacheTag } from 'next/cache'
import { refreshAction } from '../actions'

async function getCachedRandomNumber() {
  'use cache'
  cacheTag('server-action-test')

  await new Promise((resolve) => setTimeout(resolve, 100))

  return Math.random()
}

async function getUncachedRandomNumber() {
  // No 'use cache' - this will generate a new value on every render
  await new Promise((resolve) => setTimeout(resolve, 100))
  return Math.random()
}

async function Dynami

(
    <>

{cachedNumber}

      <form action={refreshAction}>
        <button id="refresh-button" type="submit">
          Refresh
        </button>
      </form>
      <Suspense fallback={
Loading...</

cComponent() {
  const uncachedNumber = await getUncachedRandomNumber()
  return
{uncachedNumber}

}

export default async function Page() {
  const cachedNumber = await getCachedRandomNumber()
  return


ltCacheHandler =
  require('next/dist/server/lib/cache-handlers/default.external').default
const { AsyncLocalStorage } = require('node:async_hooks')
const snapshot = AsyncLocalStorage.snapshot()

/**
 * @type {import('next/dist/server/lib/cache-handlers/types').CacheHandler}
 */
const cacheHandler = {
  async get(cacheKey, softTags) {
    console.log('ModernCustomCacheHandler::get', cacheKey, softTags)
    return defaultCacheHandler.get(cacheKey, softTags)
  },

  async set(cacheKey, pendingEntry) {
    con

lidate}, expire: ${expire}, tags: ${tags}\n  ${cacheKey}`
        )
      })
    })

    return defaultCacheHandler.set(cacheKey, pendingEntry)
  },

  async refreshTags() {
    console.log('ModernCustomCacheHandler::refreshTags')
    return defaultCacheHa

sole.log('ModernCustomCacheHandler::set', cacheKey)

    pendingEntry.then(({ revalidate, expire, tags }) => {
      snapshot(() => {
        console.log(
          `ModernCustomCacheHandler::set-resolved-entry revalidate: ${reva


 from 'e2e-utils'

describe('turbopack-loader-content-type', () => {
  const { next, skipped } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
  })

  if (skipped) return

  it('should apply loader based on contentType glob pattern', async () => {
    const $ = await next.render$('/')
    const text = $('#text').text()
    expect(text).toBe('TEXT:Hello World')
  })

  it('should apply loader based on contentType for text/javascript', async () => {
    const $ = await next.render$('/')

('#js').text()
    expect(text).toBe('Hello from loader')
  })

  it('should apply loader based on contentType regex', async () => {
    const $ = await next.render$('/')
    const text = $('#image').text()
    expect(text).toMatch(/^IMAGE:\d+ bytes$/)
  }


tils'

describe('useSelectedLayoutSegment(s)', () => {
  const { next } = nextTestSetup({
    files: new FileRef(__dirname),
  })

  let browser: Playwright
  beforeEach(async () => {
    browser = await next.browser(
      '/segment-name/value1/segment-name2/value2/value3/value4'
    )
  })

  it('should return correct values for root layout', async () => {
    expect(
      await browser.elementByCss('#root > .segments').text()
    ).toMatchInlineSnapshot(
      `"["segment-name","value1","segment-name2",

 async () => {
    expect(
      await browser.elementByCss('#before-static > .segments').text()
    ).toMatchInlineSnapshot(`"["segment-name2","value2","value3/value4"]"`)

    expect(
      await browser.elementByCss('#before-static > .segment').text()

"value2","value3/value4"]"`
    )

    expect(
      await browser.elementByCss('#root > .segment').text()
    ).toMatchInlineSnapshot(`""segment-name""`)
  })

  it('should return correct values in layout before static segment',


rt { ImageResponse } from 'next/og'
import { ImageResponse as ImageResponse2 } from '@vercel/og'

// Node.js: Using @vercel/og external package, and should be aliased to "next/server" ImageResponse
// @ts-ignore
if (ImageResponse2.displayName !== ImageResponse.displayName)
  // @ts-ignore
  throw new Error('ImageResponse mismatch: ' + ImageResponse2.displayName)

export const alt = 'Twitter'
export const size = { width: 1600, height: 900 }

export default function twitter() {
  return new ImageResponse(

%',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          fontSize: 128,
          background: 'lavender',
        }}
      >
        Twitter Image
      </div>
    ),
    size

 (
      <div
        style={{
          width: '100


import { NextRequest, NextResponse } from 'next/server'

// Simulates what might happen if a proxy or firewall modifies the
// request based on a condition that changes after the prefetch but before
// the actual navigation.
//
// The proxy modifies the request based on special search parameters, but only
// during a navigation — not during a prefetch.
export const config = {
  matcher: [
    {
      source: '/:path*',

      // Exclude prefetch requests
      missing: [{ type: 'header', key: 'Next-Router-P

tResponse.redirect(new URL(mismatchRedirect, req.url))
  }

  const mismatchRewrite = req.nextUrl.searchParams.get('mismatch-rewrite')
  if (mismatchRewrite) {
    // Rewrite to the given URL.
    return NextResponse.rewrite(new URL(mismatchRewrite, req.ur

refetch' }],
    },
  ],
}

export default function proxy(req: NextRequest) {
  const mismatchRedirect = req.nextUrl.searchParams.get('mismatch-redirect')
  if (mismatchRedirect) {
    // Redirect to the given URL.
    return Nex


import { nextTestSetup } from 'e2e-utils'

describe('next-config-ts-import-js-extensions-esm', () => {
  // TODO: Remove this once we bump minimum Node.js version to v22
  if (!(process.features as any).typescript) {
    it.skip('requires `process.features.typescript` to feature detect Node.js native TS', () => {})
    return
  }

  const { next } = nextTestSetup({
    files: __dirname,
    packageJson: {
      type: 'module',
    },
  })

  it('should import js extensions (ESM)', async () => {
    const $

ender$('/')
    const text = $('p').text()
    expect(text).toContain('jsESM')
    expect(text).toContain('cjs')
    expect(text).toContain('mjs')
    expect(text).toContain('cts')
    expect(text).toContain('mts')
    expect(text).toContain('ts')
  })
})


retry } from 'next-test-utils'

describe('app dir - dynamic css', () => {
  const { next, skipped } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
  })

  if (skipped) {
    return
  }

  it('should preload all chunks of dynamic component during SSR', async () => {
    const $ = await next.render$('/ssr')
    const cssLinks = $('link[rel="stylesheet"][data-precedence="dynamic"]')
    expect(cssLinks.attr('href')).toContain('.css')

    const preloadJsChunks = $('link[rel="preload"]')

ait next.browser('/ssr')
    await retry(async () => {
      expect(
        await browser.eval(
          `window.getComputedStyle(document.querySelector('.text')).color`
        )
      ).toBe('rgb(255, 0, 0)')
      // Default border width, which is not

expect(preloadJsChunks.attr('as')).toBe('script')
    expect(preloadJsChunks.attr('fetchpriority')).toContain(`low`)
  })

  it('should only apply corresponding css for page loaded that /ssr', async () => {
    const browser = aw


 Suspense } from 'react'
import { connection } from 'next/server'
import { cacheTag } from 'next/cache'
import { RevalidateButton } from './revalidate-button'

async function getCachedRandom() {
  'use cache'
  cacheTag('revalidate-action-test')
  return Math.random()
}

async function DynamicContent() {
  // Make the page dynamic/PPR by accessing connection()
  await connection()
  // Generate uncached value after dynamic access
  const uncachedValue = Math.random()
  return <p id="uncached-value">{uncache

{
  const cachedValue = await getCachedRandom()

  return (

{cachedValue}

      <Suspense fallback={
Loading...
}>
        <DynamicContent />
      </Suspense>
      <RevalidateButton />

dValue}</p>
}

export default async function Page()


port { connection } from 'next/server'
import { RevalidateButton } from './revalidate-button'

async function DynamicContent() {
  // Make the page dynamic/PPR by accessing connection()
  await connection()
  // Generate uncached value after dynamic access
  const uncachedValue = Math.random()
  return
{uncachedValue}

}

export default async function Page() {
  // Use fetch with cache and tags
  const cachedValue = await fetch(
    'https://next-data-api-endpoint.vercel.app/api/ra

evalidate-fetch-action-test'] } }
  ).then((res) => res.text())

  return (

{cachedValue}

      <Suspense fallback={
Loading...
}>
        <DynamicContent />
      </Suspense>
      <Revalid

ndom',
    { cache: 'force-cache', next: { tags: ['r


st { next, skipped, isNextStart } = nextTestSetup({
    files: __dirname,
    // Skip deployment so we can test the custom cache handlers log output
    skipDeployment: true,
  })

  if (skipped) return

  let outputIndex: number

  beforeEach(() => {
    outputIndex = next.cliOutput.length
  })

  it('should use a modern custom cache handler if provided', async () => {
    const browser = await next.browser(`/`)
    const initialData = await browser.elementById('data').text()
    expect(initialData).toMatc

andler::get \["(development|[A-Za-z0-9_-]+)","([0-9a-f]{2})+",\[\]\] \[ '_N_T_\/layout', '_N_T_\/page', '_N_T_\/', '_N_T_\/index' \]/
    )

    expect(next.cliOutput.slice(outputIndex)).toMatch(
      /ModernCustomCacheHandler::set \["(development|[A-Za-z

h(isoDateRegExp)

    const cliOutput = next.cliOutput.slice(outputIndex)

    expect(cliOutput).toContain('ModernCustomCacheHandler::refreshTags')

    expect(next.cliOutput.slice(outputIndex)).toMatch(
      /ModernCustomCacheH


ort { MetadataRoute } from 'next'

export default function sitemap(): MetadataRoute.Sitemap {
  return [
    {
      url: 'https://example.com/about',
      videos: [
        {
          title: 'example',
          thumbnail_loc: 'https://example.com/image.jpg',
          description: 'this is the description',
          content_loc: 'http://streamserver.example.com/video123.mp4',
          player_loc: 'https://www.example.com/videoplayer.php?video=123',
          duration: 2,
          view_count: 50,

 restriction: {
            relationship: 'allow',
            content: 'IE GB US CA',
          },
          platform: {
            relationship: 'allow',
            content: 'web',
          },
          uploader: {
            info: 'https://www.examp

      tag: 'summer',
          rating: 4,
          expiration_date: '2025-09-16',
          publication_date: '2024-09-16',
          family_friendly: 'yes',
          requires_subscription: 'no',
          live: 'no',


port { nextTestSetup } from 'e2e-utils'

describe('app-dir - metadata-non-standard-custom-routes', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })

  it('should work with custom sitemap route', async () => {
    const res = await next.fetch('/sitemap')
    expect(res.status).toBe(200)
    expect(res.headers.get('content-type')).toBe('application/xml')
    expect(await res.text()).toMatchInlineSnapshot(`
      "<?xml version="1.0" encoding="UTF-8"?>
            <urlset xmlns="http://www

schemas/sitemap/0.9">
            <url>
            <loc>https://example.com</loc>
            <lastmod>2021-01-01</lastmod>
            <changefreq>weekly</changefreq>
            <priority>0.5</priority>
            </url>
            </urlset>"
    `)


./components/link-accordion'

export default function Page() {
  return (

        Tests what happens if a navigation resolves to a different route than
        the one that was prefetched.

            <LinkAccordion href="/mismatching-prefetch/dynamic-page/a?mismatch-redirect=./b">
              {`/mismatching-prefetch/dynamic-page/a ──[ redirects to ]──→ /mismatching-prefetch/dynamic-page/b`}
            </LinkAccordion>

ion href="/mismatching-prefetch/dynamic-page/a?mismatch-rewrite=./b">
              <code>{`/mismatching-prefetch/dynamic-page/a ──[ rewrites to ]──→ /mismatching-prefetch/dynamic-page/b`}</code>
            </LinkAccordion>
          </li>
        </ul>

        </li>
          <li>
            <LinkAccord


es: __dirname,
    skipDeployment: true,
    env: {
      NEXT_TEST_LOG_VALIDATION: '1',
    },
  })
  if (skipped) return
  if (!isNextDev) {
    it.skip('Only implemented in dev', () => {})
    return
  }

  let currentCliOutputIndex = 0
  beforeEach(() => {
    currentCliOutputIndex = next.cliOutput.length
  })

  function getCliOutputSinceMark(): string {
    if (next.cliOutput.length < currentCliOutputIndex) {
      currentCliOutputIndex = 0
    }
    return next.cliOutput.slice(currentCliOutputIndex)

t[] {
    const messageRe = /<VALIDATION_MESSAGE>(.*?)<\/VALIDATION_MESSAGE>/g
    const events: ValidationEvent[] = []
    let match: RegExpExecArray | null
    while ((match = messageRe.exec(output)) !== null) {
      try {
        events.push(JSON.parse

  }

  type ValidationEvent =
    | { type: 'validation_start'; requestId: string; url: string }
    | { type: 'validation_end'; requestId: string; url: string }

  function parseValidationMessages(output: string): ValidationEven


expect(text).toMatchInlineSnapshot(`
        "User-Agent: Googlebot
        Allow: /

        User-Agent: Applebot
        User-Agent: Bingbot
        Disallow: /
        Crawl-delay: 2

        Host: https://example.com
        Sitemap: https://example.com/sitemap.xml
        "
      `)
    })
  })

  describe('sitemap', () => {
    it('should handle sitemap.[ext] dynamic routes', async () => {
      const res = await next.fetch('/sitemap.xml')
      const text = await res.text()

      expect(res.headers.

    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
             <url>
             <loc>https://example.com</loc>
             <lastmod>2021-01-01</lastmod>
             <changefreq>weekly</changefreq>
             <priority>0.5</priority>

get('content-type')).toBe('application/xml')
      expect(res.headers.get('cache-control')).toBe(CACHE_HEADERS.REVALIDATE)

      expect(text).toMatchInlineSnapshot(`
             "<?xml version="1.0" encoding="UTF-8"?>


le_cache, updateTag } from 'next/cache'
import { connection } from 'next/server'
import { Suspense } from 'react'

export function generateStaticParams() {
  return [{ slug: '🎉' }]
}

async function Cached({ params }: { params: Promise<{ slug: string }> }) {
  'use cache'
  const { slug } = await params
  cacheTag('🎂')
  return (
    <>

{slug}

        Cached: {new Date().toISOString()}

    </>
  )
}

async function Dynamic() {
  await

],
  { tags: ['🌶'], revalidate: false }
)

export default async function Page({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  const fetched = await fetch(
    'https://next-data-api-endpoint.vercel.app/api/random',
    { next: { tags: ['🌮'], re

connection()

  return (

      Dynamic: {new Date().toISOString()}

  )
}

const getUnstableCached = unstable_cache(
  async () => new Date().toISOString(),
  ['unstable-cache-time'


from 'e2e-utils'
import { waitForRedbox, getRedboxHeader, retry } from 'next-test-utils'

describe('revalidateTag-rsc', () => {
  const { next, isNextDev, isNextDeploy } = nextTestSetup({
    files: __dirname,
  })

  it('should revalidate fetch cache if revalidateTag invoked via server action', async () => {
    const browser = await next.browser('/')
    const randomNumber = await browser.elementById('data').text()
    await browser.refresh()
    const randomNumber2 = await browser.elementById('data').tex

mber3).not.toEqual(randomNumber)
    })
  })

  if (!isNextDeploy) {
    // skipped in deploy because it uses `next.cliOutput`
    it('should error if revalidateTag is called during render', async () => {
      const browser = await next.browser('/')

t()
    expect(randomNumber).toEqual(randomNumber2)

    await browser.elementByCss('#submit-form').click()

    await retry(async () => {
      const randomNumber3 = await browser.elementById('data').text()
      expect(randomNu


check } from 'next-test-utils'

describe('parallel-route-not-found', () => {
  const { next, isNextDeploy } = nextTestSetup({
    files: __dirname,
  })

  it('should behave correctly without any errors', async () => {
    const browser = await next.browser('/en')

    // Deploy doesn't have access to runtime logs
    if (!isNextDeploy) {
      await check(() => {
        if (
          next.cliOutput.includes('TypeError') ||
          next.cliOutput.includes('Warning')
        ) {
          return 'has-err

tain('Locale: en')

    await browser.elementByCss("[href='/en/show']").click()

    // Deploy doesn't have access to runtime logs
    if (!isNextDeploy) {
      await check(() => {
        if (
          next.cliOutput.includes('TypeError') ||
          n

ors'
        }

        return 'success'
      }, 'success')
    }

    expect(await browser.elementByCss('body').text()).not.toContain(
      'Interception Modal'
    )
    expect(await browser.elementByCss('body').text()).toCon


` outside of the cached function and pass only the required search params as arguments to the cached function. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`

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

describe('use-cache-search-params', () => {
  const { next, isNextDev, skipped } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
    skipStart: process.env.NEXT_TEST_MODE !== 'dev',
  })

  if (skipped) {
    return
  }

=> {
        const outputIndex = next.cliOutput.length
        const browser = await next.browser(`${route}?foo=1`)

        if (isCacheComponentsEnabled) {
          await expect(browser).toDisplayRedbox(`
           {
             "code": "E842",

  if (isNextDev) {
    let route: string

    describe('when searchParams are used inside of "use cache"', () => {
      beforeAll(() => {
        route = '/search-params-used'
      })

      it('should show an error', async ()


, isNextDev } = nextTestSetup({
    files: __dirname,
  })

  // TODO: adjust the test to work with the new error
  it.skip('should handle a layout that attempts to render a missing parallel route', async () => {
    const browser = await next.browser('/no-bar-slot')
    const logs = await browser.log()
    expect(await browser.elementByCss('body').text()).toContain(
      'This page could not be found'
    )
    const warnings = logs.filter((log) => log.source === 'warning')
    if (isNextDev) {
      expe

')
    } else {
      expect(warnings.length).toBe(0)
    }
  })

  // TODO: adjust the test to work with the new error
  it.skip('should handle multiple missing parallel routes', async () => {
    const browser = await next.browser('/both-slots-missing')

ct(warnings.length).toBe(1)
      expect(warnings[0].message).toContain(
        'No default component was found for a parallel route rendered on this page'
      )
      expect(warnings[0].message).toContain('Missing slots: @bar


ype Playwright } from 'e2e-utils'
import { retry } from 'next-test-utils'

describe('router autoscrolling on navigation with css modules', () => {
  const { next } = nextTestSetup({
    files: __dirname,
  })
  const getTopScroll = async (browser: Playwright) =>
    await browser.eval('document.documentElement.scrollTop')

  const getLeftScroll = async (browser: Playwright) =>
    await browser.eval('document.documentElement.scrollLeft')

  const waitForScrollToComplete = async (
    browser: Playwright,

top: options.y, left: options.x })
    })
  }

  const scrollTo = async (
    browser: Playwright,
    options: { x: number; y: number }
  ) => {
    await browser.eval(`window.scrollTo(${options.x}, ${options.y})`)
    await waitForScrollToComplete(browse

  options: { x: number; y: number }
  ) => {
    await retry(async function expectScrolledTo() {
      const top = await getTopScroll(browser)
      const left = await getLeftScroll(browser)
      expect({ top, left }).toEqual({


tTestSetup } from 'e2e-utils'

// TODO: Test didn't (or maybe) never ran in CI but it should.
describe.skip('app dir - next-image (with https)', () => {
  const { next, skipped } = nextTestSetup({
    files: __dirname,
    skipDeployment: true,
    startCommand: `pnpm next dev --experimental-https`,
  })

  if (skipped) {
    return
  }

  it('loads images without any errors', async () => {
    let failCount = 0
    const browser = await next.browser('/', {
      beforePageLoad(page) {
        page.on('resp

esponse.ok()) {
            console.log(`Request failed: ${url}`)
            failCount++
          }
        })
      },
    })
    const image = browser.elementByCss('#app-page')
    const src = await image.getAttribute('src')

    if (process.env.IS_TUR

onse', (response) => {
          const url = response.url()
          if (!url.includes('/_next/image')) return

          const status = response.status()

          console.log(`URL: ${url} Status: ${status}`)

          if (!r


'
import httpProxy from 'http-proxy'
import fs from 'fs'
import { nextTestSetup } from 'e2e-utils'

let proxyPort
let proxyServer: https.Server

describe('next-image-proxy', () => {
  const { next, skipped } = nextTestSetup({
    files: __dirname,
    // This test is skipped when deployed because it relies on a proxy server
    skipDeployment: true,
  })

  if (skipped) return

  beforeAll(async () => {
    proxyPort = await findPort()

    const ssl = {
      key: fs.readFileSync(
        join(__dirname, '

rget: `http://localhost:${next.appPort}`,
      ssl,
      secure: false,
    })

    proxyServer = https.createServer(ssl, async (req, res) => {
      proxy.web(req, res)
    })

    proxy.on('error', (err) => {
      throw new Error('Failed to proxy: ' +

certificates/localhost-key.pem'),
        'utf8'
      ),
      cert: fs.readFileSync(
        join(__dirname, 'certificates/localhost.pem'),
        'utf8'
      ),
    }

    const proxy = httpProxy.createProxyServer({
      ta


ges')
        await fs.remove(imagesDir).catch(() => {})

        const $ = await next.render$('/')
        const imageUrl = $('#app-layout').attr('src')

        const headRes = await next.fetch(imageUrl, { method: 'HEAD' })
        expect(headRes.status).toBe(200)
        expect(headRes.headers.get('content-type')).toMatch(/^image\//)
        expect(headRes.headers.get('X-Nextjs-Cache')).toBe('MISS')

        const contentLength = headRes.headers.get('content-length')
        expect(Number(contentLength |

(getRes.headers.get('content-type')).toMatch(/^image\//)
        expect(getRes.headers.get('X-Nextjs-Cache')).toBe('HIT')

        const getContentLength = getRes.headers.get('content-length')
        expect(Number(getContentLength || '0')).toBeGreaterThan

| '0')).toBeGreaterThan(0)
        const headBody = await headRes.arrayBuffer()
        expect(headBody.byteLength).toBe(0)

        const getRes = await next.fetch(imageUrl)
        expect(getRes.status).toBe(200)
        expect


from 'e2e-utils'
;(process.env.IS_TURBOPACK_TEST ? describe : describe.skip)(
  'ecmascript-features turbopack',
  () => {
    const { next } = nextTestSetup({
      files: __dirname,
    })

    // Recommended for tests that check HTML. Cheerio is a HTML parser that has a jQuery like API.
    it('should work using cheerio', async () => {
      const $ = await next.render$('/')
      expect(JSON.parse($('#values-to-check').text())).toEqual({
        privateField: 10,
        privateFieldWithInitializer: 11,

next.render$('/export-as-string')
      expect(JSON.parse($1('#values-to-check').text())).toEqual({
        exportAsString: 1,
      })
    })

    // Recommended for tests that need a full browser
    it('should work using browser', async () => {
      co

        privateStaticFieldWithInitializer: 12,
        privateStaticMethod: 12,
        privateMethodInThis: true,
        exportAs: 1,
        // regex: true,
        importWith: 'Hello World',
      })

      const $1 = await


 server and client compilation of ECMAScript features.
import { abc } from './export-as'
import json from './file.json' with { type: 'json' }

class ClassWithPrivate {
  #privateField
  #privateFieldWithInitializer = 11

  #privateMethod() {
    this.#privateField = 10
  }

  static #privateStaticFieldWithInitializer = 12

  static #privateStaticMethod() {
    return this.#privateStaticFieldWithInitializer
  }

  constructor() {
    this.#privateMethod()
  }

  getPrivateField() {
    return this.#privateFi

) {
    return ClassWithPrivate.#privateStaticMethod()
  }
  isPrivateMethodAvailable() {
    return #privateField in this
  }
}

// Not supported in Node.js yet.
// let regex = /abc/v

export default function Page() {
  const instance = new ClassWithPriva

eld
  }
  getPrivateFieldWithInitializer() {
    return this.#privateFieldWithInitializer
  }
  getPrivateStaticFieldWithInitializer() {
    return ClassWithPrivate.#privateStaticFieldWithInitializer
  }
  getPrivateStaticMethod(


from 'e2e-utils'
;(process.env.IS_TURBOPACK_TEST ? describe.skip : describe)(
  'ecmascript-features webpack',
  () => {
    const { next } = nextTestSetup({
      files: __dirname,
    })

    // Recommended for tests that check HTML. Cheerio is a HTML parser that has a jQuery like API.
    it('should work using cheerio', async () => {
      const $ = await next.render$('/')
      expect(JSON.parse($('#values-to-check').text())).toEqual({
        privateField: 10,
        privateFieldWithInitializer: 11,

x as "abc" }` (export as string) is not supported in webpack yet.
      // const $1 = await next.render$('/export-as-string')
      // expect(JSON.parse($1('#values-to-check').text())).toEqual({
      //   exportAsString: 1,
      // })
    })

    // Reco

       privateStaticFieldWithInitializer: 12,
        privateStaticMethod: 12,
        privateMethodInThis: true,
        exportAs: 1,
        // regex: true,
        importWith: 'Hello World',
      })

      // TODO: `export {


s'

describe('bfcache-regression', () => {
  const { next, isTurbopack } = nextTestSetup({
    files: __dirname,
  })

  it('should preserve interactivity after navigating back from another page via MPA navigation', async () => {
    // In webpack dev, compiling a new route on demand while another page is
    // open triggers an HMR cycle that has no Fast Refresh boundary, surfacing
    // a "performing full reload" warning on the open page. Warm up the target
    // page in parallel with the browser load s

null,
    ])

    // Verify initial state and that the counter is interactive.
    await browser.elementById('increment').click()

    await retry(async () => {
      expect(await browser.elementById('count').text()).toBe('Count: 1')
    })

    // Navigat

o it's already compiled by the
    // time we click the link.
    const [browser] = await Promise.all([
      next.browser('/', { pushErrorAsConsoleLog: true }),
      !isTurbopack ? next.render('/target-page').catch(() => {}) :