{"version":3,"sources":["../../../../src/client/components/segment-cache-impl/cache.ts"],"sourcesContent":["import type {\n  TreePrefetch,\n  RootTreePrefetch,\n  SegmentPrefetch,\n} from '../../../server/app-render/collect-segment-data'\nimport type {\n  HeadData,\n  LoadingModuleData,\n} from '../../../shared/lib/app-router-context.shared-runtime'\nimport type {\n  CacheNodeSeedData,\n  DynamicParamTypesShort,\n  Segment as FlightRouterStateSegment,\n} from '../../../server/app-render/types'\nimport { HasLoadingBoundary } from '../../../server/app-render/types'\nimport {\n  NEXT_DID_POSTPONE_HEADER,\n  NEXT_ROUTER_PREFETCH_HEADER,\n  NEXT_ROUTER_SEGMENT_PREFETCH_HEADER,\n  NEXT_ROUTER_STALE_TIME_HEADER,\n  NEXT_ROUTER_STATE_TREE_HEADER,\n  NEXT_URL,\n  RSC_CONTENT_TYPE_HEADER,\n  RSC_HEADER,\n} from '../app-router-headers'\nimport {\n  createFetch,\n  createFromNextReadableStream,\n  type RSCResponse,\n  type RequestHeaders,\n} from '../router-reducer/fetch-server-response'\nimport {\n  pingPrefetchTask,\n  isPrefetchTaskDirty,\n  type PrefetchTask,\n  type PrefetchSubtaskResult,\n} from './scheduler'\nimport { getAppBuildId } from '../../app-build-id'\nimport { createHrefFromUrl } from '../router-reducer/create-href-from-url'\nimport type {\n  NormalizedHref,\n  NormalizedNextUrl,\n  NormalizedSearch,\n  RouteCacheKey,\n} from './cache-key'\n// TODO: Rename this module to avoid confusion with other types of cache keys\nimport { createCacheKey as createPrefetchRequestKey } from './cache-key'\nimport {\n  doesStaticSegmentAppearInURL,\n  getCacheKeyForDynamicParam,\n  getParamValueFromCacheKey,\n  getRenderedPathname,\n  getRenderedSearch,\n  parseDynamicParamFromURLPart,\n  type RouteParam,\n} from '../../route-params'\nimport { createTupleMap, type TupleMap, type Prefix } from './tuple-map'\nimport { createLRU } from './lru'\nimport {\n  appendSegmentCacheKeyPart,\n  appendSegmentRequestKeyPart,\n  convertSegmentPathToStaticExportFilename,\n  createSegmentCacheKeyPart,\n  createSegmentRequestKeyPart,\n  ROOT_SEGMENT_CACHE_KEY,\n  ROOT_SEGMENT_REQUEST_KEY,\n  type SegmentCacheKey,\n  type SegmentRequestKey,\n} from '../../../shared/lib/segment-cache/segment-value-encoding'\nimport type {\n  FlightRouterState,\n  NavigationFlightResponse,\n} from '../../../server/app-render/types'\nimport { normalizeFlightData } from '../../flight-data-helpers'\nimport { STATIC_STALETIME_MS } from '../router-reducer/prefetch-cache-utils'\nimport { pingVisibleLinks } from '../links'\nimport { PAGE_SEGMENT_KEY } from '../../../shared/lib/segment'\nimport {\n  DOC_PREFETCH_RANGE_HEADER_VALUE,\n  doesExportedHtmlMatchBuildId,\n} from '../../../shared/lib/segment-cache/output-export-prefetch-encoding'\nimport { FetchStrategy } from '../segment-cache'\nimport { createPromiseWithResolvers } from '../../../shared/lib/promise-with-resolvers'\n\n// A note on async/await when working in the prefetch cache:\n//\n// Most async operations in the prefetch cache should *not* use async/await,\n// Instead, spawn a subtask that writes the results to a cache entry, and attach\n// a \"ping\" listener to notify the prefetch queue to try again.\n//\n// The reason is we need to be able to access the segment cache and traverse its\n// data structures synchronously. For example, if there's a synchronous update\n// we can take an immediate snapshot of the cache to produce something we can\n// render. Limiting the use of async/await also makes it easier to avoid race\n// conditions, which is especially important because is cache is mutable.\n//\n// Another reason is that while we're performing async work, it's possible for\n// existing entries to become stale, or for Link prefetches to be removed from\n// the queue. For optimal scheduling, we need to be able to \"cancel\" subtasks\n// that are no longer needed. So, when a segment is received from the server, we\n// restart from the root of the tree that's being prefetched, to confirm all the\n// parent segments are still cached. If the segment is no longer reachable from\n// the root, then it's effectively canceled. This is similar to the design of\n// Rust Futures, or React Suspense.\n\nexport type RouteTree = {\n  cacheKey: SegmentCacheKey\n  requestKey: SegmentRequestKey\n  // TODO: Remove the `segment` field, now that it can be reconstructed\n  // from `param`.\n  segment: FlightRouterStateSegment\n  param: RouteParam | null\n  slots: null | {\n    [parallelRouteKey: string]: RouteTree\n  }\n  isRootLayout: boolean\n\n  // If this is a dynamic route, indicates whether there is a loading boundary\n  // somewhere in the tree. If not, we can skip the prefetch for the data,\n  // because we know it would be an empty response. (For a static/PPR route,\n  // this value is disregarded, because in that model `loading.tsx` is treated\n  // like any other Suspense boundary.)\n  hasLoadingBoundary: HasLoadingBoundary\n}\n\ntype RouteCacheEntryShared = {\n  staleAt: number\n  // This is false only if we're certain the route cannot be intercepted. It's\n  // true in all other cases, including on initialization when we haven't yet\n  // received a response from the server.\n  couldBeIntercepted: boolean\n\n  // See comment in scheduler.ts for context\n  TODO_metadataStatus: EntryStatus.Empty | EntryStatus.Fulfilled\n  TODO_isHeadDynamic: boolean\n\n  // LRU-related fields\n  keypath: null | Prefix<RouteCacheKeypath>\n  next: null | RouteCacheEntry\n  prev: null | RouteCacheEntry\n  size: number\n}\n\n/**\n * Tracks the status of a cache entry as it progresses from no data (Empty),\n * waiting for server data (Pending), and finished (either Fulfilled or\n * Rejected depending on the response from the server.\n */\nexport const enum EntryStatus {\n  Empty,\n  Pending,\n  Fulfilled,\n  Rejected,\n}\n\ntype PendingRouteCacheEntry = RouteCacheEntryShared & {\n  status: EntryStatus.Empty | EntryStatus.Pending\n  blockedTasks: Set<PrefetchTask> | null\n  canonicalUrl: null\n  renderedSearch: null\n  tree: null\n  head: HeadData | null\n  isHeadPartial: true\n  isPPREnabled: false\n}\n\ntype RejectedRouteCacheEntry = RouteCacheEntryShared & {\n  status: EntryStatus.Rejected\n  blockedTasks: Set<PrefetchTask> | null\n  canonicalUrl: null\n  renderedSearch: null\n  tree: null\n  head: null\n  isHeadPartial: true\n  isPPREnabled: boolean\n}\n\nexport type FulfilledRouteCacheEntry = RouteCacheEntryShared & {\n  status: EntryStatus.Fulfilled\n  blockedTasks: null\n  canonicalUrl: string\n  renderedSearch: NormalizedSearch\n  tree: RouteTree\n  head: HeadData\n  isHeadPartial: boolean\n  isPPREnabled: boolean\n}\n\nexport type RouteCacheEntry =\n  | PendingRouteCacheEntry\n  | FulfilledRouteCacheEntry\n  | RejectedRouteCacheEntry\n\ntype SegmentCacheEntryShared = {\n  staleAt: number\n  fetchStrategy: FetchStrategy\n  revalidating: SegmentCacheEntry | null\n\n  // LRU-related fields\n  keypath: null | Prefix<SegmentCacheKeypath>\n  next: null | SegmentCacheEntry\n  prev: null | SegmentCacheEntry\n  size: number\n}\n\nexport type EmptySegmentCacheEntry = SegmentCacheEntryShared & {\n  status: EntryStatus.Empty\n  rsc: null\n  loading: null\n  isPartial: true\n  promise: null\n}\n\nexport type PendingSegmentCacheEntry = SegmentCacheEntryShared & {\n  status: EntryStatus.Pending\n  rsc: null\n  loading: null\n  isPartial: true\n  promise: null | PromiseWithResolvers<FulfilledSegmentCacheEntry | null>\n}\n\ntype RejectedSegmentCacheEntry = SegmentCacheEntryShared & {\n  status: EntryStatus.Rejected\n  rsc: null\n  loading: null\n  isPartial: true\n  promise: null\n}\n\nexport type FulfilledSegmentCacheEntry = SegmentCacheEntryShared & {\n  status: EntryStatus.Fulfilled\n  rsc: React.ReactNode | null\n  loading: LoadingModuleData | Promise<LoadingModuleData>\n  isPartial: boolean\n  promise: null\n}\n\nexport type SegmentCacheEntry =\n  | EmptySegmentCacheEntry\n  | PendingSegmentCacheEntry\n  | RejectedSegmentCacheEntry\n  | FulfilledSegmentCacheEntry\n\nexport type NonEmptySegmentCacheEntry = Exclude<\n  SegmentCacheEntry,\n  EmptySegmentCacheEntry\n>\n\nconst isOutputExportMode =\n  process.env.NODE_ENV === 'production' &&\n  process.env.__NEXT_CONFIG_OUTPUT === 'export'\n\n/**\n * Ensures a minimum stale time of 30s to avoid issues where the server sends a too\n * short-lived stale time, which would prevent anything from being prefetched.\n */\nfunction getStaleTimeMs(staleTimeSeconds: number): number {\n  return Math.max(staleTimeSeconds, 30) * 1000\n}\n\n// Route cache entries vary on multiple keys: the href and the Next-Url. Each of\n// these parts needs to be included in the internal cache key. Rather than\n// concatenate the keys into a single key, we use a multi-level map, where the\n// first level is keyed by href, the second level is keyed by Next-Url, and so\n// on (if were to add more levels).\ntype RouteCacheKeypath = [NormalizedHref, NormalizedNextUrl]\nlet routeCacheMap: TupleMap<RouteCacheKeypath, RouteCacheEntry> =\n  createTupleMap()\n\n// We use an LRU for memory management. We must update this whenever we add or\n// remove a new cache entry, or when an entry changes size.\n// TODO: I chose the max size somewhat arbitrarily. Consider setting this based\n// on navigator.deviceMemory, or some other heuristic. We should make this\n// customizable via the Next.js config, too.\nconst maxRouteLruSize = 10 * 1024 * 1024 // 10 MB\nlet routeCacheLru = createLRU<RouteCacheEntry>(\n  maxRouteLruSize,\n  onRouteLRUEviction\n)\n\ntype SegmentCacheKeypath = [string, NormalizedSearch]\nlet segmentCacheMap: TupleMap<SegmentCacheKeypath, SegmentCacheEntry> =\n  createTupleMap()\n// NOTE: Segments and Route entries are managed by separate LRUs. We could\n// combine them into a single LRU, but because they are separate types, we'd\n// need to wrap each one in an extra LRU node (to maintain monomorphism, at the\n// cost of additional memory).\nconst maxSegmentLruSize = 50 * 1024 * 1024 // 50 MB\nlet segmentCacheLru = createLRU<SegmentCacheEntry>(\n  maxSegmentLruSize,\n  onSegmentLRUEviction\n)\n\n// All invalidation listeners for the whole cache are tracked in single set.\n// Since we don't yet support tag or path-based invalidation, there's no point\n// tracking them any more granularly than this. Once we add granular\n// invalidation, that may change, though generally the model is to just notify\n// the listeners and allow the caller to poll the prefetch cache with a new\n// prefetch task if desired.\nlet invalidationListeners: Set<PrefetchTask> | null = null\n\n// Incrementing counter used to track cache invalidations.\nlet currentCacheVersion = 0\n\nexport function getCurrentCacheVersion(): number {\n  return currentCacheVersion\n}\n\n/**\n * Used to clear the client prefetch cache when a server action calls\n * revalidatePath or revalidateTag. Eventually we will support only clearing the\n * segments that were actually affected, but there's more work to be done on the\n * server before the client is able to do this correctly.\n */\nexport function revalidateEntireCache(\n  nextUrl: string | null,\n  tree: FlightRouterState\n) {\n  currentCacheVersion++\n\n  // Clearing the cache also effectively rejects any pending requests, because\n  // when the response is received, it gets written into a cache entry that is\n  // no longer reachable.\n  // TODO: There's an exception to this case that we don't currently handle\n  // correctly: background revalidations. See note in `upsertSegmentEntry`.\n  routeCacheMap = createTupleMap()\n  routeCacheLru = createLRU(maxRouteLruSize, onRouteLRUEviction)\n  segmentCacheMap = createTupleMap()\n  segmentCacheLru = createLRU(maxSegmentLruSize, onSegmentLRUEviction)\n\n  // Prefetch all the currently visible links again, to re-fill the cache.\n  pingVisibleLinks(nextUrl, tree)\n\n  // Similarly, notify all invalidation listeners (i.e. those passed to\n  // `router.prefetch(onInvalidate)`), so they can trigger a new prefetch\n  // if needed.\n  pingInvalidationListeners(nextUrl, tree)\n}\n\nfunction attachInvalidationListener(task: PrefetchTask): void {\n  // This function is called whenever a prefetch task reads a cache entry. If\n  // the task has an onInvalidate function associated with it — i.e. the one\n  // optionally passed to router.prefetch(onInvalidate) — then we attach that\n  // listener to the every cache entry that the task reads. Then, if an entry\n  // is invalidated, we call the function.\n  if (task.onInvalidate !== null) {\n    if (invalidationListeners === null) {\n      invalidationListeners = new Set([task])\n    } else {\n      invalidationListeners.add(task)\n    }\n  }\n}\n\nfunction notifyInvalidationListener(task: PrefetchTask): void {\n  const onInvalidate = task.onInvalidate\n  if (onInvalidate !== null) {\n    // Clear the callback from the task object to guarantee it's not called more\n    // than once.\n    task.onInvalidate = null\n\n    // This is a user-space function, so we must wrap in try/catch.\n    try {\n      onInvalidate()\n    } catch (error) {\n      if (typeof reportError === 'function') {\n        reportError(error)\n      } else {\n        console.error(error)\n      }\n    }\n  }\n}\n\nexport function pingInvalidationListeners(\n  nextUrl: string | null,\n  tree: FlightRouterState\n): void {\n  // The rough equivalent of pingVisibleLinks, but for onInvalidate callbacks.\n  // This is called when the Next-Url or the base tree changes, since those\n  // may affect the result of a prefetch task. It's also called after a\n  // cache invalidation.\n  if (invalidationListeners !== null) {\n    const tasks = invalidationListeners\n    invalidationListeners = null\n    for (const task of tasks) {\n      if (isPrefetchTaskDirty(task, nextUrl, tree)) {\n        notifyInvalidationListener(task)\n      }\n    }\n  }\n}\n\nexport function readExactRouteCacheEntry(\n  now: number,\n  href: NormalizedHref,\n  nextUrl: NormalizedNextUrl | null\n): RouteCacheEntry | null {\n  const keypath: Prefix<RouteCacheKeypath> =\n    nextUrl === null ? [href] : [href, nextUrl]\n  const existingEntry = routeCacheMap.get(keypath)\n  if (existingEntry !== null) {\n    // Check if the entry is stale\n    if (existingEntry.staleAt > now) {\n      // Reuse the existing entry.\n\n      // Since this is an access, move the entry to the front of the LRU.\n      routeCacheLru.put(existingEntry)\n\n      return existingEntry\n    } else {\n      // Evict the stale entry from the cache.\n      deleteRouteFromCache(existingEntry, keypath)\n    }\n  }\n  return null\n}\n\nexport function readRouteCacheEntry(\n  now: number,\n  key: RouteCacheKey\n): RouteCacheEntry | null {\n  // First check if there's a non-intercepted entry. Most routes cannot be\n  // intercepted, so this is the common case.\n  const nonInterceptedEntry = readExactRouteCacheEntry(now, key.href, null)\n  if (nonInterceptedEntry !== null && !nonInterceptedEntry.couldBeIntercepted) {\n    // Found a match, and the route cannot be intercepted. We can reuse it.\n    return nonInterceptedEntry\n  }\n  // There was no match. Check again but include the Next-Url this time.\n  return readExactRouteCacheEntry(now, key.href, key.nextUrl)\n}\n\nexport function getSegmentKeypathForTask(\n  task: PrefetchTask,\n  route: FulfilledRouteCacheEntry,\n  cacheKey: SegmentCacheKey\n): Prefix<SegmentCacheKeypath> {\n  // When a prefetch includes dynamic data, the search params are included\n  // in the result, so we must include the search string in the segment\n  // cache key. (Note that this is true even if the search string is empty.)\n  //\n  // If we're fetching using PPR, we do not need to include the search params in\n  // the cache key, because the search params are treated as dynamic data. The\n  // cache entry is valid for all possible search param values.\n  const isDynamicTask =\n    task.fetchStrategy === FetchStrategy.Full ||\n    task.fetchStrategy === FetchStrategy.PPRRuntime ||\n    !route.isPPREnabled\n  return isDynamicTask && cacheKey.endsWith('/' + PAGE_SEGMENT_KEY)\n    ? [cacheKey, route.renderedSearch]\n    : [cacheKey]\n}\n\nexport function readSegmentCacheEntry(\n  now: number,\n  route: FulfilledRouteCacheEntry,\n  cacheKey: SegmentCacheKey\n): SegmentCacheEntry | null {\n  if (!cacheKey.endsWith('/' + PAGE_SEGMENT_KEY)) {\n    // Fast path. Search params only exist on page segments.\n    return readExactSegmentCacheEntry(now, [cacheKey])\n  }\n\n  const renderedSearch = route.renderedSearch\n  if (renderedSearch !== null) {\n    // Page segments may or may not contain search params. If they were prefetched\n    // using a dynamic request, then we will have an entry with search params.\n    // Check for that case first.\n    const entryWithSearchParams = readExactSegmentCacheEntry(now, [\n      cacheKey,\n      renderedSearch,\n    ])\n    if (entryWithSearchParams !== null) {\n      return entryWithSearchParams\n    }\n  }\n\n  // If we did not find an entry with the given search params, check for a\n  // \"fallback\" entry, where the search params are treated as dynamic data. This\n  // is the common case because PPR/static prerenders always treat search params\n  // as dynamic.\n  //\n  // See corresponding logic in `getSegmentKeypathForTask`.\n  const entryWithoutSearchParams = readExactSegmentCacheEntry(now, [cacheKey])\n  return entryWithoutSearchParams\n}\n\nfunction readExactSegmentCacheEntry(\n  now: number,\n  keypath: Prefix<SegmentCacheKeypath>\n): SegmentCacheEntry | null {\n  const existingEntry = segmentCacheMap.get(keypath)\n  if (existingEntry !== null) {\n    // Check if the entry is stale\n    if (existingEntry.staleAt > now) {\n      // Reuse the existing entry.\n\n      // Since this is an access, move the entry to the front of the LRU.\n      segmentCacheLru.put(existingEntry)\n\n      return existingEntry\n    } else {\n      // This is a stale entry.\n      const revalidatingEntry = existingEntry.revalidating\n      if (revalidatingEntry !== null) {\n        // There's a revalidation in progress. Upsert it.\n        const upsertedEntry = upsertSegmentEntry(\n          now,\n          keypath,\n          revalidatingEntry\n        )\n        if (upsertedEntry !== null && upsertedEntry.staleAt > now) {\n          // We can use the upserted revalidation entry.\n          return upsertedEntry\n        }\n      } else {\n        // Evict the stale entry from the cache.\n        deleteSegmentFromCache(existingEntry, keypath)\n      }\n    }\n  }\n  return null\n}\n\nfunction readRevalidatingSegmentCacheEntry(\n  now: number,\n  owner: SegmentCacheEntry\n): SegmentCacheEntry | null {\n  const existingRevalidation = owner.revalidating\n  if (existingRevalidation !== null) {\n    if (existingRevalidation.staleAt > now) {\n      // There's already a revalidation in progress. Or a previous revalidation\n      // failed and it has not yet expired.\n      return existingRevalidation\n    } else {\n      // Clear the stale revalidation from its owner.\n      clearRevalidatingSegmentFromOwner(owner)\n    }\n  }\n  return null\n}\n\nexport function waitForSegmentCacheEntry(\n  pendingEntry: PendingSegmentCacheEntry\n): Promise<FulfilledSegmentCacheEntry | null> {\n  // Because the entry is pending, there's already a in-progress request.\n  // Attach a promise to the entry that will resolve when the server responds.\n  let promiseWithResolvers = pendingEntry.promise\n  if (promiseWithResolvers === null) {\n    promiseWithResolvers = pendingEntry.promise =\n      createPromiseWithResolvers<FulfilledSegmentCacheEntry | null>()\n  } else {\n    // There's already a promise we can use\n  }\n  return promiseWithResolvers.promise\n}\n\n/**\n * Checks if an entry for a route exists in the cache. If so, it returns the\n * entry, If not, it adds an empty entry to the cache and returns it.\n */\nexport function readOrCreateRouteCacheEntry(\n  now: number,\n  task: PrefetchTask\n): RouteCacheEntry {\n  attachInvalidationListener(task)\n\n  const key = task.key\n  const existingEntry = readRouteCacheEntry(now, key)\n  if (existingEntry !== null) {\n    return existingEntry\n  }\n  // Create a pending entry and add it to the cache.\n  const pendingEntry: PendingRouteCacheEntry = {\n    canonicalUrl: null,\n    status: EntryStatus.Empty,\n    blockedTasks: null,\n    tree: null,\n    head: null,\n    isHeadPartial: true,\n    // Since this is an empty entry, there's no reason to ever evict it. It will\n    // be updated when the data is populated.\n    staleAt: Infinity,\n    // This is initialized to true because we don't know yet whether the route\n    // could be intercepted. It's only set to false once we receive a response\n    // from the server.\n    couldBeIntercepted: true,\n    // Similarly, we don't yet know if the route supports PPR.\n    isPPREnabled: false,\n    renderedSearch: null,\n\n    TODO_metadataStatus: EntryStatus.Empty,\n    TODO_isHeadDynamic: false,\n\n    // LRU-related fields\n    keypath: null,\n    next: null,\n    prev: null,\n    size: 0,\n  }\n  const keypath: Prefix<RouteCacheKeypath> =\n    key.nextUrl === null ? [key.href] : [key.href, key.nextUrl]\n  routeCacheMap.set(keypath, pendingEntry)\n  // Stash the keypath on the entry so we know how to remove it from the map\n  // if it gets evicted from the LRU.\n  pendingEntry.keypath = keypath\n  routeCacheLru.put(pendingEntry)\n  return pendingEntry\n}\n\nexport function requestOptimisticRouteCacheEntry(\n  now: number,\n  requestedUrl: URL,\n  nextUrl: string | null\n): FulfilledRouteCacheEntry | null {\n  // This function is called during a navigation when there was no matching\n  // route tree in the prefetch cache. Before de-opting to a blocking,\n  // unprefetched navigation, we will first attempt to construct an \"optimistic\"\n  // route tree by checking the cache for similar routes.\n  //\n  // Check if there's a route with the same pathname, but with different\n  // search params. We can then base our optimistic route tree on this entry.\n  //\n  // Conceptually, we are simulating what would happen if we did perform a\n  // prefetch the requested URL, under the assumption that the server will\n  // not redirect or rewrite the request in a different manner than the\n  // base route tree. This assumption might not hold, in which case we'll have\n  // to recover when we perform the dynamic navigation request. However, this\n  // is what would happen if a route were dynamically rewritten/redirected\n  // in between the prefetch and the navigation. So the logic needs to exist\n  // to handle this case regardless.\n\n  // Look for a route with the same pathname, but with an empty search string.\n  // TODO: There's nothing inherently special about the empty search string;\n  // it's chosen somewhat arbitrarily, with the rationale that it's the most\n  // likely one to exist. But we should update this to match _any_ search\n  // string. The plan is to generalize this logic alongside other improvements\n  // related to \"fallback\" cache entries.\n  const requestedSearch = requestedUrl.search as NormalizedSearch\n  if (requestedSearch === '') {\n    // The caller would have already checked if a route with an empty search\n    // string is in the cache. So we can bail out here.\n    return null\n  }\n  const routeWithNoSearchParams = readRouteCacheEntry(\n    now,\n    createPrefetchRequestKey(\n      requestedUrl.origin + requestedUrl.pathname,\n      nextUrl\n    )\n  )\n\n  if (\n    routeWithNoSearchParams === null ||\n    routeWithNoSearchParams.status !== EntryStatus.Fulfilled ||\n    // There's no point constructing an optimistic route tree if the metadata\n    // isn't fully available, because we'll have to do a blocking\n    // navigation anyway.\n    routeWithNoSearchParams.isHeadPartial ||\n    // We cannot reuse this route if it has dynamic metadata.\n    // TODO: Move the metadata out of the route cache entry so the route\n    // tree is reusable separately from the metadata. Then we can remove\n    // these checks.\n    routeWithNoSearchParams.TODO_metadataStatus !== EntryStatus.Empty ||\n    routeWithNoSearchParams.TODO_isHeadDynamic\n  ) {\n    // Bail out of constructing an optimistic route tree. This will result in\n    // a blocking, unprefetched navigation.\n    return null\n  }\n\n  // Now we have a base route tree we can \"patch\" with our optimistic values.\n\n  // Optimistically assume that redirects for the requested pathname do\n  // not vary on the search string. Therefore, if the base route was\n  // redirected to a different search string, then the optimistic route\n  // should be redirected to the same search string. Otherwise, we use\n  // the requested search string.\n  const canonicalUrlForRouteWithNoSearchParams = new URL(\n    routeWithNoSearchParams.canonicalUrl,\n    requestedUrl.origin\n  )\n  const optimisticCanonicalSearch =\n    canonicalUrlForRouteWithNoSearchParams.search !== ''\n      ? // Base route was redirected. Reuse the same redirected search string.\n        canonicalUrlForRouteWithNoSearchParams.search\n      : requestedSearch\n\n  // Similarly, optimistically assume that rewrites for the requested\n  // pathname do not vary on the search string. Therefore, if the base\n  // route was rewritten to a different search string, then the optimistic\n  // route should be rewritten to the same search string. Otherwise, we use\n  // the requested search string.\n  const optimisticRenderedSearch =\n    routeWithNoSearchParams.renderedSearch !== ''\n      ? // Base route was rewritten. Reuse the same rewritten search string.\n        routeWithNoSearchParams.renderedSearch\n      : requestedSearch\n\n  const optimisticUrl = new URL(\n    routeWithNoSearchParams.canonicalUrl,\n    location.origin\n  )\n  optimisticUrl.search = optimisticCanonicalSearch\n  const optimisticCanonicalUrl = createHrefFromUrl(optimisticUrl)\n\n  // Clone the base route tree, and override the relevant fields with our\n  // optimistic values.\n  const optimisticEntry: FulfilledRouteCacheEntry = {\n    canonicalUrl: optimisticCanonicalUrl,\n\n    status: EntryStatus.Fulfilled,\n    // This isn't cloned because it's instance-specific\n    blockedTasks: null,\n    tree: routeWithNoSearchParams.tree,\n    head: routeWithNoSearchParams.head,\n    isHeadPartial: routeWithNoSearchParams.isHeadPartial,\n    staleAt: routeWithNoSearchParams.staleAt,\n    couldBeIntercepted: routeWithNoSearchParams.couldBeIntercepted,\n    isPPREnabled: routeWithNoSearchParams.isPPREnabled,\n\n    // Override the rendered search with the optimistic value.\n    renderedSearch: optimisticRenderedSearch,\n\n    TODO_metadataStatus: routeWithNoSearchParams.TODO_metadataStatus,\n    TODO_isHeadDynamic: routeWithNoSearchParams.TODO_isHeadDynamic,\n\n    // LRU-related fields\n    keypath: null,\n    next: null,\n    prev: null,\n    size: 0,\n  }\n\n  // Do not insert this entry into the cache. It only exists so we can\n  // perform the current navigation. Just return it to the caller.\n  return optimisticEntry\n}\n\n/**\n * Checks if an entry for a segment exists in the cache. If so, it returns the\n * entry, If not, it adds an empty entry to the cache and returns it.\n */\nexport function readOrCreateSegmentCacheEntry(\n  now: number,\n  task: PrefetchTask,\n  route: FulfilledRouteCacheEntry,\n  cacheKey: SegmentCacheKey\n): SegmentCacheEntry {\n  const keypath = getSegmentKeypathForTask(task, route, cacheKey)\n  const existingEntry = readExactSegmentCacheEntry(now, keypath)\n  if (existingEntry !== null) {\n    return existingEntry\n  }\n  // Create a pending entry and add it to the cache.\n  const pendingEntry = createDetachedSegmentCacheEntry(route.staleAt)\n  segmentCacheMap.set(keypath, pendingEntry)\n  // Stash the keypath on the entry so we know how to remove it from the map\n  // if it gets evicted from the LRU.\n  pendingEntry.keypath = keypath\n  segmentCacheLru.put(pendingEntry)\n  return pendingEntry\n}\n\nexport function readOrCreateRevalidatingSegmentEntry(\n  now: number,\n  prevEntry: SegmentCacheEntry\n): SegmentCacheEntry {\n  const existingRevalidation = readRevalidatingSegmentCacheEntry(now, prevEntry)\n  if (existingRevalidation !== null) {\n    return existingRevalidation\n  }\n  const pendingEntry = createDetachedSegmentCacheEntry(prevEntry.staleAt)\n\n  // Background revalidations are not stored directly in the cache map or LRU;\n  // they're stashed on the entry that they will (potentially) replace.\n  //\n  // Note that we don't actually ever clear this field, except when the entry\n  // expires. When the revalidation finishes, one of two things will happen:\n  //\n  //  1) the revalidation is successful, `prevEntry` is removed from the cache\n  //     and garbage collected (so there's no point clearing any of its fields)\n  //  2) the revalidation fails, and we'll use the `revalidating` field to\n  //     prevent subsequent revalidation attempts, until it expires.\n  prevEntry.revalidating = pendingEntry\n\n  return pendingEntry\n}\n\nexport function upsertSegmentEntry(\n  now: number,\n  keypath: Prefix<SegmentCacheKeypath>,\n  candidateEntry: SegmentCacheEntry\n): SegmentCacheEntry | null {\n  // We have a new entry that has not yet been inserted into the cache. Before\n  // we do so, we need to confirm whether it takes precedence over the existing\n  // entry (if one exists).\n  // TODO: We should not upsert an entry if its key was invalidated in the time\n  // since the request was made. We can do that by passing the \"owner\" entry to\n  // this function and confirming it's the same as `existingEntry`.\n  const existingEntry = readExactSegmentCacheEntry(now, keypath)\n  if (existingEntry !== null) {\n    // Don't replace a more specific segment with a less-specific one. A case where this\n    // might happen is if the existing segment was fetched via\n    // `<Link prefetch={true}>`.\n    if (\n      // We fetched the new segment using a different, less specific fetch strategy\n      // than the segment we already have in the cache, so it can't have more content.\n      (candidateEntry.fetchStrategy !== existingEntry.fetchStrategy &&\n        !canNewFetchStrategyProvideMoreContent(\n          existingEntry.fetchStrategy,\n          candidateEntry.fetchStrategy\n        )) ||\n      // The existing entry isn't partial, but the new one is.\n      // (TODO: can this be true if `candidateEntry.fetchStrategy >= existingEntry.fetchStrategy`?)\n      (!existingEntry.isPartial && candidateEntry.isPartial)\n    ) {\n      // We're going to leave the entry on the owner's `revalidating` field\n      // so that it doesn't get revalidated again unnecessarily. Downgrade the\n      // Fulfilled entry to Rejected and null out the data so it can be garbage\n      // collected. We leave `staleAt` intact to prevent subsequent revalidation\n      // attempts only until the entry expires.\n      const rejectedEntry: RejectedSegmentCacheEntry = candidateEntry as any\n      rejectedEntry.status = EntryStatus.Rejected\n      rejectedEntry.loading = null\n      rejectedEntry.rsc = null\n      return null\n    }\n\n    // Evict the existing entry from the cache.\n    deleteSegmentFromCache(existingEntry, keypath)\n  }\n  segmentCacheMap.set(keypath, candidateEntry)\n  // Stash the keypath on the entry so we know how to remove it from the map\n  // if it gets evicted from the LRU.\n  candidateEntry.keypath = keypath\n  segmentCacheLru.put(candidateEntry)\n  return candidateEntry\n}\n\nexport function createDetachedSegmentCacheEntry(\n  staleAt: number\n): EmptySegmentCacheEntry {\n  const emptyEntry: EmptySegmentCacheEntry = {\n    status: EntryStatus.Empty,\n    // Default to assuming the fetch strategy will be PPR. This will be updated\n    // when a fetch is actually initiated.\n    fetchStrategy: FetchStrategy.PPR,\n    revalidating: null,\n    rsc: null,\n    loading: null,\n    staleAt,\n    isPartial: true,\n    promise: null,\n\n    // LRU-related fields\n    keypath: null,\n    next: null,\n    prev: null,\n    size: 0,\n  }\n  return emptyEntry\n}\n\nexport function upgradeToPendingSegment(\n  emptyEntry: EmptySegmentCacheEntry,\n  fetchStrategy: FetchStrategy\n): PendingSegmentCacheEntry {\n  const pendingEntry: PendingSegmentCacheEntry = emptyEntry as any\n  pendingEntry.status = EntryStatus.Pending\n  pendingEntry.fetchStrategy = fetchStrategy\n  return pendingEntry\n}\n\nfunction deleteRouteFromCache(\n  entry: RouteCacheEntry,\n  keypath: Prefix<RouteCacheKeypath>\n): void {\n  pingBlockedTasks(entry)\n  routeCacheMap.delete(keypath)\n  routeCacheLru.delete(entry)\n}\n\nfunction deleteSegmentFromCache(\n  entry: SegmentCacheEntry,\n  keypath: Prefix<SegmentCacheKeypath>\n): void {\n  cancelEntryListeners(entry)\n  segmentCacheMap.delete(keypath)\n  segmentCacheLru.delete(entry)\n  clearRevalidatingSegmentFromOwner(entry)\n}\n\nfunction clearRevalidatingSegmentFromOwner(owner: SegmentCacheEntry): void {\n  // Revalidating segments are not stored in the cache directly; they're\n  // stored as a field on the entry that they will (potentially) replace. So\n  // to dispose of an existing revalidation, we just need to null out the field\n  // on the owner.\n  const revalidatingSegment = owner.revalidating\n  if (revalidatingSegment !== null) {\n    cancelEntryListeners(revalidatingSegment)\n    owner.revalidating = null\n  }\n}\n\nexport function resetRevalidatingSegmentEntry(\n  owner: SegmentCacheEntry\n): EmptySegmentCacheEntry {\n  clearRevalidatingSegmentFromOwner(owner)\n  const emptyEntry = createDetachedSegmentCacheEntry(owner.staleAt)\n  owner.revalidating = emptyEntry\n  return emptyEntry\n}\n\nfunction onRouteLRUEviction(entry: RouteCacheEntry): void {\n  // The LRU evicted this entry. Remove it from the map.\n  const keypath = entry.keypath\n  if (keypath !== null) {\n    entry.keypath = null\n    pingBlockedTasks(entry)\n    routeCacheMap.delete(keypath)\n  }\n}\n\nfunction onSegmentLRUEviction(entry: SegmentCacheEntry): void {\n  // The LRU evicted this entry. Remove it from the map.\n  const keypath = entry.keypath\n  if (keypath !== null) {\n    entry.keypath = null\n    cancelEntryListeners(entry)\n    segmentCacheMap.delete(keypath)\n  }\n}\n\nfunction cancelEntryListeners(entry: SegmentCacheEntry): void {\n  if (entry.status === EntryStatus.Pending && entry.promise !== null) {\n    // There were listeners for this entry. Resolve them with `null` to indicate\n    // that the prefetch failed. It's up to the listener to decide how to handle\n    // this case.\n    // NOTE: We don't currently propagate the reason the prefetch was canceled\n    // but we could by accepting a `reason` argument.\n    entry.promise.resolve(null)\n    entry.promise = null\n  }\n}\n\nfunction pingBlockedTasks(entry: {\n  blockedTasks: Set<PrefetchTask> | null\n}): void {\n  const blockedTasks = entry.blockedTasks\n  if (blockedTasks !== null) {\n    for (const task of blockedTasks) {\n      pingPrefetchTask(task)\n    }\n    entry.blockedTasks = null\n  }\n}\n\nfunction fulfillRouteCacheEntry(\n  entry: RouteCacheEntry,\n  tree: RouteTree,\n  head: HeadData,\n  isHeadPartial: boolean,\n  staleAt: number,\n  couldBeIntercepted: boolean,\n  canonicalUrl: string,\n  renderedSearch: NormalizedSearch,\n  isPPREnabled: boolean,\n  isHeadDynamic: boolean\n): FulfilledRouteCacheEntry {\n  const fulfilledEntry: FulfilledRouteCacheEntry = entry as any\n  fulfilledEntry.status = EntryStatus.Fulfilled\n  fulfilledEntry.tree = tree\n  fulfilledEntry.head = head\n  fulfilledEntry.isHeadPartial = isHeadPartial\n  fulfilledEntry.staleAt = staleAt\n  fulfilledEntry.couldBeIntercepted = couldBeIntercepted\n  fulfilledEntry.canonicalUrl = canonicalUrl\n  fulfilledEntry.renderedSearch = renderedSearch\n  fulfilledEntry.isPPREnabled = isPPREnabled\n  fulfilledEntry.TODO_isHeadDynamic = isHeadDynamic\n  pingBlockedTasks(entry)\n  return fulfilledEntry\n}\n\nfunction fulfillSegmentCacheEntry(\n  segmentCacheEntry: PendingSegmentCacheEntry,\n  rsc: React.ReactNode,\n  loading: LoadingModuleData | Promise<LoadingModuleData>,\n  staleAt: number,\n  isPartial: boolean\n): FulfilledSegmentCacheEntry {\n  const fulfilledEntry: FulfilledSegmentCacheEntry = segmentCacheEntry as any\n  fulfilledEntry.status = EntryStatus.Fulfilled\n  fulfilledEntry.rsc = rsc\n  fulfilledEntry.loading = loading\n  fulfilledEntry.staleAt = staleAt\n  fulfilledEntry.isPartial = isPartial\n  // Resolve any listeners that were waiting for this data.\n  if (segmentCacheEntry.promise !== null) {\n    segmentCacheEntry.promise.resolve(fulfilledEntry)\n    // Free the promise for garbage collection.\n    fulfilledEntry.promise = null\n  }\n  return fulfilledEntry\n}\n\nfunction rejectRouteCacheEntry(\n  entry: PendingRouteCacheEntry,\n  staleAt: number\n): void {\n  const rejectedEntry: RejectedRouteCacheEntry = entry as any\n  rejectedEntry.status = EntryStatus.Rejected\n  rejectedEntry.staleAt = staleAt\n  pingBlockedTasks(entry)\n}\n\nfunction rejectSegmentCacheEntry(\n  entry: PendingSegmentCacheEntry,\n  staleAt: number\n): void {\n  const rejectedEntry: RejectedSegmentCacheEntry = entry as any\n  rejectedEntry.status = EntryStatus.Rejected\n  rejectedEntry.staleAt = staleAt\n  if (entry.promise !== null) {\n    // NOTE: We don't currently propagate the reason the prefetch was canceled\n    // but we could by accepting a `reason` argument.\n    entry.promise.resolve(null)\n    entry.promise = null\n  }\n}\n\nfunction convertRootTreePrefetchToRouteTree(\n  rootTree: RootTreePrefetch,\n  renderedPathname: string\n) {\n  // Remove trailing and leading slashes\n  const pathnameParts = renderedPathname.split('/').filter((p) => p !== '')\n  const index = 0\n  const rootSegment = ROOT_SEGMENT_CACHE_KEY\n  return convertTreePrefetchToRouteTree(\n    rootTree.tree,\n    rootSegment,\n    null,\n    ROOT_SEGMENT_REQUEST_KEY,\n    ROOT_SEGMENT_CACHE_KEY,\n    pathnameParts,\n    index\n  )\n}\n\nfunction convertTreePrefetchToRouteTree(\n  prefetch: TreePrefetch,\n  segment: FlightRouterStateSegment,\n  param: RouteParam | null,\n  requestKey: SegmentRequestKey,\n  cacheKey: SegmentCacheKey,\n  pathnameParts: Array<string>,\n  pathnamePartsIndex: number\n): RouteTree {\n  // Converts the route tree sent by the server into the format used by the\n  // cache. The cached version of the tree includes additional fields, such as a\n  // cache key for each segment. Since this is frequently accessed, we compute\n  // it once instead of on every access. This same cache key is also used to\n  // request the segment from the server.\n\n  let slots: { [parallelRouteKey: string]: RouteTree } | null = null\n  const prefetchSlots = prefetch.slots\n  if (prefetchSlots !== null) {\n    slots = {}\n    for (let parallelRouteKey in prefetchSlots) {\n      const childPrefetch = prefetchSlots[parallelRouteKey]\n      const childParamName = childPrefetch.name\n      const childParamType = childPrefetch.paramType\n      const childServerSentParamKey = childPrefetch.paramKey\n\n      let childDoesAppearInURL: boolean\n      let childParam: RouteParam | null = null\n      let childSegment: FlightRouterStateSegment\n      if (childParamType !== null) {\n        // This segment is parameterized. Get the param from the pathname.\n        const childParamValue = parseDynamicParamFromURLPart(\n          childParamType,\n          pathnameParts,\n          pathnamePartsIndex\n        )\n\n        // Assign a cache key to the segment, based on the param value. In the\n        // pre-Segment Cache implementation, the server computes this and sends\n        // it in the body of the response. In the Segment Cache implementation,\n        // the server sends an empty string and we fill it in here.\n\n        // TODO: We're intentionally not adding the search param to page\n        // segments here; it's tracked separately and added back during a read.\n        // This would clearer if we waited to construct the segment until it's\n        // read from the cache, since that's effectively what we're\n        // doing anyway.\n        const renderedSearch = '' as NormalizedSearch\n        const childParamKey =\n          // The server omits this field from the prefetch response when\n          // clientParamParsing is enabled. The flag only exists while we're\n          // testing the feature, in case there's a bug and we need to revert.\n          // TODO: Remove once clientParamParsing is enabled everywhere.\n          childServerSentParamKey !== null\n            ? childServerSentParamKey\n            : // If no param key was sent, use the value parsed on the client.\n              getCacheKeyForDynamicParam(childParamValue, renderedSearch)\n\n        childParam = {\n          name: childParamName,\n          value: childParamValue,\n          type: childParamType,\n        }\n        childSegment = [childParamName, childParamKey, childParamType]\n        childDoesAppearInURL = true\n      } else {\n        childSegment = childParamName\n        childDoesAppearInURL = doesStaticSegmentAppearInURL(childParamName)\n      }\n\n      // Only increment the index if the segment appears in the URL. If it's a\n      // \"virtual\" segment, like a route group, it remains the same.\n      const childPathnamePartsIndex = childDoesAppearInURL\n        ? pathnamePartsIndex + 1\n        : pathnamePartsIndex\n\n      const childRequestKeyPart = createSegmentRequestKeyPart(childSegment)\n      const childRequestKey = appendSegmentRequestKeyPart(\n        requestKey,\n        parallelRouteKey,\n        childRequestKeyPart\n      )\n      const childCacheKey = appendSegmentCacheKeyPart(\n        cacheKey,\n        parallelRouteKey,\n        createSegmentCacheKeyPart(childRequestKeyPart, childSegment)\n      )\n      slots[parallelRouteKey] = convertTreePrefetchToRouteTree(\n        childPrefetch,\n        childSegment,\n        childParam,\n        childRequestKey,\n        childCacheKey,\n        pathnameParts,\n        childPathnamePartsIndex\n      )\n    }\n  }\n\n  return {\n    cacheKey,\n    requestKey,\n    segment,\n    param,\n    slots,\n    isRootLayout: prefetch.isRootLayout,\n    // This field is only relevant to dynamic routes. For a PPR/static route,\n    // there's always some partial loading state we can fetch.\n    hasLoadingBoundary: HasLoadingBoundary.SegmentHasLoadingBoundary,\n  }\n}\n\nfunction convertRootFlightRouterStateToRouteTree(\n  flightRouterState: FlightRouterState\n): RouteTree {\n  return convertFlightRouterStateToRouteTree(\n    flightRouterState,\n    ROOT_SEGMENT_CACHE_KEY,\n    ROOT_SEGMENT_REQUEST_KEY\n  )\n}\n\nfunction convertFlightRouterStateToRouteTree(\n  flightRouterState: FlightRouterState,\n  cacheKey: SegmentCacheKey,\n  requestKey: SegmentRequestKey\n): RouteTree {\n  let slots: { [parallelRouteKey: string]: RouteTree } | null = null\n\n  const parallelRoutes = flightRouterState[1]\n  for (let parallelRouteKey in parallelRoutes) {\n    const childRouterState = parallelRoutes[parallelRouteKey]\n    const childSegment = childRouterState[0]\n    // TODO: Eventually, the param values will not be included in the response\n    // from the server. We'll instead fill them in on the client by parsing\n    // the URL. This is where we'll do that.\n    const childRequestKeyPart = createSegmentRequestKeyPart(childSegment)\n    const childRequestKey = appendSegmentRequestKeyPart(\n      requestKey,\n      parallelRouteKey,\n      childRequestKeyPart\n    )\n    const childCacheKey = appendSegmentCacheKeyPart(\n      cacheKey,\n      parallelRouteKey,\n      createSegmentCacheKeyPart(childRequestKeyPart, childSegment)\n    )\n    const childTree = convertFlightRouterStateToRouteTree(\n      childRouterState,\n      childCacheKey,\n      childRequestKey\n    )\n    if (slots === null) {\n      slots = {\n        [parallelRouteKey]: childTree,\n      }\n    } else {\n      slots[parallelRouteKey] = childTree\n    }\n  }\n  const originalSegment = flightRouterState[0]\n\n  let segment: FlightRouterStateSegment\n  let param: RouteParam | null = null\n  if (Array.isArray(originalSegment)) {\n    const paramCacheKey = originalSegment[1]\n    const paramType = originalSegment[2]\n    const paramValue = getParamValueFromCacheKey(paramCacheKey, paramType)\n    param = {\n      name: originalSegment[0],\n      value: paramValue === undefined ? null : paramValue,\n      type: originalSegment[2] as DynamicParamTypesShort,\n    }\n    segment = originalSegment\n  } else {\n    // The navigation implementation expects the search params to be included\n    // in the segment. However, in the case of a static response, the search\n    // params are omitted. So the client needs to add them back in when reading\n    // from the Segment Cache.\n    //\n    // For consistency, we'll do this for dynamic responses, too.\n    //\n    // TODO: We should move search params out of FlightRouterState and handle\n    // them entirely on the client, similar to our plan for dynamic params.\n    segment =\n      typeof originalSegment === 'string' &&\n      originalSegment.startsWith(PAGE_SEGMENT_KEY)\n        ? PAGE_SEGMENT_KEY\n        : originalSegment\n  }\n\n  return {\n    cacheKey,\n    requestKey,\n    segment,\n    param,\n    slots,\n    isRootLayout: flightRouterState[4] === true,\n    hasLoadingBoundary:\n      flightRouterState[5] !== undefined\n        ? flightRouterState[5]\n        : HasLoadingBoundary.SubtreeHasNoLoadingBoundary,\n  }\n}\n\nexport function convertRouteTreeToFlightRouterState(\n  routeTree: RouteTree\n): FlightRouterState {\n  const parallelRoutes: Record<string, FlightRouterState> = {}\n  if (routeTree.slots !== null) {\n    for (const parallelRouteKey in routeTree.slots) {\n      parallelRoutes[parallelRouteKey] = convertRouteTreeToFlightRouterState(\n        routeTree.slots[parallelRouteKey]\n      )\n    }\n  }\n  const flightRouterState: FlightRouterState = [\n    routeTree.segment,\n    parallelRoutes,\n    null,\n    null,\n    routeTree.isRootLayout,\n  ]\n  return flightRouterState\n}\n\nexport async function fetchRouteOnCacheMiss(\n  entry: PendingRouteCacheEntry,\n  task: PrefetchTask\n): Promise<PrefetchSubtaskResult<null> | null> {\n  // This function is allowed to use async/await because it contains the actual\n  // fetch that gets issued on a cache miss. Notice it writes the result to the\n  // cache entry directly, rather than return data that is then written by\n  // the caller.\n  const key = task.key\n  const href = key.href\n  const nextUrl = key.nextUrl\n  const segmentPath = '/_tree' as SegmentRequestKey\n\n  const headers: RequestHeaders = {\n    [RSC_HEADER]: '1',\n    [NEXT_ROUTER_PREFETCH_HEADER]: '1',\n    [NEXT_ROUTER_SEGMENT_PREFETCH_HEADER]: segmentPath,\n  }\n  if (nextUrl !== null) {\n    headers[NEXT_URL] = nextUrl\n  }\n\n  try {\n    let response\n    let urlAfterRedirects\n    if (isOutputExportMode) {\n      // In output: \"export\" mode, we can't use headers to request a particular\n      // segment. Instead, we encode the extra request information into the URL.\n      // This is not part of the \"public\" interface of the app; it's an internal\n      // Next.js implementation detail that the app developer should not need to\n      // concern themselves with.\n      //\n      // For example, to request a segment:\n      //\n      //   Path passed to <Link>:   /path/to/page\n      //   Path passed to fetch:    /path/to/page/__next-segments/_tree\n      //\n      //   (This is not the exact protocol, just an illustration.)\n      //\n      // Before we do that, though, we need to account for redirects. Even in\n      // output: \"export\" mode, a proxy might redirect the page to a different\n      // location, but we shouldn't assume or expect that they also redirect all\n      // the segment files, too.\n      //\n      // To check whether the page is redirected, we perform a range request of\n      // the first N bytes of the HTML document. The canonical URL is determined\n      // from the response.\n      //\n      // Then we can use the canonical URL to request the route tree.\n      //\n      // NOTE: We could embed the route tree into the HTML document, to avoid\n      // a second request. We're not doing that currently because it would make\n      // the HTML document larger and affect normal page loads.\n      const url = new URL(href)\n      const htmlResponse = await fetch(href, {\n        headers: {\n          Range: DOC_PREFETCH_RANGE_HEADER_VALUE,\n        },\n      })\n      const partialHtml = await htmlResponse.text()\n      if (!doesExportedHtmlMatchBuildId(partialHtml, getAppBuildId())) {\n        // The target page is not part of this app, or it belongs to a\n        // different build.\n        rejectRouteCacheEntry(entry, Date.now() + 10 * 1000)\n        return null\n      }\n      urlAfterRedirects = htmlResponse.redirected\n        ? new URL(htmlResponse.url)\n        : url\n      response = await fetchPrefetchResponse(\n        addSegmentPathToUrlInOutputExportMode(urlAfterRedirects, segmentPath),\n        headers\n      )\n    } else {\n      // \"Server\" mode. We can use request headers instead of the pathname.\n      // TODO: The eventual plan is to get rid of our custom request headers and\n      // encode everything into the URL, using a similar strategy to the\n      // \"output: export\" block above.\n      const url = new URL(href)\n      response = await fetchPrefetchResponse(url, headers)\n      urlAfterRedirects =\n        response !== null && response.redirected ? new URL(response.url) : url\n    }\n\n    if (\n      !response ||\n      !response.ok ||\n      // 204 is a Cache miss. Though theoretically this shouldn't happen when\n      // PPR is enabled, because we always respond to route tree requests, even\n      // if it needs to be blockingly generated on demand.\n      response.status === 204 ||\n      !response.body\n    ) {\n      // Server responded with an error, or with a miss. We should still cache\n      // the response, but we can try again after 10 seconds.\n      rejectRouteCacheEntry(entry, Date.now() + 10 * 1000)\n      return null\n    }\n\n    // TODO: The canonical URL is the href without the origin. I think\n    // historically the reason for this is because the initial canonical URL\n    // gets passed as a prop to the top-level React component, which means it\n    // needs to be computed during SSR. If it were to include the origin, it\n    // would need to always be same as location.origin on the client, to prevent\n    // a hydration mismatch. To sidestep this complexity, we omit the origin.\n    //\n    // However, since this is neither a native URL object nor a fully qualified\n    // URL string, we need to be careful about how we use it. To prevent subtle\n    // mistakes, we should create a special type for it, instead of just string.\n    // Or, we should just use a (readonly) URL object instead. The type of the\n    // prop that we pass to seed the initial state does not need to be the same\n    // type as the state itself.\n    const canonicalUrl = createHrefFromUrl(urlAfterRedirects)\n\n    // Check whether the response varies based on the Next-Url header.\n    const varyHeader = response.headers.get('vary')\n    const couldBeIntercepted =\n      varyHeader !== null && varyHeader.includes(NEXT_URL)\n\n    // Track when the network connection closes.\n    const closed = createPromiseWithResolvers<void>()\n\n    // This checks whether the response was served from the per-segment cache,\n    // rather than the old prefetching flow. If it fails, it implies that PPR\n    // is disabled on this route.\n    const routeIsPPREnabled =\n      response.headers.get(NEXT_DID_POSTPONE_HEADER) === '2' ||\n      // In output: \"export\" mode, we can't rely on response headers. But if we\n      // receive a well-formed response, we can assume it's a static response,\n      // because all data is static in this mode.\n      isOutputExportMode\n\n    // Regardless of the type of response, we will never receive dynamic\n    // metadata as part of this prefetch request.\n    const isHeadDynamic = false\n\n    if (routeIsPPREnabled) {\n      const prefetchStream = createPrefetchResponseStream(\n        response.body,\n        closed.resolve,\n        function onResponseSizeUpdate(size) {\n          routeCacheLru.updateSize(entry, size)\n        }\n      )\n      const serverData = await (createFromNextReadableStream(\n        prefetchStream\n      ) as Promise<RootTreePrefetch>)\n      if (serverData.buildId !== getAppBuildId()) {\n        // The server build does not match the client. Treat as a 404. During\n        // an actual navigation, the router will trigger an MPA navigation.\n        // TODO: Consider moving the build ID to a response header so we can check\n        // it before decoding the response, and so there's one way of checking\n        // across all response types.\n        // TODO: We should cache the fact that this is an MPA navigation.\n        rejectRouteCacheEntry(entry, Date.now() + 10 * 1000)\n        return null\n      }\n\n      // Get the params that were used to render the target page. These may\n      // be different from the params in the request URL, if the page\n      // was rewritten.\n      const renderedPathname = getRenderedPathname(response)\n      const renderedSearch = getRenderedSearch(response)\n\n      const routeTree = convertRootTreePrefetchToRouteTree(\n        serverData,\n        renderedPathname\n      )\n\n      const staleTimeMs = getStaleTimeMs(serverData.staleTime)\n      fulfillRouteCacheEntry(\n        entry,\n        routeTree,\n        serverData.head,\n        serverData.isHeadPartial,\n        Date.now() + staleTimeMs,\n        couldBeIntercepted,\n        canonicalUrl,\n        renderedSearch,\n        routeIsPPREnabled,\n        isHeadDynamic\n      )\n    } else {\n      // PPR is not enabled for this route. The server responds with a\n      // different format (FlightRouterState) that we need to convert.\n      // TODO: We will unify the responses eventually. I'm keeping the types\n      // separate for now because FlightRouterState has so many\n      // overloaded concerns.\n      const prefetchStream = createPrefetchResponseStream(\n        response.body,\n        closed.resolve,\n        function onResponseSizeUpdate(size) {\n          routeCacheLru.updateSize(entry, size)\n        }\n      )\n      const serverData = await (createFromNextReadableStream(\n        prefetchStream\n      ) as Promise<NavigationFlightResponse>)\n      if (serverData.b !== getAppBuildId()) {\n        // The server build does not match the client. Treat as a 404. During\n        // an actual navigation, the router will trigger an MPA navigation.\n        // TODO: Consider moving the build ID to a response header so we can check\n        // it before decoding the response, and so there's one way of checking\n        // across all response types.\n        // TODO: We should cache the fact that this is an MPA navigation.\n        rejectRouteCacheEntry(entry, Date.now() + 10 * 1000)\n        return null\n      }\n\n      writeDynamicTreeResponseIntoCache(\n        Date.now(),\n        task,\n        // The non-PPR response format is what we'd get if we prefetched these segments\n        // using the LoadingBoundary fetch strategy, so mark their cache entries accordingly.\n        FetchStrategy.LoadingBoundary,\n        response,\n        serverData,\n        entry,\n        couldBeIntercepted,\n        canonicalUrl,\n        routeIsPPREnabled\n      )\n    }\n\n    if (!couldBeIntercepted && nextUrl !== null) {\n      // This route will never be intercepted. So we can use this entry for all\n      // requests to this route, regardless of the Next-Url header. This works\n      // because when reading the cache we always check for a valid\n      // non-intercepted entry first.\n      //\n      // Re-key the entry. Since we're in an async task, we must first confirm\n      // that the entry hasn't been concurrently modified by a different task.\n      const currentKeypath: Prefix<RouteCacheKeypath> = [href, nextUrl]\n      const expectedEntry = routeCacheMap.get(currentKeypath)\n      if (expectedEntry === entry) {\n        routeCacheMap.delete(currentKeypath)\n        const newKeypath: Prefix<RouteCacheKeypath> = [href]\n        routeCacheMap.set(newKeypath, entry)\n        // We don't need to update the LRU because the entry is already in it.\n        // But since we changed the keypath, we do need to update that, so we\n        // know how to remove it from the map if it gets evicted from the LRU.\n        entry.keypath = newKeypath\n      } else {\n        // Something else modified this entry already. Since the re-keying is\n        // just a performance optimization, we can safely skip it.\n      }\n    }\n    // Return a promise that resolves when the network connection closes, so\n    // the scheduler can track the number of concurrent network connections.\n    return { value: null, closed: closed.promise }\n  } catch (error) {\n    // Either the connection itself failed, or something bad happened while\n    // decoding the response.\n    rejectRouteCacheEntry(entry, Date.now() + 10 * 1000)\n    return null\n  }\n}\n\nexport async function fetchSegmentOnCacheMiss(\n  route: FulfilledRouteCacheEntry,\n  segmentCacheEntry: PendingSegmentCacheEntry,\n  routeKey: RouteCacheKey,\n  tree: RouteTree\n): Promise<PrefetchSubtaskResult<FulfilledSegmentCacheEntry> | null> {\n  // This function is allowed to use async/await because it contains the actual\n  // fetch that gets issued on a cache miss. Notice it writes the result to the\n  // cache entry directly, rather than return data that is then written by\n  // the caller.\n  //\n  // Segment fetches are non-blocking so we don't need to ping the scheduler\n  // on completion.\n\n  // Use the canonical URL to request the segment, not the original URL. These\n  // are usually the same, but the canonical URL will be different if the route\n  // tree response was redirected. To avoid an extra waterfall on every segment\n  // request, we pass the redirected URL instead of the original one.\n  const url = new URL(route.canonicalUrl, routeKey.href)\n  const nextUrl = routeKey.nextUrl\n\n  const requestKey = tree.requestKey\n  const normalizedRequestKey =\n    requestKey === ROOT_SEGMENT_REQUEST_KEY\n      ? // The root segment is a special case. To simplify the server-side\n        // handling of these requests, we encode the root segment path as\n        // `_index` instead of as an empty string. This should be treated as\n        // an implementation detail and not as a stable part of the protocol.\n        // It just needs to match the equivalent logic that happens when\n        // prerendering the responses. It should not leak outside of Next.js.\n        ('/_index' as SegmentRequestKey)\n      : requestKey\n\n  const headers: RequestHeaders = {\n    [RSC_HEADER]: '1',\n    [NEXT_ROUTER_PREFETCH_HEADER]: '1',\n    [NEXT_ROUTER_SEGMENT_PREFETCH_HEADER]: normalizedRequestKey,\n  }\n  if (nextUrl !== null) {\n    headers[NEXT_URL] = nextUrl\n  }\n\n  const requestUrl = isOutputExportMode\n    ? // In output: \"export\" mode, we need to add the segment path to the URL.\n      addSegmentPathToUrlInOutputExportMode(url, normalizedRequestKey)\n    : url\n  try {\n    const response = await fetchPrefetchResponse(requestUrl, headers)\n    if (\n      !response ||\n      !response.ok ||\n      response.status === 204 || // Cache miss\n      // This checks whether the response was served from the per-segment cache,\n      // rather than the old prefetching flow. If it fails, it implies that PPR\n      // is disabled on this route. Theoretically this should never happen\n      // because we only issue requests for segments once we've verified that\n      // the route supports PPR.\n      (response.headers.get(NEXT_DID_POSTPONE_HEADER) !== '2' &&\n        // In output: \"export\" mode, we can't rely on response headers. But if\n        // we receive a well-formed response, we can assume it's a static\n        // response, because all data is static in this mode.\n        !isOutputExportMode) ||\n      !response.body\n    ) {\n      // Server responded with an error, or with a miss. We should still cache\n      // the response, but we can try again after 10 seconds.\n      rejectSegmentCacheEntry(segmentCacheEntry, Date.now() + 10 * 1000)\n      return null\n    }\n\n    // Track when the network connection closes.\n    const closed = createPromiseWithResolvers<void>()\n\n    // Wrap the original stream in a new stream that never closes. That way the\n    // Flight client doesn't error if there's a hanging promise.\n    const prefetchStream = createPrefetchResponseStream(\n      response.body,\n      closed.resolve,\n      function onResponseSizeUpdate(size) {\n        segmentCacheLru.updateSize(segmentCacheEntry, size)\n      }\n    )\n    const serverData = await (createFromNextReadableStream(\n      prefetchStream\n    ) as Promise<SegmentPrefetch>)\n    if (serverData.buildId !== getAppBuildId()) {\n      // The server build does not match the client. Treat as a 404. During\n      // an actual navigation, the router will trigger an MPA navigation.\n      // TODO: Consider moving the build ID to a response header so we can check\n      // it before decoding the response, and so there's one way of checking\n      // across all response types.\n      rejectSegmentCacheEntry(segmentCacheEntry, Date.now() + 10 * 1000)\n      return null\n    }\n    return {\n      value: fulfillSegmentCacheEntry(\n        segmentCacheEntry,\n        serverData.rsc,\n        serverData.loading,\n        // TODO: The server does not currently provide per-segment stale time.\n        // So we use the stale time of the route.\n        route.staleAt,\n        serverData.isPartial\n      ),\n      // Return a promise that resolves when the network connection closes, so\n      // the scheduler can track the number of concurrent network connections.\n      closed: closed.promise,\n    }\n  } catch (error) {\n    // Either the connection itself failed, or something bad happened while\n    // decoding the response.\n    rejectSegmentCacheEntry(segmentCacheEntry, Date.now() + 10 * 1000)\n    return null\n  }\n}\n\nexport async function fetchSegmentPrefetchesUsingDynamicRequest(\n  task: PrefetchTask,\n  route: FulfilledRouteCacheEntry,\n  fetchStrategy:\n    | FetchStrategy.LoadingBoundary\n    | FetchStrategy.PPRRuntime\n    | FetchStrategy.Full,\n  dynamicRequestTree: FlightRouterState,\n  spawnedEntries: Map<SegmentCacheKey, PendingSegmentCacheEntry>\n): Promise<PrefetchSubtaskResult<null> | null> {\n  const url = new URL(route.canonicalUrl, task.key.href)\n  const nextUrl = task.key.nextUrl\n  const headers: RequestHeaders = {\n    [RSC_HEADER]: '1',\n    [NEXT_ROUTER_STATE_TREE_HEADER]: encodeURIComponent(\n      JSON.stringify(dynamicRequestTree)\n    ),\n  }\n  if (nextUrl !== null) {\n    headers[NEXT_URL] = nextUrl\n  }\n  switch (fetchStrategy) {\n    case FetchStrategy.Full: {\n      // We omit the prefetch header from a full prefetch because it's essentially\n      // just a navigation request that happens ahead of time — it should include\n      // all the same data in the response.\n      break\n    }\n    case FetchStrategy.PPRRuntime: {\n      headers[NEXT_ROUTER_PREFETCH_HEADER] = '2'\n      break\n    }\n    case FetchStrategy.LoadingBoundary: {\n      headers[NEXT_ROUTER_PREFETCH_HEADER] = '1'\n      break\n    }\n    default: {\n      fetchStrategy satisfies never\n    }\n  }\n\n  try {\n    const response = await fetchPrefetchResponse(url, headers)\n    if (!response || !response.ok || !response.body) {\n      // Server responded with an error, or with a miss. We should still cache\n      // the response, but we can try again after 10 seconds.\n      rejectSegmentEntriesIfStillPending(spawnedEntries, Date.now() + 10 * 1000)\n      return null\n    }\n\n    const renderedSearch = getRenderedSearch(response)\n    if (renderedSearch !== route.renderedSearch) {\n      // The search params that were used to render the target page are\n      // different from the search params in the request URL. This only happens\n      // when there's a dynamic rewrite in between the tree prefetch and the\n      // data prefetch.\n      // TODO: For now, since this is an edge case, we reject the prefetch, but\n      // the proper way to handle this is to evict the stale route tree entry\n      // then fill the cache with the new response.\n      rejectSegmentEntriesIfStillPending(spawnedEntries, Date.now() + 10 * 1000)\n      return null\n    }\n\n    // Track when the network connection closes.\n    const closed = createPromiseWithResolvers<void>()\n\n    let fulfilledEntries: Array<FulfilledSegmentCacheEntry> | null = null\n    const prefetchStream = createPrefetchResponseStream(\n      response.body,\n      closed.resolve,\n      function onResponseSizeUpdate(totalBytesReceivedSoFar) {\n        // When processing a dynamic response, we don't know how large each\n        // individual segment is, so approximate by assiging each segment\n        // the average of the total response size.\n        if (fulfilledEntries === null) {\n          // Haven't received enough data yet to know which segments\n          // were included.\n          return\n        }\n        const averageSize = totalBytesReceivedSoFar / fulfilledEntries.length\n        for (const entry of fulfilledEntries) {\n          segmentCacheLru.updateSize(entry, averageSize)\n        }\n      }\n    )\n    const serverData = await (createFromNextReadableStream(\n      prefetchStream\n    ) as Promise<NavigationFlightResponse>)\n\n    const isResponsePartial =\n      fetchStrategy === FetchStrategy.PPRRuntime\n        ? // A runtime prefetch may have holes.\n          !!response.headers.get(NEXT_DID_POSTPONE_HEADER)\n        : // Full and LoadingBoundary prefetches cannot have holes.\n          // (even if we did set the prefetch header, we only use this codepath for non-PPR-enabled routes)\n          false\n\n    // Aside from writing the data into the cache, this function also returns\n    // the entries that were fulfilled, so we can streamingly update their sizes\n    // in the LRU as more data comes in.\n    fulfilledEntries = writeDynamicRenderResponseIntoCache(\n      Date.now(),\n      task,\n      fetchStrategy,\n      response,\n      serverData,\n      isResponsePartial,\n      route,\n      spawnedEntries\n    )\n\n    // Return a promise that resolves when the network connection closes, so\n    // the scheduler can track the number of concurrent network connections.\n    return { value: null, closed: closed.promise }\n  } catch (error) {\n    rejectSegmentEntriesIfStillPending(spawnedEntries, Date.now() + 10 * 1000)\n    return null\n  }\n}\n\nfunction writeDynamicTreeResponseIntoCache(\n  now: number,\n  task: PrefetchTask,\n  fetchStrategy:\n    | FetchStrategy.LoadingBoundary\n    | FetchStrategy.PPRRuntime\n    | FetchStrategy.Full,\n  response: RSCResponse,\n  serverData: NavigationFlightResponse,\n  entry: PendingRouteCacheEntry,\n  couldBeIntercepted: boolean,\n  canonicalUrl: string,\n  routeIsPPREnabled: boolean\n) {\n  // Get the URL that was used to render the target page. This may be different\n  // from the URL in the request URL, if the page was rewritten.\n  const renderedSearch = getRenderedSearch(response)\n\n  const normalizedFlightDataResult = normalizeFlightData(serverData.f)\n  if (\n    // A string result means navigating to this route will result in an\n    // MPA navigation.\n    typeof normalizedFlightDataResult === 'string' ||\n    normalizedFlightDataResult.length !== 1\n  ) {\n    rejectRouteCacheEntry(entry, now + 10 * 1000)\n    return\n  }\n  const flightData = normalizedFlightDataResult[0]\n  if (!flightData.isRootRender) {\n    // Unexpected response format.\n    rejectRouteCacheEntry(entry, now + 10 * 1000)\n    return\n  }\n\n  const flightRouterState = flightData.tree\n  // TODO: Extract to function\n  const staleTimeHeaderSeconds = response.headers.get(\n    NEXT_ROUTER_STALE_TIME_HEADER\n  )\n  const staleTimeMs =\n    staleTimeHeaderSeconds !== null\n      ? getStaleTimeMs(parseInt(staleTimeHeaderSeconds, 10))\n      : STATIC_STALETIME_MS\n\n  // If the response contains dynamic holes, then we must conservatively assume\n  // that any individual segment might contain dynamic holes, and also the\n  // head. If it did not contain dynamic holes, then we can assume every segment\n  // and the head is completely static.\n  const isResponsePartial =\n    response.headers.get(NEXT_DID_POSTPONE_HEADER) === '1'\n\n  // Since this is a dynamic response, we must conservatively assume that the\n  // head responded with dynamic data.\n  const isHeadDynamic = true\n\n  const fulfilledEntry = fulfillRouteCacheEntry(\n    entry,\n    convertRootFlightRouterStateToRouteTree(flightRouterState),\n    flightData.head,\n    flightData.isHeadPartial,\n    now + staleTimeMs,\n    couldBeIntercepted,\n    canonicalUrl,\n    renderedSearch,\n    routeIsPPREnabled,\n    isHeadDynamic\n  )\n\n  // If the server sent segment data as part of the response, we should write\n  // it into the cache to prevent a second, redundant prefetch request.\n  //\n  // TODO: When `clientSegmentCache` is enabled, the server does not include\n  // segment data when responding to a route tree prefetch request. However,\n  // when `clientSegmentCache` is set to \"client-only\", and PPR is enabled (or\n  // the page is fully static), the normal check is bypassed and the server\n  // responds with the full page. This is a temporary situation until we can\n  // remove the \"client-only\" option. Then, we can delete this function call.\n  writeDynamicRenderResponseIntoCache(\n    now,\n    task,\n    fetchStrategy,\n    response,\n    serverData,\n    isResponsePartial,\n    fulfilledEntry,\n    null\n  )\n}\n\nfunction rejectSegmentEntriesIfStillPending(\n  entries: Map<SegmentCacheKey, SegmentCacheEntry>,\n  staleAt: number\n): Array<FulfilledSegmentCacheEntry> {\n  const fulfilledEntries = []\n  for (const entry of entries.values()) {\n    if (entry.status === EntryStatus.Pending) {\n      rejectSegmentCacheEntry(entry, staleAt)\n    } else if (entry.status === EntryStatus.Fulfilled) {\n      fulfilledEntries.push(entry)\n    }\n  }\n  return fulfilledEntries\n}\n\nfunction writeDynamicRenderResponseIntoCache(\n  now: number,\n  task: PrefetchTask,\n  fetchStrategy:\n    | FetchStrategy.LoadingBoundary\n    | FetchStrategy.PPRRuntime\n    | FetchStrategy.Full,\n  response: RSCResponse,\n  serverData: NavigationFlightResponse,\n  isResponsePartial: boolean,\n  route: FulfilledRouteCacheEntry,\n  spawnedEntries: Map<SegmentCacheKey, PendingSegmentCacheEntry> | null\n): Array<FulfilledSegmentCacheEntry> | null {\n  if (serverData.b !== getAppBuildId()) {\n    // The server build does not match the client. Treat as a 404. During\n    // an actual navigation, the router will trigger an MPA navigation.\n    // TODO: Consider moving the build ID to a response header so we can check\n    // it before decoding the response, and so there's one way of checking\n    // across all response types.\n    if (spawnedEntries !== null) {\n      rejectSegmentEntriesIfStillPending(spawnedEntries, now + 10 * 1000)\n    }\n    return null\n  }\n\n  const flightDatas = normalizeFlightData(serverData.f)\n  if (typeof flightDatas === 'string') {\n    // This means navigating to this route will result in an MPA navigation.\n    // TODO: We should cache this, too, so that the MPA navigation is immediate.\n    return null\n  }\n\n  const staleTimeHeaderSeconds = response.headers.get(\n    NEXT_ROUTER_STALE_TIME_HEADER\n  )\n  const staleTimeMs =\n    staleTimeHeaderSeconds !== null\n      ? getStaleTimeMs(parseInt(staleTimeHeaderSeconds, 10))\n      : STATIC_STALETIME_MS\n  const staleAt = now + staleTimeMs\n\n  for (const flightData of flightDatas) {\n    const seedData = flightData.seedData\n    if (seedData !== null) {\n      // The data sent by the server represents only a subtree of the app. We\n      // need to find the part of the task tree that matches the response.\n      //\n      // segmentPath represents the parent path of subtree. It's a repeating\n      // pattern of parallel route key and segment:\n      //\n      //   [string, Segment, string, Segment, string, Segment, ...]\n      const segmentPath = flightData.segmentPath\n      let requestKey = ROOT_SEGMENT_REQUEST_KEY\n      let cacheKey = ROOT_SEGMENT_CACHE_KEY\n      for (let i = 0; i < segmentPath.length; i += 2) {\n        const parallelRouteKey: string = segmentPath[i]\n        const segment: FlightRouterStateSegment = segmentPath[i + 1]\n        const requestKeyPart = createSegmentRequestKeyPart(segment)\n        requestKey = appendSegmentRequestKeyPart(\n          requestKey,\n          parallelRouteKey,\n          requestKeyPart\n        )\n        cacheKey = appendSegmentCacheKeyPart(\n          cacheKey,\n          parallelRouteKey,\n          createSegmentCacheKeyPart(requestKeyPart, segment)\n        )\n      }\n\n      writeSeedDataIntoCache(\n        now,\n        task,\n        fetchStrategy,\n        route,\n        staleAt,\n        seedData,\n        isResponsePartial,\n        cacheKey,\n        requestKey,\n        spawnedEntries\n      )\n    }\n\n    // During a dynamic request, the server sends back new head data for the\n    // page. Overwrite the existing head with the new one. Note that we're\n    // intentionally not taking into account whether the existing head is\n    // already complete, even though the incoming head might not have finished\n    // streaming in yet. This is to prioritize consistency of the head with\n    // the segment data (though it's still not a guarantee, since some of the\n    // segment data may be reused from a previous request).\n    route.head = flightData.head\n    route.isHeadPartial = flightData.isHeadPartial\n    route.TODO_isHeadDynamic = true\n\n    // TODO: Currently the stale time of the route tree represents the\n    // stale time of both the route tree *and* all the segment data. So we\n    // can't just overwrite this field; we have to use whichever value is\n    // lower. In the future, though, the plan is to track segment lifetimes\n    // separately from the route tree lifetime.\n    if (staleAt < route.staleAt) {\n      route.staleAt = staleAt\n    }\n  }\n  // Any entry that's still pending was intentionally not rendered by the\n  // server, because it was inside the loading boundary. Mark them as rejected\n  // so we know not to fetch them again.\n  // TODO: If PPR is enabled on some routes but not others, then it's possible\n  // that a different page is able to do a per-segment prefetch of one of the\n  // segments we're marking as rejected here. We should mark on the segment\n  // somehow that the reason for the rejection is because of a non-PPR prefetch.\n  // That way a per-segment prefetch knows to disregard the rejection.\n  if (spawnedEntries !== null) {\n    const fulfilledEntries = rejectSegmentEntriesIfStillPending(\n      spawnedEntries,\n      now + 10 * 1000\n    )\n    return fulfilledEntries\n  }\n  return null\n}\n\nfunction writeSeedDataIntoCache(\n  now: number,\n  task: PrefetchTask,\n  fetchStrategy:\n    | FetchStrategy.LoadingBoundary\n    | FetchStrategy.PPRRuntime\n    | FetchStrategy.Full,\n  route: FulfilledRouteCacheEntry,\n  staleAt: number,\n  seedData: CacheNodeSeedData,\n  isResponsePartial: boolean,\n  cacheKey: SegmentCacheKey,\n  requestKey: SegmentRequestKey,\n  entriesOwnedByCurrentTask: Map<\n    SegmentCacheKey,\n    PendingSegmentCacheEntry\n  > | null\n) {\n  // This function is used to write the result of a dynamic server request\n  // (CacheNodeSeedData) into the prefetch cache. It's used in cases where we\n  // want to treat a dynamic response as if it were static. The two examples\n  // where this happens are <Link prefetch={true}> (which implicitly opts\n  // dynamic data into being static) and when prefetching a PPR-disabled route\n  const rsc = seedData[1]\n  const loading = seedData[3]\n  const isPartial = rsc === null || isResponsePartial\n\n  // We should only write into cache entries that are owned by us. Or create\n  // a new one and write into that. We must never write over an entry that was\n  // created by a different task, because that causes data races.\n  const ownedEntry =\n    entriesOwnedByCurrentTask !== null\n      ? entriesOwnedByCurrentTask.get(cacheKey)\n      : undefined\n  if (ownedEntry !== undefined) {\n    fulfillSegmentCacheEntry(ownedEntry, rsc, loading, staleAt, isPartial)\n  } else {\n    // There's no matching entry. Attempt to create a new one.\n    const possiblyNewEntry = readOrCreateSegmentCacheEntry(\n      now,\n      task,\n      route,\n      cacheKey\n    )\n    if (possiblyNewEntry.status === EntryStatus.Empty) {\n      // Confirmed this is a new entry. We can fulfill it.\n      const newEntry = possiblyNewEntry\n      fulfillSegmentCacheEntry(\n        upgradeToPendingSegment(newEntry, fetchStrategy),\n        rsc,\n        loading,\n        staleAt,\n        isPartial\n      )\n    } else {\n      // There was already an entry in the cache. But we may be able to\n      // replace it with the new one from the server.\n      const newEntry = fulfillSegmentCacheEntry(\n        upgradeToPendingSegment(\n          createDetachedSegmentCacheEntry(staleAt),\n          fetchStrategy\n        ),\n        rsc,\n        loading,\n        staleAt,\n        isPartial\n      )\n      upsertSegmentEntry(\n        now,\n        getSegmentKeypathForTask(task, route, cacheKey),\n        newEntry\n      )\n    }\n  }\n  // Recursively write the child data into the cache.\n  const seedDataChildren = seedData[2]\n  if (seedDataChildren !== null) {\n    for (const parallelRouteKey in seedDataChildren) {\n      const childSeedData = seedDataChildren[parallelRouteKey]\n      if (childSeedData !== null) {\n        const childSegment = childSeedData[0]\n        const childRequestKeyPart = createSegmentRequestKeyPart(childSegment)\n        const childRequestKey = appendSegmentRequestKeyPart(\n          requestKey,\n          parallelRouteKey,\n          childRequestKeyPart\n        )\n        const childCacheKey = appendSegmentCacheKeyPart(\n          cacheKey,\n          parallelRouteKey,\n          createSegmentCacheKeyPart(childRequestKeyPart, childSegment)\n        )\n        writeSeedDataIntoCache(\n          now,\n          task,\n          fetchStrategy,\n          route,\n          staleAt,\n          childSeedData,\n          isResponsePartial,\n          childCacheKey,\n          childRequestKey,\n          entriesOwnedByCurrentTask\n        )\n      }\n    }\n  }\n}\n\nasync function fetchPrefetchResponse(\n  url: URL,\n  headers: RequestHeaders\n): Promise<RSCResponse | null> {\n  const fetchPriority = 'low'\n  const response = await createFetch(url, headers, fetchPriority)\n  if (!response.ok) {\n    return null\n  }\n\n  // Check the content type\n  if (isOutputExportMode) {\n    // In output: \"export\" mode, we relaxed about the content type, since it's\n    // not Next.js that's serving the response. If the status is OK, assume the\n    // response is valid. If it's not a valid response, the Flight client won't\n    // be able to decode it, and we'll treat it as a miss.\n  } else {\n    const contentType = response.headers.get('content-type')\n    const isFlightResponse =\n      contentType && contentType.startsWith(RSC_CONTENT_TYPE_HEADER)\n    if (!isFlightResponse) {\n      return null\n    }\n  }\n  return response\n}\n\nfunction createPrefetchResponseStream(\n  originalFlightStream: ReadableStream<Uint8Array>,\n  onStreamClose: () => void,\n  onResponseSizeUpdate: (size: number) => void\n): ReadableStream<Uint8Array> {\n  // When PPR is enabled, prefetch streams may contain references that never\n  // resolve, because that's how we encode dynamic data access. In the decoded\n  // object returned by the Flight client, these are reified into hanging\n  // promises that suspend during render, which is effectively what we want.\n  // The UI resolves when it switches to the dynamic data stream\n  // (via useDeferredValue(dynamic, static)).\n  //\n  // However, the Flight implementation currently errors if the server closes\n  // the response before all the references are resolved. As a cheat to work\n  // around this, we wrap the original stream in a new stream that never closes,\n  // and therefore doesn't error.\n  //\n  // While processing the original stream, we also incrementally update the size\n  // of the cache entry in the LRU.\n  let totalByteLength = 0\n  const reader = originalFlightStream.getReader()\n  return new ReadableStream({\n    async pull(controller) {\n      while (true) {\n        const { done, value } = await reader.read()\n        if (!done) {\n          // Pass to the target stream and keep consuming the Flight response\n          // from the server.\n          controller.enqueue(value)\n\n          // Incrementally update the size of the cache entry in the LRU.\n          // NOTE: Since prefetch responses are delivered in a single chunk,\n          // it's not really necessary to do this streamingly, but I'm doing it\n          // anyway in case this changes in the future.\n          totalByteLength += value.byteLength\n          onResponseSizeUpdate(totalByteLength)\n          continue\n        }\n        // The server stream has closed. Exit, but intentionally do not close\n        // the target stream. We do notify the caller, though.\n        onStreamClose()\n        return\n      }\n    },\n  })\n}\n\nfunction addSegmentPathToUrlInOutputExportMode(\n  url: URL,\n  segmentPath: SegmentRequestKey\n): URL {\n  if (isOutputExportMode) {\n    // In output: \"export\" mode, we cannot use a header to encode the segment\n    // path. Instead, we append it to the end of the pathname.\n    const staticUrl = new URL(url)\n    const routeDir = staticUrl.pathname.endsWith('/')\n      ? staticUrl.pathname.substring(0, -1)\n      : staticUrl.pathname\n    const staticExportFilename =\n      convertSegmentPathToStaticExportFilename(segmentPath)\n    staticUrl.pathname = `${routeDir}/${staticExportFilename}`\n    return staticUrl\n  }\n  return url\n}\n\n/**\n * Checks whether the new fetch strategy is likely to provide more content than the old one.\n *\n * Generally, when an app uses dynamic data, a \"more specific\" fetch strategy is expected to provide more content:\n * - `LoadingBoundary` only provides static layouts\n * - `PPR` can provide shells for each segment (even for segments that use dynamic data)\n * - `PPRRuntime` can additionally include content that uses searchParams, params, or cookies\n * - `Full` includes all the content, even if it uses dynamic data\n *\n * However, it's possible that a more specific fetch strategy *won't* give us more content if:\n * - a segment is fully static\n *   (then, `PPR`/`PPRRuntime`/`Full` will all yield equivalent results)\n * - providing searchParams/params/cookies doesn't reveal any more content, e.g. because of an `await connection()`\n *   (then, `PPR` and `PPRRuntime` will yield equivalent results, only `Full` will give us more)\n * Because of this, when comparing two segments, we should also check if the existing segment is partial.\n * If it's not partial, then there's no need to prefetch it again, even using a \"more specific\" strategy.\n * There's currently no way to know if `PPRRuntime` will yield more data that `PPR`, so we have to assume it will.\n *\n * Also note that, in practice, we don't expect to be comparing `LoadingBoundary` to `PPR`/`PPRRuntime`,\n * because a non-PPR-enabled route wouldn't ever use the latter strategies. It might however use `Full`.\n */\nexport function canNewFetchStrategyProvideMoreContent(\n  currentStrategy: FetchStrategy,\n  newStrategy: FetchStrategy\n): boolean {\n  return currentStrategy < newStrategy\n}\n"],"names":["EntryStatus","canNewFetchStrategyProvideMoreContent","convertRouteTreeToFlightRouterState","createDetachedSegmentCacheEntry","fetchRouteOnCacheMiss","fetchSegmentOnCacheMiss","fetchSegmentPrefetchesUsingDynamicRequest","getCurrentCacheVersion","getSegmentKeypathForTask","pingInvalidationListeners","readExactRouteCacheEntry","readOrCreateRevalidatingSegmentEntry","readOrCreateRouteCacheEntry","readOrCreateSegmentCacheEntry","readRouteCacheEntry","readSegmentCacheEntry","requestOptimisticRouteCacheEntry","resetRevalidatingSegmentEntry","revalidateEntireCache","upgradeToPendingSegment","upsertSegmentEntry","waitForSegmentCacheEntry","isOutputExportMode","process","env","NODE_ENV","__NEXT_CONFIG_OUTPUT","getStaleTimeMs","staleTimeSeconds","Math","max","routeCacheMap","createTupleMap","maxRouteLruSize","routeCacheLru","createLRU","onRouteLRUEviction","segmentCacheMap","maxSegmentLruSize","segmentCacheLru","onSegmentLRUEviction","invalidationListeners","currentCacheVersion","nextUrl","tree","pingVisibleLinks","attachInvalidationListener","task","onInvalidate","Set","add","notifyInvalidationListener","error","reportError","console","tasks","isPrefetchTaskDirty","now","href","keypath","existingEntry","get","staleAt","put","deleteRouteFromCache","key","nonInterceptedEntry","couldBeIntercepted","route","cacheKey","isDynamicTask","fetchStrategy","FetchStrategy","Full","PPRRuntime","isPPREnabled","endsWith","PAGE_SEGMENT_KEY","renderedSearch","readExactSegmentCacheEntry","entryWithSearchParams","entryWithoutSearchParams","revalidatingEntry","revalidating","upsertedEntry","deleteSegmentFromCache","readRevalidatingSegmentCacheEntry","owner","existingRevalidation","clearRevalidatingSegmentFromOwner","pendingEntry","promiseWithResolvers","promise","createPromiseWithResolvers","canonicalUrl","status","blockedTasks","head","isHeadPartial","Infinity","TODO_metadataStatus","TODO_isHeadDynamic","next","prev","size","set","requestedUrl","requestedSearch","search","routeWithNoSearchParams","createPrefetchRequestKey","origin","pathname","canonicalUrlForRouteWithNoSearchParams","URL","optimisticCanonicalSearch","optimisticRenderedSearch","optimisticUrl","location","optimisticCanonicalUrl","createHrefFromUrl","optimisticEntry","prevEntry","candidateEntry","isPartial","rejectedEntry","loading","rsc","emptyEntry","PPR","entry","pingBlockedTasks","delete","cancelEntryListeners","revalidatingSegment","resolve","pingPrefetchTask","fulfillRouteCacheEntry","isHeadDynamic","fulfilledEntry","fulfillSegmentCacheEntry","segmentCacheEntry","rejectRouteCacheEntry","rejectSegmentCacheEntry","convertRootTreePrefetchToRouteTree","rootTree","renderedPathname","pathnameParts","split","filter","p","index","rootSegment","ROOT_SEGMENT_CACHE_KEY","convertTreePrefetchToRouteTree","ROOT_SEGMENT_REQUEST_KEY","prefetch","segment","param","requestKey","pathnamePartsIndex","slots","prefetchSlots","parallelRouteKey","childPrefetch","childParamName","name","childParamType","paramType","childServerSentParamKey","paramKey","childDoesAppearInURL","childParam","childSegment","childParamValue","parseDynamicParamFromURLPart","childParamKey","getCacheKeyForDynamicParam","value","type","doesStaticSegmentAppearInURL","childPathnamePartsIndex","childRequestKeyPart","createSegmentRequestKeyPart","childRequestKey","appendSegmentRequestKeyPart","childCacheKey","appendSegmentCacheKeyPart","createSegmentCacheKeyPart","isRootLayout","hasLoadingBoundary","HasLoadingBoundary","SegmentHasLoadingBoundary","convertRootFlightRouterStateToRouteTree","flightRouterState","convertFlightRouterStateToRouteTree","parallelRoutes","childRouterState","childTree","originalSegment","Array","isArray","paramCacheKey","paramValue","getParamValueFromCacheKey","undefined","startsWith","SubtreeHasNoLoadingBoundary","routeTree","segmentPath","headers","RSC_HEADER","NEXT_ROUTER_PREFETCH_HEADER","NEXT_ROUTER_SEGMENT_PREFETCH_HEADER","NEXT_URL","response","urlAfterRedirects","url","htmlResponse","fetch","Range","DOC_PREFETCH_RANGE_HEADER_VALUE","partialHtml","text","doesExportedHtmlMatchBuildId","getAppBuildId","Date","redirected","fetchPrefetchResponse","addSegmentPathToUrlInOutputExportMode","ok","body","varyHeader","includes","closed","routeIsPPREnabled","NEXT_DID_POSTPONE_HEADER","prefetchStream","createPrefetchResponseStream","onResponseSizeUpdate","updateSize","serverData","createFromNextReadableStream","buildId","getRenderedPathname","getRenderedSearch","staleTimeMs","staleTime","b","writeDynamicTreeResponseIntoCache","LoadingBoundary","currentKeypath","expectedEntry","newKeypath","routeKey","normalizedRequestKey","requestUrl","dynamicRequestTree","spawnedEntries","NEXT_ROUTER_STATE_TREE_HEADER","encodeURIComponent","JSON","stringify","rejectSegmentEntriesIfStillPending","fulfilledEntries","totalBytesReceivedSoFar","averageSize","length","isResponsePartial","writeDynamicRenderResponseIntoCache","normalizedFlightDataResult","normalizeFlightData","f","flightData","isRootRender","staleTimeHeaderSeconds","NEXT_ROUTER_STALE_TIME_HEADER","parseInt","STATIC_STALETIME_MS","entries","values","push","flightDatas","seedData","i","requestKeyPart","writeSeedDataIntoCache","entriesOwnedByCurrentTask","ownedEntry","possiblyNewEntry","newEntry","seedDataChildren","childSeedData","fetchPriority","createFetch","contentType","isFlightResponse","RSC_CONTENT_TYPE_HEADER","originalFlightStream","onStreamClose","totalByteLength","reader","getReader","ReadableStream","pull","controller","done","read","enqueue","byteLength","staticUrl","routeDir","substring","staticExportFilename","convertSegmentPathToStaticExportFilename","currentStrategy","newStrategy"],"mappings":"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","ignoreList":[0]}