{"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":["HasLoadingBoundary","NEXT_DID_POSTPONE_HEADER","NEXT_ROUTER_PREFETCH_HEADER","NEXT_ROUTER_SEGMENT_PREFETCH_HEADER","NEXT_ROUTER_STALE_TIME_HEADER","NEXT_ROUTER_STATE_TREE_HEADER","NEXT_URL","RSC_CONTENT_TYPE_HEADER","RSC_HEADER","createFetch","createFromNextReadableStream","pingPrefetchTask","isPrefetchTaskDirty","getAppBuildId","createHrefFromUrl","createCacheKey","createPrefetchRequestKey","doesStaticSegmentAppearInURL","getCacheKeyForDynamicParam","getParamValueFromCacheKey","getRenderedPathname","getRenderedSearch","parseDynamicParamFromURLPart","createTupleMap","createLRU","appendSegmentCacheKeyPart","appendSegmentRequestKeyPart","convertSegmentPathToStaticExportFilename","createSegmentCacheKeyPart","createSegmentRequestKeyPart","ROOT_SEGMENT_CACHE_KEY","ROOT_SEGMENT_REQUEST_KEY","normalizeFlightData","STATIC_STALETIME_MS","pingVisibleLinks","PAGE_SEGMENT_KEY","DOC_PREFETCH_RANGE_HEADER_VALUE","doesExportedHtmlMatchBuildId","FetchStrategy","createPromiseWithResolvers","EntryStatus","isOutputExportMode","process","env","NODE_ENV","__NEXT_CONFIG_OUTPUT","getStaleTimeMs","staleTimeSeconds","Math","max","routeCacheMap","maxRouteLruSize","routeCacheLru","onRouteLRUEviction","segmentCacheMap","maxSegmentLruSize","segmentCacheLru","onSegmentLRUEviction","invalidationListeners","currentCacheVersion","getCurrentCacheVersion","revalidateEntireCache","nextUrl","tree","pingInvalidationListeners","attachInvalidationListener","task","onInvalidate","Set","add","notifyInvalidationListener","error","reportError","console","tasks","readExactRouteCacheEntry","now","href","keypath","existingEntry","get","staleAt","put","deleteRouteFromCache","readRouteCacheEntry","key","nonInterceptedEntry","couldBeIntercepted","getSegmentKeypathForTask","route","cacheKey","isDynamicTask","fetchStrategy","Full","PPRRuntime","isPPREnabled","endsWith","renderedSearch","readSegmentCacheEntry","readExactSegmentCacheEntry","entryWithSearchParams","entryWithoutSearchParams","revalidatingEntry","revalidating","upsertedEntry","upsertSegmentEntry","deleteSegmentFromCache","readRevalidatingSegmentCacheEntry","owner","existingRevalidation","clearRevalidatingSegmentFromOwner","waitForSegmentCacheEntry","pendingEntry","promiseWithResolvers","promise","readOrCreateRouteCacheEntry","canonicalUrl","status","blockedTasks","head","isHeadPartial","Infinity","TODO_metadataStatus","TODO_isHeadDynamic","next","prev","size","set","requestOptimisticRouteCacheEntry","requestedUrl","requestedSearch","search","routeWithNoSearchParams","origin","pathname","canonicalUrlForRouteWithNoSearchParams","URL","optimisticCanonicalSearch","optimisticRenderedSearch","optimisticUrl","location","optimisticCanonicalUrl","optimisticEntry","readOrCreateSegmentCacheEntry","createDetachedSegmentCacheEntry","readOrCreateRevalidatingSegmentEntry","prevEntry","candidateEntry","canNewFetchStrategyProvideMoreContent","isPartial","rejectedEntry","loading","rsc","emptyEntry","PPR","upgradeToPendingSegment","entry","pingBlockedTasks","delete","cancelEntryListeners","revalidatingSegment","resetRevalidatingSegmentEntry","resolve","fulfillRouteCacheEntry","isHeadDynamic","fulfilledEntry","fulfillSegmentCacheEntry","segmentCacheEntry","rejectRouteCacheEntry","rejectSegmentCacheEntry","convertRootTreePrefetchToRouteTree","rootTree","renderedPathname","pathnameParts","split","filter","p","index","rootSegment","convertTreePrefetchToRouteTree","prefetch","segment","param","requestKey","pathnamePartsIndex","slots","prefetchSlots","parallelRouteKey","childPrefetch","childParamName","name","childParamType","paramType","childServerSentParamKey","paramKey","childDoesAppearInURL","childParam","childSegment","childParamValue","childParamKey","value","type","childPathnamePartsIndex","childRequestKeyPart","childRequestKey","childCacheKey","isRootLayout","hasLoadingBoundary","SegmentHasLoadingBoundary","convertRootFlightRouterStateToRouteTree","flightRouterState","convertFlightRouterStateToRouteTree","parallelRoutes","childRouterState","childTree","originalSegment","Array","isArray","paramCacheKey","paramValue","undefined","startsWith","SubtreeHasNoLoadingBoundary","convertRouteTreeToFlightRouterState","routeTree","fetchRouteOnCacheMiss","segmentPath","headers","response","urlAfterRedirects","url","htmlResponse","fetch","Range","partialHtml","text","Date","redirected","fetchPrefetchResponse","addSegmentPathToUrlInOutputExportMode","ok","body","varyHeader","includes","closed","routeIsPPREnabled","prefetchStream","createPrefetchResponseStream","onResponseSizeUpdate","updateSize","serverData","buildId","staleTimeMs","staleTime","b","writeDynamicTreeResponseIntoCache","LoadingBoundary","currentKeypath","expectedEntry","newKeypath","fetchSegmentOnCacheMiss","routeKey","normalizedRequestKey","requestUrl","fetchSegmentPrefetchesUsingDynamicRequest","dynamicRequestTree","spawnedEntries","encodeURIComponent","JSON","stringify","rejectSegmentEntriesIfStillPending","fulfilledEntries","totalBytesReceivedSoFar","averageSize","length","isResponsePartial","writeDynamicRenderResponseIntoCache","normalizedFlightDataResult","f","flightData","isRootRender","staleTimeHeaderSeconds","parseInt","entries","values","push","flightDatas","seedData","i","requestKeyPart","writeSeedDataIntoCache","entriesOwnedByCurrentTask","ownedEntry","possiblyNewEntry","newEntry","seedDataChildren","childSeedData","fetchPriority","contentType","isFlightResponse","originalFlightStream","onStreamClose","totalByteLength","reader","getReader","ReadableStream","pull","controller","done","read","enqueue","byteLength","staticUrl","routeDir","substring","staticExportFilename","currentStrategy","newStrategy"],"mappings":"AAcA,SAASA,kBAAkB,QAAQ,mCAAkC;AACrE,SACEC,wBAAwB,EACxBC,2BAA2B,EAC3BC,mCAAmC,EACnCC,6BAA6B,EAC7BC,6BAA6B,EAC7BC,QAAQ,EACRC,uBAAuB,EACvBC,UAAU,QACL,wBAAuB;AAC9B,SACEC,WAAW,EACXC,4BAA4B,QAGvB,0CAAyC;AAChD,SACEC,gBAAgB,EAChBC,mBAAmB,QAGd,cAAa;AACpB,SAASC,aAAa,QAAQ,qBAAoB;AAClD,SAASC,iBAAiB,QAAQ,yCAAwC;AAO1E,6EAA6E;AAC7E,SAASC,kBAAkBC,wBAAwB,QAAQ,cAAa;AACxE,SACEC,4BAA4B,EAC5BC,0BAA0B,EAC1BC,yBAAyB,EACzBC,mBAAmB,EACnBC,iBAAiB,EACjBC,4BAA4B,QAEvB,qBAAoB;AAC3B,SAASC,cAAc,QAAoC,cAAa;AACxE,SAASC,SAAS,QAAQ,QAAO;AACjC,SACEC,yBAAyB,EACzBC,2BAA2B,EAC3BC,wCAAwC,EACxCC,yBAAyB,EACzBC,2BAA2B,EAC3BC,sBAAsB,EACtBC,wBAAwB,QAGnB,2DAA0D;AAKjE,SAASC,mBAAmB,QAAQ,4BAA2B;AAC/D,SAASC,mBAAmB,QAAQ,yCAAwC;AAC5E,SAASC,gBAAgB,QAAQ,WAAU;AAC3C,SAASC,gBAAgB,QAAQ,8BAA6B;AAC9D,SACEC,+BAA+B,EAC/BC,4BAA4B,QACvB,oEAAmE;AAC1E,SAASC,aAAa,QAAQ,mBAAkB;AAChD,SAASC,0BAA0B,QAAQ,6CAA4C;AA6DvF;;;;CAIC,GACD,OAAO,IAAA,AAAWC,qCAAAA;;;;;WAAAA;MAKjB;AA+FD,MAAMC,qBACJC,QAAQC,GAAG,CAACC,QAAQ,KAAK,gBACzBF,QAAQC,GAAG,CAACE,oBAAoB,KAAK;AAEvC;;;CAGC,GACD,SAASC,eAAeC,gBAAwB;IAC9C,OAAOC,KAAKC,GAAG,CAACF,kBAAkB,MAAM;AAC1C;AAQA,IAAIG,gBACF3B;AAEF,8EAA8E;AAC9E,2DAA2D;AAC3D,+EAA+E;AAC/E,0EAA0E;AAC1E,4CAA4C;AAC5C,MAAM4B,kBAAkB,KAAK,OAAO,KAAK,QAAQ;;AACjD,IAAIC,gBAAgB5B,UAClB2B,iBACAE;AAIF,IAAIC,kBACF/B;AACF,0EAA0E;AAC1E,4EAA4E;AAC5E,+EAA+E;AAC/E,8BAA8B;AAC9B,MAAMgC,oBAAoB,KAAK,OAAO,KAAK,QAAQ;;AACnD,IAAIC,kBAAkBhC,UACpB+B,mBACAE;AAGF,4EAA4E;AAC5E,8EAA8E;AAC9E,oEAAoE;AACpE,8EAA8E;AAC9E,2EAA2E;AAC3E,4BAA4B;AAC5B,IAAIC,wBAAkD;AAEtD,0DAA0D;AAC1D,IAAIC,sBAAsB;AAE1B,OAAO,SAASC;IACd,OAAOD;AACT;AAEA;;;;;CAKC,GACD,OAAO,SAASE,sBACdC,OAAsB,EACtBC,IAAuB;IAEvBJ;IAEA,4EAA4E;IAC5E,4EAA4E;IAC5E,uBAAuB;IACvB,yEAAyE;IACzE,yEAAyE;IACzET,gBAAgB3B;IAChB6B,gBAAgB5B,UAAU2B,iBAAiBE;IAC3CC,kBAAkB/B;IAClBiC,kBAAkBhC,UAAU+B,mBAAmBE;IAE/C,wEAAwE;IACxEvB,iBAAiB4B,SAASC;IAE1B,qEAAqE;IACrE,uEAAuE;IACvE,aAAa;IACbC,0BAA0BF,SAASC;AACrC;AAEA,SAASE,2BAA2BC,IAAkB;IACpD,2EAA2E;IAC3E,0EAA0E;IAC1E,2EAA2E;IAC3E,2EAA2E;IAC3E,wCAAwC;IACxC,IAAIA,KAAKC,YAAY,KAAK,MAAM;QAC9B,IAAIT,0BAA0B,MAAM;YAClCA,wBAAwB,IAAIU,IAAI;gBAACF;aAAK;QACxC,OAAO;YACLR,sBAAsBW,GAAG,CAACH;QAC5B;IACF;AACF;AAEA,SAASI,2BAA2BJ,IAAkB;IACpD,MAAMC,eAAeD,KAAKC,YAAY;IACtC,IAAIA,iBAAiB,MAAM;QACzB,4EAA4E;QAC5E,aAAa;QACbD,KAAKC,YAAY,GAAG;QAEpB,+DAA+D;QAC/D,IAAI;YACFA;QACF,EAAE,OAAOI,OAAO;YACd,IAAI,OAAOC,gBAAgB,YAAY;gBACrCA,YAAYD;YACd,OAAO;gBACLE,QAAQF,KAAK,CAACA;YAChB;QACF;IACF;AACF;AAEA,OAAO,SAASP,0BACdF,OAAsB,EACtBC,IAAuB;IAEvB,4EAA4E;IAC5E,yEAAyE;IACzE,qEAAqE;IACrE,sBAAsB;IACtB,IAAIL,0BAA0B,MAAM;QAClC,MAAMgB,QAAQhB;QACdA,wBAAwB;QACxB,KAAK,MAAMQ,QAAQQ,MAAO;YACxB,IAAI9D,oBAAoBsD,MAAMJ,SAASC,OAAO;gBAC5CO,2BAA2BJ;YAC7B;QACF;IACF;AACF;AAEA,OAAO,SAASS,yBACdC,GAAW,EACXC,IAAoB,EACpBf,OAAiC;IAEjC,MAAMgB,UACJhB,YAAY,OAAO;QAACe;KAAK,GAAG;QAACA;QAAMf;KAAQ;IAC7C,MAAMiB,gBAAgB7B,cAAc8B,GAAG,CAACF;IACxC,IAAIC,kBAAkB,MAAM;QAC1B,8BAA8B;QAC9B,IAAIA,cAAcE,OAAO,GAAGL,KAAK;YAC/B,4BAA4B;YAE5B,mEAAmE;YACnExB,cAAc8B,GAAG,CAACH;YAElB,OAAOA;QACT,OAAO;YACL,wCAAwC;YACxCI,qBAAqBJ,eAAeD;QACtC;IACF;IACA,OAAO;AACT;AAEA,OAAO,SAASM,oBACdR,GAAW,EACXS,GAAkB;IAElB,wEAAwE;IACxE,2CAA2C;IAC3C,MAAMC,sBAAsBX,yBAAyBC,KAAKS,IAAIR,IAAI,EAAE;IACpE,IAAIS,wBAAwB,QAAQ,CAACA,oBAAoBC,kBAAkB,EAAE;QAC3E,uEAAuE;QACvE,OAAOD;IACT;IACA,sEAAsE;IACtE,OAAOX,yBAAyBC,KAAKS,IAAIR,IAAI,EAAEQ,IAAIvB,OAAO;AAC5D;AAEA,OAAO,SAAS0B,yBACdtB,IAAkB,EAClBuB,KAA+B,EAC/BC,QAAyB;IAEzB,wEAAwE;IACxE,qEAAqE;IACrE,0EAA0E;IAC1E,EAAE;IACF,8EAA8E;IAC9E,4EAA4E;IAC5E,6DAA6D;IAC7D,MAAMC,gBACJzB,KAAK0B,aAAa,KAAKtD,cAAcuD,IAAI,IACzC3B,KAAK0B,aAAa,KAAKtD,cAAcwD,UAAU,IAC/C,CAACL,MAAMM,YAAY;IACrB,OAAOJ,iBAAiBD,SAASM,QAAQ,CAAC,MAAM7D,oBAC5C;QAACuD;QAAUD,MAAMQ,cAAc;KAAC,GAChC;QAACP;KAAS;AAChB;AAEA,OAAO,SAASQ,sBACdtB,GAAW,EACXa,KAA+B,EAC/BC,QAAyB;IAEzB,IAAI,CAACA,SAASM,QAAQ,CAAC,MAAM7D,mBAAmB;QAC9C,wDAAwD;QACxD,OAAOgE,2BAA2BvB,KAAK;YAACc;SAAS;IACnD;IAEA,MAAMO,iBAAiBR,MAAMQ,cAAc;IAC3C,IAAIA,mBAAmB,MAAM;QAC3B,8EAA8E;QAC9E,0EAA0E;QAC1E,6BAA6B;QAC7B,MAAMG,wBAAwBD,2BAA2BvB,KAAK;YAC5Dc;YACAO;SACD;QACD,IAAIG,0BAA0B,MAAM;YAClC,OAAOA;QACT;IACF;IAEA,wEAAwE;IACxE,8EAA8E;IAC9E,8EAA8E;IAC9E,cAAc;IACd,EAAE;IACF,yDAAyD;IACzD,MAAMC,2BAA2BF,2BAA2BvB,KAAK;QAACc;KAAS;IAC3E,OAAOW;AACT;AAEA,SAASF,2BACPvB,GAAW,EACXE,OAAoC;IAEpC,MAAMC,gBAAgBzB,gBAAgB0B,GAAG,CAACF;IAC1C,IAAIC,kBAAkB,MAAM;QAC1B,8BAA8B;QAC9B,IAAIA,cAAcE,OAAO,GAAGL,KAAK;YAC/B,4BAA4B;YAE5B,mEAAmE;YACnEpB,gBAAgB0B,GAAG,CAACH;YAEpB,OAAOA;QACT,OAAO;YACL,yBAAyB;YACzB,MAAMuB,oBAAoBvB,cAAcwB,YAAY;YACpD,IAAID,sBAAsB,MAAM;gBAC9B,iDAAiD;gBACjD,MAAME,gBAAgBC,mBACpB7B,KACAE,SACAwB;gBAEF,IAAIE,kBAAkB,QAAQA,cAAcvB,OAAO,GAAGL,KAAK;oBACzD,8CAA8C;oBAC9C,OAAO4B;gBACT;YACF,OAAO;gBACL,wCAAwC;gBACxCE,uBAAuB3B,eAAeD;YACxC;QACF;IACF;IACA,OAAO;AACT;AAEA,SAAS6B,kCACP/B,GAAW,EACXgC,KAAwB;IAExB,MAAMC,uBAAuBD,MAAML,YAAY;IAC/C,IAAIM,yBAAyB,MAAM;QACjC,IAAIA,qBAAqB5B,OAAO,GAAGL,KAAK;YACtC,yEAAyE;YACzE,qCAAqC;YACrC,OAAOiC;QACT,OAAO;YACL,+CAA+C;YAC/CC,kCAAkCF;QACpC;IACF;IACA,OAAO;AACT;AAEA,OAAO,SAASG,yBACdC,YAAsC;IAEtC,uEAAuE;IACvE,4EAA4E;IAC5E,IAAIC,uBAAuBD,aAAaE,OAAO;IAC/C,IAAID,yBAAyB,MAAM;QACjCA,uBAAuBD,aAAaE,OAAO,GACzC3E;IACJ,OAAO;IACL,uCAAuC;IACzC;IACA,OAAO0E,qBAAqBC,OAAO;AACrC;AAEA;;;CAGC,GACD,OAAO,SAASC,4BACdvC,GAAW,EACXV,IAAkB;IAElBD,2BAA2BC;IAE3B,MAAMmB,MAAMnB,KAAKmB,GAAG;IACpB,MAAMN,gBAAgBK,oBAAoBR,KAAKS;IAC/C,IAAIN,kBAAkB,MAAM;QAC1B,OAAOA;IACT;IACA,kDAAkD;IAClD,MAAMiC,eAAuC;QAC3CI,cAAc;QACdC,MAAM;QACNC,cAAc;QACdvD,MAAM;QACNwD,MAAM;QACNC,eAAe;QACf,4EAA4E;QAC5E,yCAAyC;QACzCvC,SAASwC;QACT,0EAA0E;QAC1E,0EAA0E;QAC1E,mBAAmB;QACnBlC,oBAAoB;QACpB,0DAA0D;QAC1DQ,cAAc;QACdE,gBAAgB;QAEhByB,mBAAmB;QACnBC,oBAAoB;QAEpB,qBAAqB;QACrB7C,SAAS;QACT8C,MAAM;QACNC,MAAM;QACNC,MAAM;IACR;IACA,MAAMhD,UACJO,IAAIvB,OAAO,KAAK,OAAO;QAACuB,IAAIR,IAAI;KAAC,GAAG;QAACQ,IAAIR,IAAI;QAAEQ,IAAIvB,OAAO;KAAC;IAC7DZ,cAAc6E,GAAG,CAACjD,SAASkC;IAC3B,0EAA0E;IAC1E,mCAAmC;IACnCA,aAAalC,OAAO,GAAGA;IACvB1B,cAAc8B,GAAG,CAAC8B;IAClB,OAAOA;AACT;AAEA,OAAO,SAASgB,iCACdpD,GAAW,EACXqD,YAAiB,EACjBnE,OAAsB;IAEtB,yEAAyE;IACzE,oEAAoE;IACpE,8EAA8E;IAC9E,uDAAuD;IACvD,EAAE;IACF,sEAAsE;IACtE,2EAA2E;IAC3E,EAAE;IACF,wEAAwE;IACxE,wEAAwE;IACxE,qEAAqE;IACrE,4EAA4E;IAC5E,2EAA2E;IAC3E,wEAAwE;IACxE,0EAA0E;IAC1E,kCAAkC;IAElC,4EAA4E;IAC5E,0EAA0E;IAC1E,0EAA0E;IAC1E,uEAAuE;IACvE,4EAA4E;IAC5E,uCAAuC;IACvC,MAAMoE,kBAAkBD,aAAaE,MAAM;IAC3C,IAAID,oBAAoB,IAAI;QAC1B,wEAAwE;QACxE,mDAAmD;QACnD,OAAO;IACT;IACA,MAAME,0BAA0BhD,oBAC9BR,KACA5D,yBACEiH,aAAaI,MAAM,GAAGJ,aAAaK,QAAQ,EAC3CxE;IAIJ,IACEsE,4BAA4B,QAC5BA,wBAAwBf,MAAM,UAC9B,yEAAyE;IACzE,6DAA6D;IAC7D,qBAAqB;IACrBe,wBAAwBZ,aAAa,IACrC,yDAAyD;IACzD,oEAAoE;IACpE,oEAAoE;IACpE,gBAAgB;IAChBY,wBAAwBV,mBAAmB,UAC3CU,wBAAwBT,kBAAkB,EAC1C;QACA,yEAAyE;QACzE,uCAAuC;QACvC,OAAO;IACT;IAEA,2EAA2E;IAE3E,qEAAqE;IACrE,kEAAkE;IAClE,qEAAqE;IACrE,oEAAoE;IACpE,+BAA+B;IAC/B,MAAMY,yCAAyC,IAAIC,IACjDJ,wBAAwBhB,YAAY,EACpCa,aAAaI,MAAM;IAErB,MAAMI,4BACJF,uCAAuCJ,MAAM,KAAK,KAE9CI,uCAAuCJ,MAAM,GAC7CD;IAEN,mEAAmE;IACnE,oEAAoE;IACpE,wEAAwE;IACxE,yEAAyE;IACzE,+BAA+B;IAC/B,MAAMQ,2BACJN,wBAAwBnC,cAAc,KAAK,KAEvCmC,wBAAwBnC,cAAc,GACtCiC;IAEN,MAAMS,gBAAgB,IAAIH,IACxBJ,wBAAwBhB,YAAY,EACpCwB,SAASP,MAAM;IAEjBM,cAAcR,MAAM,GAAGM;IACvB,MAAMI,yBAAyB/H,kBAAkB6H;IAEjD,uEAAuE;IACvE,qBAAqB;IACrB,MAAMG,kBAA4C;QAChD1B,cAAcyB;QAEdxB,MAAM;QACN,mDAAmD;QACnDC,cAAc;QACdvD,MAAMqE,wBAAwBrE,IAAI;QAClCwD,MAAMa,wBAAwBb,IAAI;QAClCC,eAAeY,wBAAwBZ,aAAa;QACpDvC,SAASmD,wBAAwBnD,OAAO;QACxCM,oBAAoB6C,wBAAwB7C,kBAAkB;QAC9DQ,cAAcqC,wBAAwBrC,YAAY;QAElD,0DAA0D;QAC1DE,gBAAgByC;QAEhBhB,qBAAqBU,wBAAwBV,mBAAmB;QAChEC,oBAAoBS,wBAAwBT,kBAAkB;QAE9D,qBAAqB;QACrB7C,SAAS;QACT8C,MAAM;QACNC,MAAM;QACNC,MAAM;IACR;IAEA,oEAAoE;IACpE,gEAAgE;IAChE,OAAOgB;AACT;AAEA;;;CAGC,GACD,OAAO,SAASC,8BACdnE,GAAW,EACXV,IAAkB,EAClBuB,KAA+B,EAC/BC,QAAyB;IAEzB,MAAMZ,UAAUU,yBAAyBtB,MAAMuB,OAAOC;IACtD,MAAMX,gBAAgBoB,2BAA2BvB,KAAKE;IACtD,IAAIC,kBAAkB,MAAM;QAC1B,OAAOA;IACT;IACA,kDAAkD;IAClD,MAAMiC,eAAegC,gCAAgCvD,MAAMR,OAAO;IAClE3B,gBAAgByE,GAAG,CAACjD,SAASkC;IAC7B,0EAA0E;IAC1E,mCAAmC;IACnCA,aAAalC,OAAO,GAAGA;IACvBtB,gBAAgB0B,GAAG,CAAC8B;IACpB,OAAOA;AACT;AAEA,OAAO,SAASiC,qCACdrE,GAAW,EACXsE,SAA4B;IAE5B,MAAMrC,uBAAuBF,kCAAkC/B,KAAKsE;IACpE,IAAIrC,yBAAyB,MAAM;QACjC,OAAOA;IACT;IACA,MAAMG,eAAegC,gCAAgCE,UAAUjE,OAAO;IAEtE,4EAA4E;IAC5E,qEAAqE;IACrE,EAAE;IACF,2EAA2E;IAC3E,0EAA0E;IAC1E,EAAE;IACF,4EAA4E;IAC5E,6EAA6E;IAC7E,wEAAwE;IACxE,kEAAkE;IAClEiE,UAAU3C,YAAY,GAAGS;IAEzB,OAAOA;AACT;AAEA,OAAO,SAASP,mBACd7B,GAAW,EACXE,OAAoC,EACpCqE,cAAiC;IAEjC,4EAA4E;IAC5E,6EAA6E;IAC7E,yBAAyB;IACzB,6EAA6E;IAC7E,6EAA6E;IAC7E,iEAAiE;IACjE,MAAMpE,gBAAgBoB,2BAA2BvB,KAAKE;IACtD,IAAIC,kBAAkB,MAAM;QAC1B,oFAAoF;QACpF,0DAA0D;QAC1D,4BAA4B;QAC5B,IAGE,AAFA,6EAA6E;QAC7E,gFAAgF;QAC/EoE,eAAevD,aAAa,KAAKb,cAAca,aAAa,IAC3D,CAACwD,sCACCrE,cAAca,aAAa,EAC3BuD,eAAevD,aAAa,KAEhC,wDAAwD;QACxD,6FAA6F;QAC5F,CAACb,cAAcsE,SAAS,IAAIF,eAAeE,SAAS,EACrD;YACA,qEAAqE;YACrE,wEAAwE;YACxE,yEAAyE;YACzE,0EAA0E;YAC1E,yCAAyC;YACzC,MAAMC,gBAA2CH;YACjDG,cAAcjC,MAAM;YACpBiC,cAAcC,OAAO,GAAG;YACxBD,cAAcE,GAAG,GAAG;YACpB,OAAO;QACT;QAEA,2CAA2C;QAC3C9C,uBAAuB3B,eAAeD;IACxC;IACAxB,gBAAgByE,GAAG,CAACjD,SAASqE;IAC7B,0EAA0E;IAC1E,mCAAmC;IACnCA,eAAerE,OAAO,GAAGA;IACzBtB,gBAAgB0B,GAAG,CAACiE;IACpB,OAAOA;AACT;AAEA,OAAO,SAASH,gCACd/D,OAAe;IAEf,MAAMwE,aAAqC;QACzCpC,MAAM;QACN,2EAA2E;QAC3E,sCAAsC;QACtCzB,eAAetD,cAAcoH,GAAG;QAChCnD,cAAc;QACdiD,KAAK;QACLD,SAAS;QACTtE;QACAoE,WAAW;QACXnC,SAAS;QAET,qBAAqB;QACrBpC,SAAS;QACT8C,MAAM;QACNC,MAAM;QACNC,MAAM;IACR;IACA,OAAO2B;AACT;AAEA,OAAO,SAASE,wBACdF,UAAkC,EAClC7D,aAA4B;IAE5B,MAAMoB,eAAyCyC;IAC/CzC,aAAaK,MAAM;IACnBL,aAAapB,aAAa,GAAGA;IAC7B,OAAOoB;AACT;AAEA,SAAS7B,qBACPyE,KAAsB,EACtB9E,OAAkC;IAElC+E,iBAAiBD;IACjB1G,cAAc4G,MAAM,CAAChF;IACrB1B,cAAc0G,MAAM,CAACF;AACvB;AAEA,SAASlD,uBACPkD,KAAwB,EACxB9E,OAAoC;IAEpCiF,qBAAqBH;IACrBtG,gBAAgBwG,MAAM,CAAChF;IACvBtB,gBAAgBsG,MAAM,CAACF;IACvB9C,kCAAkC8C;AACpC;AAEA,SAAS9C,kCAAkCF,KAAwB;IACjE,sEAAsE;IACtE,0EAA0E;IAC1E,6EAA6E;IAC7E,gBAAgB;IAChB,MAAMoD,sBAAsBpD,MAAML,YAAY;IAC9C,IAAIyD,wBAAwB,MAAM;QAChCD,qBAAqBC;QACrBpD,MAAML,YAAY,GAAG;IACvB;AACF;AAEA,OAAO,SAAS0D,8BACdrD,KAAwB;IAExBE,kCAAkCF;IAClC,MAAM6C,aAAaT,gCAAgCpC,MAAM3B,OAAO;IAChE2B,MAAML,YAAY,GAAGkD;IACrB,OAAOA;AACT;AAEA,SAASpG,mBAAmBuG,KAAsB;IAChD,sDAAsD;IACtD,MAAM9E,UAAU8E,MAAM9E,OAAO;IAC7B,IAAIA,YAAY,MAAM;QACpB8E,MAAM9E,OAAO,GAAG;QAChB+E,iBAAiBD;QACjB1G,cAAc4G,MAAM,CAAChF;IACvB;AACF;AAEA,SAASrB,qBAAqBmG,KAAwB;IACpD,sDAAsD;IACtD,MAAM9E,UAAU8E,MAAM9E,OAAO;IAC7B,IAAIA,YAAY,MAAM;QACpB8E,MAAM9E,OAAO,GAAG;QAChBiF,qBAAqBH;QACrBtG,gBAAgBwG,MAAM,CAAChF;IACzB;AACF;AAEA,SAASiF,qBAAqBH,KAAwB;IACpD,IAAIA,MAAMvC,MAAM,UAA4BuC,MAAM1C,OAAO,KAAK,MAAM;QAClE,4EAA4E;QAC5E,4EAA4E;QAC5E,aAAa;QACb,0EAA0E;QAC1E,iDAAiD;QACjD0C,MAAM1C,OAAO,CAACgD,OAAO,CAAC;QACtBN,MAAM1C,OAAO,GAAG;IAClB;AACF;AAEA,SAAS2C,iBAAiBD,KAEzB;IACC,MAAMtC,eAAesC,MAAMtC,YAAY;IACvC,IAAIA,iBAAiB,MAAM;QACzB,KAAK,MAAMpD,QAAQoD,aAAc;YAC/B3G,iBAAiBuD;QACnB;QACA0F,MAAMtC,YAAY,GAAG;IACvB;AACF;AAEA,SAAS6C,uBACPP,KAAsB,EACtB7F,IAAe,EACfwD,IAAc,EACdC,aAAsB,EACtBvC,OAAe,EACfM,kBAA2B,EAC3B6B,YAAoB,EACpBnB,cAAgC,EAChCF,YAAqB,EACrBqE,aAAsB;IAEtB,MAAMC,iBAA2CT;IACjDS,eAAehD,MAAM;IACrBgD,eAAetG,IAAI,GAAGA;IACtBsG,eAAe9C,IAAI,GAAGA;IACtB8C,eAAe7C,aAAa,GAAGA;IAC/B6C,eAAepF,OAAO,GAAGA;IACzBoF,eAAe9E,kBAAkB,GAAGA;IACpC8E,eAAejD,YAAY,GAAGA;IAC9BiD,eAAepE,cAAc,GAAGA;IAChCoE,eAAetE,YAAY,GAAGA;IAC9BsE,eAAe1C,kBAAkB,GAAGyC;IACpCP,iBAAiBD;IACjB,OAAOS;AACT;AAEA,SAASC,yBACPC,iBAA2C,EAC3Cf,GAAoB,EACpBD,OAAuD,EACvDtE,OAAe,EACfoE,SAAkB;IAElB,MAAMgB,iBAA6CE;IACnDF,eAAehD,MAAM;IACrBgD,eAAeb,GAAG,GAAGA;IACrBa,eAAed,OAAO,GAAGA;IACzBc,eAAepF,OAAO,GAAGA;IACzBoF,eAAehB,SAAS,GAAGA;IAC3B,yDAAyD;IACzD,IAAIkB,kBAAkBrD,OAAO,KAAK,MAAM;QACtCqD,kBAAkBrD,OAAO,CAACgD,OAAO,CAACG;QAClC,2CAA2C;QAC3CA,eAAenD,OAAO,GAAG;IAC3B;IACA,OAAOmD;AACT;AAEA,SAASG,sBACPZ,KAA6B,EAC7B3E,OAAe;IAEf,MAAMqE,gBAAyCM;IAC/CN,cAAcjC,MAAM;IACpBiC,cAAcrE,OAAO,GAAGA;IACxB4E,iBAAiBD;AACnB;AAEA,SAASa,wBACPb,KAA+B,EAC/B3E,OAAe;IAEf,MAAMqE,gBAA2CM;IACjDN,cAAcjC,MAAM;IACpBiC,cAAcrE,OAAO,GAAGA;IACxB,IAAI2E,MAAM1C,OAAO,KAAK,MAAM;QAC1B,0EAA0E;QAC1E,iDAAiD;QACjD0C,MAAM1C,OAAO,CAACgD,OAAO,CAAC;QACtBN,MAAM1C,OAAO,GAAG;IAClB;AACF;AAEA,SAASwD,mCACPC,QAA0B,EAC1BC,gBAAwB;IAExB,sCAAsC;IACtC,MAAMC,gBAAgBD,iBAAiBE,KAAK,CAAC,KAAKC,MAAM,CAAC,CAACC,IAAMA,MAAM;IACtE,MAAMC,QAAQ;IACd,MAAMC,cAAcpJ;IACpB,OAAOqJ,+BACLR,SAAS5G,IAAI,EACbmH,aACA,MACAnJ,0BACAD,wBACA+I,eACAI;AAEJ;AAEA,SAASE,+BACPC,QAAsB,EACtBC,OAAiC,EACjCC,KAAwB,EACxBC,UAA6B,EAC7B7F,QAAyB,EACzBmF,aAA4B,EAC5BW,kBAA0B;IAE1B,yEAAyE;IACzE,8EAA8E;IAC9E,4EAA4E;IAC5E,0EAA0E;IAC1E,uCAAuC;IAEvC,IAAIC,QAA0D;IAC9D,MAAMC,gBAAgBN,SAASK,KAAK;IACpC,IAAIC,kBAAkB,MAAM;QAC1BD,QAAQ,CAAC;QACT,IAAK,IAAIE,oBAAoBD,cAAe;YAC1C,MAAME,gBAAgBF,aAAa,CAACC,iBAAiB;YACrD,MAAME,iBAAiBD,cAAcE,IAAI;YACzC,MAAMC,iBAAiBH,cAAcI,SAAS;YAC9C,MAAMC,0BAA0BL,cAAcM,QAAQ;YAEtD,IAAIC;YACJ,IAAIC,aAAgC;YACpC,IAAIC;YACJ,IAAIN,mBAAmB,MAAM;gBAC3B,kEAAkE;gBAClE,MAAMO,kBAAkBhL,6BACtByK,gBACAlB,eACAW;gBAGF,sEAAsE;gBACtE,uEAAuE;gBACvE,uEAAuE;gBACvE,2DAA2D;gBAE3D,gEAAgE;gBAChE,uEAAuE;gBACvE,sEAAsE;gBACtE,2DAA2D;gBAC3D,gBAAgB;gBAChB,MAAMvF,iBAAiB;gBACvB,MAAMsG,gBACJ,8DAA8D;gBAC9D,kEAAkE;gBAClE,oEAAoE;gBACpE,8DAA8D;gBAC9DN,4BAA4B,OACxBA,0BAEA/K,2BAA2BoL,iBAAiBrG;gBAElDmG,aAAa;oBACXN,MAAMD;oBACNW,OAAOF;oBACPG,MAAMV;gBACR;gBACAM,eAAe;oBAACR;oBAAgBU;oBAAeR;iBAAe;gBAC9DI,uBAAuB;YACzB,OAAO;gBACLE,eAAeR;gBACfM,uBAAuBlL,6BAA6B4K;YACtD;YAEA,wEAAwE;YACxE,8DAA8D;YAC9D,MAAMa,0BAA0BP,uBAC5BX,qBAAqB,IACrBA;YAEJ,MAAMmB,sBAAsB9K,4BAA4BwK;YACxD,MAAMO,kBAAkBlL,4BACtB6J,YACAI,kBACAgB;YAEF,MAAME,gBAAgBpL,0BACpBiE,UACAiG,kBACA/J,0BAA0B+K,qBAAqBN;YAEjDZ,KAAK,CAACE,iBAAiB,GAAGR,+BACxBS,eACAS,cACAD,YACAQ,iBACAC,eACAhC,eACA6B;QAEJ;IACF;IAEA,OAAO;QACLhH;QACA6F;QACAF;QACAC;QACAG;QACAqB,cAAc1B,SAAS0B,YAAY;QACnC,yEAAyE;QACzE,0DAA0D;QAC1DC,oBAAoB/M,mBAAmBgN,yBAAyB;IAClE;AACF;AAEA,SAASC,wCACPC,iBAAoC;IAEpC,OAAOC,oCACLD,mBACApL,wBACAC;AAEJ;AAEA,SAASoL,oCACPD,iBAAoC,EACpCxH,QAAyB,EACzB6F,UAA6B;IAE7B,IAAIE,QAA0D;IAE9D,MAAM2B,iBAAiBF,iBAAiB,CAAC,EAAE;IAC3C,IAAK,IAAIvB,oBAAoByB,eAAgB;QAC3C,MAAMC,mBAAmBD,cAAc,CAACzB,iBAAiB;QACzD,MAAMU,eAAegB,gBAAgB,CAAC,EAAE;QACxC,0EAA0E;QAC1E,uEAAuE;QACvE,wCAAwC;QACxC,MAAMV,sBAAsB9K,4BAA4BwK;QACxD,MAAMO,kBAAkBlL,4BACtB6J,YACAI,kBACAgB;QAEF,MAAME,gBAAgBpL,0BACpBiE,UACAiG,kBACA/J,0BAA0B+K,qBAAqBN;QAEjD,MAAMiB,YAAYH,oCAChBE,kBACAR,eACAD;QAEF,IAAInB,UAAU,MAAM;YAClBA,QAAQ;gBACN,CAACE,iBAAiB,EAAE2B;YACtB;QACF,OAAO;YACL7B,KAAK,CAACE,iBAAiB,GAAG2B;QAC5B;IACF;IACA,MAAMC,kBAAkBL,iBAAiB,CAAC,EAAE;IAE5C,IAAI7B;IACJ,IAAIC,QAA2B;IAC/B,IAAIkC,MAAMC,OAAO,CAACF,kBAAkB;QAClC,MAAMG,gBAAgBH,eAAe,CAAC,EAAE;QACxC,MAAMvB,YAAYuB,eAAe,CAAC,EAAE;QACpC,MAAMI,aAAaxM,0BAA0BuM,eAAe1B;QAC5DV,QAAQ;YACNQ,MAAMyB,eAAe,CAAC,EAAE;YACxBf,OAAOmB,eAAeC,YAAY,OAAOD;YACzClB,MAAMc,eAAe,CAAC,EAAE;QAC1B;QACAlC,UAAUkC;IACZ,OAAO;QACL,yEAAyE;QACzE,wEAAwE;QACxE,2EAA2E;QAC3E,0BAA0B;QAC1B,EAAE;QACF,6DAA6D;QAC7D,EAAE;QACF,yEAAyE;QACzE,uEAAuE;QACvElC,UACE,OAAOkC,oBAAoB,YAC3BA,gBAAgBM,UAAU,CAAC1L,oBACvBA,mBACAoL;IACR;IAEA,OAAO;QACL7H;QACA6F;QACAF;QACAC;QACAG;QACAqB,cAAcI,iBAAiB,CAAC,EAAE,KAAK;QACvCH,oBACEG,iBAAiB,CAAC,EAAE,KAAKU,YACrBV,iBAAiB,CAAC,EAAE,GACpBlN,mBAAmB8N,2BAA2B;IACtD;AACF;AAEA,OAAO,SAASC,oCACdC,SAAoB;IAEpB,MAAMZ,iBAAoD,CAAC;IAC3D,IAAIY,UAAUvC,KAAK,KAAK,MAAM;QAC5B,IAAK,MAAME,oBAAoBqC,UAAUvC,KAAK,CAAE;YAC9C2B,cAAc,CAACzB,iBAAiB,GAAGoC,oCACjCC,UAAUvC,KAAK,CAACE,iBAAiB;QAErC;IACF;IACA,MAAMuB,oBAAuC;QAC3Cc,UAAU3C,OAAO;QACjB+B;QACA;QACA;QACAY,UAAUlB,YAAY;KACvB;IACD,OAAOI;AACT;AAEA,OAAO,eAAee,sBACpBrE,KAA6B,EAC7B1F,IAAkB;IAElB,6EAA6E;IAC7E,6EAA6E;IAC7E,wEAAwE;IACxE,cAAc;IACd,MAAMmB,MAAMnB,KAAKmB,GAAG;IACpB,MAAMR,OAAOQ,IAAIR,IAAI;IACrB,MAAMf,UAAUuB,IAAIvB,OAAO;IAC3B,MAAMoK,cAAc;IAEpB,MAAMC,UAA0B;QAC9B,CAAC3N,WAAW,EAAE;QACd,CAACN,4BAA4B,EAAE;QAC/B,CAACC,oCAAoC,EAAE+N;IACzC;IACA,IAAIpK,YAAY,MAAM;QACpBqK,OAAO,CAAC7N,SAAS,GAAGwD;IACtB;IAEA,IAAI;QACF,IAAIsK;QACJ,IAAIC;QACJ,IAAI5L,oBAAoB;YACtB,yEAAyE;YACzE,0EAA0E;YAC1E,0EAA0E;YAC1E,0EAA0E;YAC1E,2BAA2B;YAC3B,EAAE;YACF,qCAAqC;YACrC,EAAE;YACF,2CAA2C;YAC3C,iEAAiE;YACjE,EAAE;YACF,4DAA4D;YAC5D,EAAE;YACF,uEAAuE;YACvE,wEAAwE;YACxE,0EAA0E;YAC1E,0BAA0B;YAC1B,EAAE;YACF,yEAAyE;YACzE,0EAA0E;YAC1E,qBAAqB;YACrB,EAAE;YACF,+DAA+D;YAC/D,EAAE;YACF,uEAAuE;YACvE,yEAAyE;YACzE,yDAAyD;YACzD,MAAM6L,MAAM,IAAI9F,IAAI3D;YACpB,MAAM0J,eAAe,MAAMC,MAAM3J,MAAM;gBACrCsJ,SAAS;oBACPM,OAAOrM;gBACT;YACF;YACA,MAAMsM,cAAc,MAAMH,aAAaI,IAAI;YAC3C,IAAI,CAACtM,6BAA6BqM,aAAa7N,kBAAkB;gBAC/D,8DAA8D;gBAC9D,mBAAmB;gBACnB2J,sBAAsBZ,OAAOgF,KAAKhK,GAAG,KAAK,KAAK;gBAC/C,OAAO;YACT;YACAyJ,oBAAoBE,aAAaM,UAAU,GACvC,IAAIrG,IAAI+F,aAAaD,GAAG,IACxBA;YACJF,WAAW,MAAMU,sBACfC,sCAAsCV,mBAAmBH,cACzDC;QAEJ,OAAO;YACL,qEAAqE;YACrE,0EAA0E;YAC1E,kEAAkE;YAClE,gCAAgC;YAChC,MAAMG,MAAM,IAAI9F,IAAI3D;YACpBuJ,WAAW,MAAMU,sBAAsBR,KAAKH;YAC5CE,oBACED,aAAa,QAAQA,SAASS,UAAU,GAAG,IAAIrG,IAAI4F,SAASE,GAAG,IAAIA;QACvE;QAEA,IACE,CAACF,YACD,CAACA,SAASY,EAAE,IACZ,uEAAuE;QACvE,yEAAyE;QACzE,oDAAoD;QACpDZ,SAAS/G,MAAM,KAAK,OACpB,CAAC+G,SAASa,IAAI,EACd;YACA,wEAAwE;YACxE,uDAAuD;YACvDzE,sBAAsBZ,OAAOgF,KAAKhK,GAAG,KAAK,KAAK;YAC/C,OAAO;QACT;QAEA,kEAAkE;QAClE,wEAAwE;QACxE,yEAAyE;QACzE,wEAAwE;QACxE,4EAA4E;QAC5E,yEAAyE;QACzE,EAAE;QACF,2EAA2E;QAC3E,2EAA2E;QAC3E,4EAA4E;QAC5E,0EAA0E;QAC1E,2EAA2E;QAC3E,4BAA4B;QAC5B,MAAMwC,eAAetG,kBAAkBuN;QAEvC,kEAAkE;QAClE,MAAMa,aAAad,SAASD,OAAO,CAACnJ,GAAG,CAAC;QACxC,MAAMO,qBACJ2J,eAAe,QAAQA,WAAWC,QAAQ,CAAC7O;QAE7C,4CAA4C;QAC5C,MAAM8O,SAAS7M;QAEf,0EAA0E;QAC1E,yEAAyE;QACzE,6BAA6B;QAC7B,MAAM8M,oBACJjB,SAASD,OAAO,CAACnJ,GAAG,CAAC/E,8BAA8B,OACnD,yEAAyE;QACzE,wEAAwE;QACxE,2CAA2C;QAC3CwC;QAEF,oEAAoE;QACpE,6CAA6C;QAC7C,MAAM2H,gBAAgB;QAEtB,IAAIiF,mBAAmB;YACrB,MAAMC,iBAAiBC,6BACrBnB,SAASa,IAAI,EACbG,OAAOlF,OAAO,EACd,SAASsF,qBAAqB1H,IAAI;gBAChC1E,cAAcqM,UAAU,CAAC7F,OAAO9B;YAClC;YAEF,MAAM4H,aAAa,MAAOhP,6BACxB4O;YAEF,IAAII,WAAWC,OAAO,KAAK9O,iBAAiB;gBAC1C,qEAAqE;gBACrE,mEAAmE;gBACnE,0EAA0E;gBAC1E,sEAAsE;gBACtE,6BAA6B;gBAC7B,iEAAiE;gBACjE2J,sBAAsBZ,OAAOgF,KAAKhK,GAAG,KAAK,KAAK;gBAC/C,OAAO;YACT;YAEA,qEAAqE;YACrE,+DAA+D;YAC/D,iBAAiB;YACjB,MAAMgG,mBAAmBxJ,oBAAoBgN;YAC7C,MAAMnI,iBAAiB5E,kBAAkB+M;YAEzC,MAAMJ,YAAYtD,mCAChBgF,YACA9E;YAGF,MAAMgF,cAAc9M,eAAe4M,WAAWG,SAAS;YACvD1F,uBACEP,OACAoE,WACA0B,WAAWnI,IAAI,EACfmI,WAAWlI,aAAa,EACxBoH,KAAKhK,GAAG,KAAKgL,aACbrK,oBACA6B,cACAnB,gBACAoJ,mBACAjF;QAEJ,OAAO;YACL,gEAAgE;YAChE,gEAAgE;YAChE,sEAAsE;YACtE,yDAAyD;YACzD,uBAAuB;YACvB,MAAMkF,iBAAiBC,6BACrBnB,SAASa,IAAI,EACbG,OAAOlF,OAAO,EACd,SAASsF,qBAAqB1H,IAAI;gBAChC1E,cAAcqM,UAAU,CAAC7F,OAAO9B;YAClC;YAEF,MAAM4H,aAAa,MAAOhP,6BACxB4O;YAEF,IAAII,WAAWI,CAAC,KAAKjP,iBAAiB;gBACpC,qEAAqE;gBACrE,mEAAmE;gBACnE,0EAA0E;gBAC1E,sEAAsE;gBACtE,6BAA6B;gBAC7B,iEAAiE;gBACjE2J,sBAAsBZ,OAAOgF,KAAKhK,GAAG,KAAK,KAAK;gBAC/C,OAAO;YACT;YAEAmL,kCACEnB,KAAKhK,GAAG,IACRV,MACA,+EAA+E;YAC/E,qFAAqF;YACrF5B,cAAc0N,eAAe,EAC7B5B,UACAsB,YACA9F,OACArE,oBACA6B,cACAiI;QAEJ;QAEA,IAAI,CAAC9J,sBAAsBzB,YAAY,MAAM;YAC3C,yEAAyE;YACzE,wEAAwE;YACxE,6DAA6D;YAC7D,+BAA+B;YAC/B,EAAE;YACF,wEAAwE;YACxE,wEAAwE;YACxE,MAAMmM,iBAA4C;gBAACpL;gBAAMf;aAAQ;YACjE,MAAMoM,gBAAgBhN,cAAc8B,GAAG,CAACiL;YACxC,IAAIC,kBAAkBtG,OAAO;gBAC3B1G,cAAc4G,MAAM,CAACmG;gBACrB,MAAME,aAAwC;oBAACtL;iBAAK;gBACpD3B,cAAc6E,GAAG,CAACoI,YAAYvG;gBAC9B,sEAAsE;gBACtE,qEAAqE;gBACrE,sEAAsE;gBACtEA,MAAM9E,OAAO,GAAGqL;YAClB,OAAO;YACL,qEAAqE;YACrE,0DAA0D;YAC5D;QACF;QACA,wEAAwE;QACxE,wEAAwE;QACxE,OAAO;YAAE3D,OAAO;YAAM4C,QAAQA,OAAOlI,OAAO;QAAC;IAC/C,EAAE,OAAO3C,OAAO;QACd,uEAAuE;QACvE,yBAAyB;QACzBiG,sBAAsBZ,OAAOgF,KAAKhK,GAAG,KAAK,KAAK;QAC/C,OAAO;IACT;AACF;AAEA,OAAO,eAAewL,wBACpB3K,KAA+B,EAC/B8E,iBAA2C,EAC3C8F,QAAuB,EACvBtM,IAAe;IAEf,6EAA6E;IAC7E,6EAA6E;IAC7E,wEAAwE;IACxE,cAAc;IACd,EAAE;IACF,0EAA0E;IAC1E,iBAAiB;IAEjB,4EAA4E;IAC5E,6EAA6E;IAC7E,6EAA6E;IAC7E,mEAAmE;IACnE,MAAMuK,MAAM,IAAI9F,IAAI/C,MAAM2B,YAAY,EAAEiJ,SAASxL,IAAI;IACrD,MAAMf,UAAUuM,SAASvM,OAAO;IAEhC,MAAMyH,aAAaxH,KAAKwH,UAAU;IAClC,MAAM+E,uBACJ/E,eAAexJ,2BAEX,iEAAiE;IACjE,oEAAoE;IACpE,qEAAqE;IACrE,gEAAgE;IAChE,qEAAqE;IACpE,YACDwJ;IAEN,MAAM4C,UAA0B;QAC9B,CAAC3N,WAAW,EAAE;QACd,CAACN,4BAA4B,EAAE;QAC/B,CAACC,oCAAoC,EAAEmQ;IACzC;IACA,IAAIxM,YAAY,MAAM;QACpBqK,OAAO,CAAC7N,SAAS,GAAGwD;IACtB;IAEA,MAAMyM,aAAa9N,qBAEfsM,sCAAsCT,KAAKgC,wBAC3ChC;IACJ,IAAI;QACF,MAAMF,WAAW,MAAMU,sBAAsByB,YAAYpC;QACzD,IACE,CAACC,YACD,CAACA,SAASY,EAAE,IACZZ,SAAS/G,MAAM,KAAK,OAAO,aAAa;QACxC,0EAA0E;QAC1E,yEAAyE;QACzE,oEAAoE;QACpE,uEAAuE;QACvE,0BAA0B;QACzB+G,SAASD,OAAO,CAACnJ,GAAG,CAAC/E,8BAA8B,OAClD,sEAAsE;QACtE,iEAAiE;QACjE,qDAAqD;QACrD,CAACwC,sBACH,CAAC2L,SAASa,IAAI,EACd;YACA,wEAAwE;YACxE,uDAAuD;YACvDxE,wBAAwBF,mBAAmBqE,KAAKhK,GAAG,KAAK,KAAK;YAC7D,OAAO;QACT;QAEA,4CAA4C;QAC5C,MAAMwK,SAAS7M;QAEf,2EAA2E;QAC3E,4DAA4D;QAC5D,MAAM+M,iBAAiBC,6BACrBnB,SAASa,IAAI,EACbG,OAAOlF,OAAO,EACd,SAASsF,qBAAqB1H,IAAI;YAChCtE,gBAAgBiM,UAAU,CAAClF,mBAAmBzC;QAChD;QAEF,MAAM4H,aAAa,MAAOhP,6BACxB4O;QAEF,IAAII,WAAWC,OAAO,KAAK9O,iBAAiB;YAC1C,qEAAqE;YACrE,mEAAmE;YACnE,0EAA0E;YAC1E,sEAAsE;YACtE,6BAA6B;YAC7B4J,wBAAwBF,mBAAmBqE,KAAKhK,GAAG,KAAK,KAAK;YAC7D,OAAO;QACT;QACA,OAAO;YACL4H,OAAOlC,yBACLC,mBACAmF,WAAWlG,GAAG,EACdkG,WAAWnG,OAAO,EAClB,sEAAsE;YACtE,yCAAyC;YACzC9D,MAAMR,OAAO,EACbyK,WAAWrG,SAAS;YAEtB,wEAAwE;YACxE,wEAAwE;YACxE+F,QAAQA,OAAOlI,OAAO;QACxB;IACF,EAAE,OAAO3C,OAAO;QACd,uEAAuE;QACvE,yBAAyB;QACzBkG,wBAAwBF,mBAAmBqE,KAAKhK,GAAG,KAAK,KAAK;QAC7D,OAAO;IACT;AACF;AAEA,OAAO,eAAe4L,0CACpBtM,IAAkB,EAClBuB,KAA+B,EAC/BG,aAGsB,EACtB6K,kBAAqC,EACrCC,cAA8D;IAE9D,MAAMpC,MAAM,IAAI9F,IAAI/C,MAAM2B,YAAY,EAAElD,KAAKmB,GAAG,CAACR,IAAI;IACrD,MAAMf,UAAUI,KAAKmB,GAAG,CAACvB,OAAO;IAChC,MAAMqK,UAA0B;QAC9B,CAAC3N,WAAW,EAAE;QACd,CAACH,8BAA8B,EAAEsQ,mBAC/BC,KAAKC,SAAS,CAACJ;IAEnB;IACA,IAAI3M,YAAY,MAAM;QACpBqK,OAAO,CAAC7N,SAAS,GAAGwD;IACtB;IACA,OAAQ8B;QACN,KAAKtD,cAAcuD,IAAI;YAAE;gBAIvB;YACF;QACA,KAAKvD,cAAcwD,UAAU;YAAE;gBAC7BqI,OAAO,CAACjO,4BAA4B,GAAG;gBACvC;YACF;QACA,KAAKoC,cAAc0N,eAAe;YAAE;gBAClC7B,OAAO,CAACjO,4BAA4B,GAAG;gBACvC;YACF;QACA;YAAS;gBACP0F;YACF;IACF;IAEA,IAAI;QACF,MAAMwI,WAAW,MAAMU,sBAAsBR,KAAKH;QAClD,IAAI,CAACC,YAAY,CAACA,SAASY,EAAE,IAAI,CAACZ,SAASa,IAAI,EAAE;YAC/C,wEAAwE;YACxE,uDAAuD;YACvD6B,mCAAmCJ,gBAAgB9B,KAAKhK,GAAG,KAAK,KAAK;YACrE,OAAO;QACT;QAEA,MAAMqB,iBAAiB5E,kBAAkB+M;QACzC,IAAInI,mBAAmBR,MAAMQ,cAAc,EAAE;YAC3C,iEAAiE;YACjE,yEAAyE;YACzE,sEAAsE;YACtE,iBAAiB;YACjB,yEAAyE;YACzE,uEAAuE;YACvE,6CAA6C;YAC7C6K,mCAAmCJ,gBAAgB9B,KAAKhK,GAAG,KAAK,KAAK;YACrE,OAAO;QACT;QAEA,4CAA4C;QAC5C,MAAMwK,SAAS7M;QAEf,IAAIwO,mBAA6D;QACjE,MAAMzB,iBAAiBC,6BACrBnB,SAASa,IAAI,EACbG,OAAOlF,OAAO,EACd,SAASsF,qBAAqBwB,uBAAuB;YACnD,mEAAmE;YACnE,iEAAiE;YACjE,0CAA0C;YAC1C,IAAID,qBAAqB,MAAM;gBAC7B,0DAA0D;gBAC1D,iBAAiB;gBACjB;YACF;YACA,MAAME,cAAcD,0BAA0BD,iBAAiBG,MAAM;YACrE,KAAK,MAAMtH,SAASmH,iBAAkB;gBACpCvN,gBAAgBiM,UAAU,CAAC7F,OAAOqH;YACpC;QACF;QAEF,MAAMvB,aAAa,MAAOhP,6BACxB4O;QAGF,MAAM6B,oBACJvL,kBAAkBtD,cAAcwD,UAAU,GAEtC,CAAC,CAACsI,SAASD,OAAO,CAACnJ,GAAG,CAAC/E,4BAEvB,iGAAiG;QACjG;QAEN,yEAAyE;QACzE,4EAA4E;QAC5E,oCAAoC;QACpC8Q,mBAAmBK,oCACjBxC,KAAKhK,GAAG,IACRV,MACA0B,eACAwI,UACAsB,YACAyB,mBACA1L,OACAiL;QAGF,wEAAwE;QACxE,wEAAwE;QACxE,OAAO;YAAElE,OAAO;YAAM4C,QAAQA,OAAOlI,OAAO;QAAC;IAC/C,EAAE,OAAO3C,OAAO;QACduM,mCAAmCJ,gBAAgB9B,KAAKhK,GAAG,KAAK,KAAK;QACrE,OAAO;IACT;AACF;AAEA,SAASmL,kCACPnL,GAAW,EACXV,IAAkB,EAClB0B,aAGsB,EACtBwI,QAAqB,EACrBsB,UAAoC,EACpC9F,KAA6B,EAC7BrE,kBAA2B,EAC3B6B,YAAoB,EACpBiI,iBAA0B;IAE1B,6EAA6E;IAC7E,8DAA8D;IAC9D,MAAMpJ,iBAAiB5E,kBAAkB+M;IAEzC,MAAMiD,6BAA6BrP,oBAAoB0N,WAAW4B,CAAC;IACnE,IACE,mEAAmE;IACnE,kBAAkB;IAClB,OAAOD,+BAA+B,YACtCA,2BAA2BH,MAAM,KAAK,GACtC;QACA1G,sBAAsBZ,OAAOhF,MAAM,KAAK;QACxC;IACF;IACA,MAAM2M,aAAaF,0BAA0B,CAAC,EAAE;IAChD,IAAI,CAACE,WAAWC,YAAY,EAAE;QAC5B,8BAA8B;QAC9BhH,sBAAsBZ,OAAOhF,MAAM,KAAK;QACxC;IACF;IAEA,MAAMsI,oBAAoBqE,WAAWxN,IAAI;IACzC,4BAA4B;IAC5B,MAAM0N,yBAAyBrD,SAASD,OAAO,CAACnJ,GAAG,CACjD5E;IAEF,MAAMwP,cACJ6B,2BAA2B,OACvB3O,eAAe4O,SAASD,wBAAwB,OAChDxP;IAEN,6EAA6E;IAC7E,wEAAwE;IACxE,8EAA8E;IAC9E,qCAAqC;IACrC,MAAMkP,oBACJ/C,SAASD,OAAO,CAACnJ,GAAG,CAAC/E,8BAA8B;IAErD,2EAA2E;IAC3E,oCAAoC;IACpC,MAAMmK,gBAAgB;IAEtB,MAAMC,iBAAiBF,uBACrBP,OACAqD,wCAAwCC,oBACxCqE,WAAWhK,IAAI,EACfgK,WAAW/J,aAAa,EACxB5C,MAAMgL,aACNrK,oBACA6B,cACAnB,gBACAoJ,mBACAjF;IAGF,2EAA2E;IAC3E,qEAAqE;IACrE,EAAE;IACF,0EAA0E;IAC1E,0EAA0E;IAC1E,4EAA4E;IAC5E,yEAAyE;IACzE,0EAA0E;IAC1E,2EAA2E;IAC3EgH,oCACExM,KACAV,MACA0B,eACAwI,UACAsB,YACAyB,mBACA9G,gBACA;AAEJ;AAEA,SAASyG,mCACPa,OAAgD,EAChD1M,OAAe;IAEf,MAAM8L,mBAAmB,EAAE;IAC3B,KAAK,MAAMnH,SAAS+H,QAAQC,MAAM,GAAI;QACpC,IAAIhI,MAAMvC,MAAM,QAA0B;YACxCoD,wBAAwBb,OAAO3E;QACjC,OAAO,IAAI2E,MAAMvC,MAAM,QAA4B;YACjD0J,iBAAiBc,IAAI,CAACjI;QACxB;IACF;IACA,OAAOmH;AACT;AAEA,SAASK,oCACPxM,GAAW,EACXV,IAAkB,EAClB0B,aAGsB,EACtBwI,QAAqB,EACrBsB,UAAoC,EACpCyB,iBAA0B,EAC1B1L,KAA+B,EAC/BiL,cAAqE;IAErE,IAAIhB,WAAWI,CAAC,KAAKjP,iBAAiB;QACpC,qEAAqE;QACrE,mEAAmE;QACnE,0EAA0E;QAC1E,sEAAsE;QACtE,6BAA6B;QAC7B,IAAI6P,mBAAmB,MAAM;YAC3BI,mCAAmCJ,gBAAgB9L,MAAM,KAAK;QAChE;QACA,OAAO;IACT;IAEA,MAAMkN,cAAc9P,oBAAoB0N,WAAW4B,CAAC;IACpD,IAAI,OAAOQ,gBAAgB,UAAU;QACnC,wEAAwE;QACxE,4EAA4E;QAC5E,OAAO;IACT;IAEA,MAAML,yBAAyBrD,SAASD,OAAO,CAACnJ,GAAG,CACjD5E;IAEF,MAAMwP,cACJ6B,2BAA2B,OACvB3O,eAAe4O,SAASD,wBAAwB,OAChDxP;IACN,MAAMgD,UAAUL,MAAMgL;IAEtB,KAAK,MAAM2B,cAAcO,YAAa;QACpC,MAAMC,WAAWR,WAAWQ,QAAQ;QACpC,IAAIA,aAAa,MAAM;YACrB,uEAAuE;YACvE,oEAAoE;YACpE,EAAE;YACF,sEAAsE;YACtE,6CAA6C;YAC7C,EAAE;YACF,6DAA6D;YAC7D,MAAM7D,cAAcqD,WAAWrD,WAAW;YAC1C,IAAI3C,aAAaxJ;YACjB,IAAI2D,WAAW5D;YACf,IAAK,IAAIkQ,IAAI,GAAGA,IAAI9D,YAAYgD,MAAM,EAAEc,KAAK,EAAG;gBAC9C,MAAMrG,mBAA2BuC,WAAW,CAAC8D,EAAE;gBAC/C,MAAM3G,UAAoC6C,WAAW,CAAC8D,IAAI,EAAE;gBAC5D,MAAMC,iBAAiBpQ,4BAA4BwJ;gBACnDE,aAAa7J,4BACX6J,YACAI,kBACAsG;gBAEFvM,WAAWjE,0BACTiE,UACAiG,kBACA/J,0BAA0BqQ,gBAAgB5G;YAE9C;YAEA6G,uBACEtN,KACAV,MACA0B,eACAH,OACAR,SACA8M,UACAZ,mBACAzL,UACA6F,YACAmF;QAEJ;QAEA,wEAAwE;QACxE,sEAAsE;QACtE,qEAAqE;QACrE,0EAA0E;QAC1E,uEAAuE;QACvE,yEAAyE;QACzE,uDAAuD;QACvDjL,MAAM8B,IAAI,GAAGgK,WAAWhK,IAAI;QAC5B9B,MAAM+B,aAAa,GAAG+J,WAAW/J,aAAa;QAC9C/B,MAAMkC,kBAAkB,GAAG;QAE3B,kEAAkE;QAClE,sEAAsE;QACtE,qEAAqE;QACrE,uEAAuE;QACvE,2CAA2C;QAC3C,IAAI1C,UAAUQ,MAAMR,OAAO,EAAE;YAC3BQ,MAAMR,OAAO,GAAGA;QAClB;IACF;IACA,uEAAuE;IACvE,4EAA4E;IAC5E,sCAAsC;IACtC,4EAA4E;IAC5E,2EAA2E;IAC3E,yEAAyE;IACzE,8EAA8E;IAC9E,oEAAoE;IACpE,IAAIyL,mBAAmB,MAAM;QAC3B,MAAMK,mBAAmBD,mCACvBJ,gBACA9L,MAAM,KAAK;QAEb,OAAOmM;IACT;IACA,OAAO;AACT;AAEA,SAASmB,uBACPtN,GAAW,EACXV,IAAkB,EAClB0B,aAGsB,EACtBH,KAA+B,EAC/BR,OAAe,EACf8M,QAA2B,EAC3BZ,iBAA0B,EAC1BzL,QAAyB,EACzB6F,UAA6B,EAC7B4G,yBAGQ;IAER,wEAAwE;IACxE,2EAA2E;IAC3E,0EAA0E;IAC1E,uEAAuE;IACvE,4EAA4E;IAC5E,MAAM3I,MAAMuI,QAAQ,CAAC,EAAE;IACvB,MAAMxI,UAAUwI,QAAQ,CAAC,EAAE;IAC3B,MAAM1I,YAAYG,QAAQ,QAAQ2H;IAElC,0EAA0E;IAC1E,4EAA4E;IAC5E,+DAA+D;IAC/D,MAAMiB,aACJD,8BAA8B,OAC1BA,0BAA0BnN,GAAG,CAACU,YAC9BkI;IACN,IAAIwE,eAAexE,WAAW;QAC5BtD,yBAAyB8H,YAAY5I,KAAKD,SAAStE,SAASoE;IAC9D,OAAO;QACL,0DAA0D;QAC1D,MAAMgJ,mBAAmBtJ,8BACvBnE,KACAV,MACAuB,OACAC;QAEF,IAAI2M,iBAAiBhL,MAAM,QAAwB;YACjD,oDAAoD;YACpD,MAAMiL,WAAWD;YACjB/H,yBACEX,wBAAwB2I,UAAU1M,gBAClC4D,KACAD,SACAtE,SACAoE;QAEJ,OAAO;YACL,iEAAiE;YACjE,+CAA+C;YAC/C,MAAMiJ,WAAWhI,yBACfX,wBACEX,gCAAgC/D,UAChCW,gBAEF4D,KACAD,SACAtE,SACAoE;YAEF5C,mBACE7B,KACAY,yBAAyBtB,MAAMuB,OAAOC,WACtC4M;QAEJ;IACF;IACA,mDAAmD;IACnD,MAAMC,mBAAmBR,QAAQ,CAAC,EAAE;IACpC,IAAIQ,qBAAqB,MAAM;QAC7B,IAAK,MAAM5G,oBAAoB4G,iBAAkB;YAC/C,MAAMC,gBAAgBD,gBAAgB,CAAC5G,iBAAiB;YACxD,IAAI6G,kBAAkB,MAAM;gBAC1B,MAAMnG,eAAemG,aAAa,CAAC,EAAE;gBACrC,MAAM7F,sBAAsB9K,4BAA4BwK;gBACxD,MAAMO,kBAAkBlL,4BACtB6J,YACAI,kBACAgB;gBAEF,MAAME,gBAAgBpL,0BACpBiE,UACAiG,kBACA/J,0BAA0B+K,qBAAqBN;gBAEjD6F,uBACEtN,KACAV,MACA0B,eACAH,OACAR,SACAuN,eACArB,mBACAtE,eACAD,iBACAuF;YAEJ;QACF;IACF;AACF;AAEA,eAAerD,sBACbR,GAAQ,EACRH,OAAuB;IAEvB,MAAMsE,gBAAgB;IACtB,MAAMrE,WAAW,MAAM3N,YAAY6N,KAAKH,SAASsE;IACjD,IAAI,CAACrE,SAASY,EAAE,EAAE;QAChB,OAAO;IACT;IAEA,yBAAyB;IACzB,IAAIvM,oBAAoB;IACtB,0EAA0E;IAC1E,2EAA2E;IAC3E,2EAA2E;IAC3E,sDAAsD;IACxD,OAAO;QACL,MAAMiQ,cAActE,SAASD,OAAO,CAACnJ,GAAG,CAAC;QACzC,MAAM2N,mBACJD,eAAeA,YAAY7E,UAAU,CAACtN;QACxC,IAAI,CAACoS,kBAAkB;YACrB,OAAO;QACT;IACF;IACA,OAAOvE;AACT;AAEA,SAASmB,6BACPqD,oBAAgD,EAChDC,aAAyB,EACzBrD,oBAA4C;IAE5C,0EAA0E;IAC1E,4EAA4E;IAC5E,uEAAuE;IACvE,0EAA0E;IAC1E,8DAA8D;IAC9D,2CAA2C;IAC3C,EAAE;IACF,2EAA2E;IAC3E,0EAA0E;IAC1E,8EAA8E;IAC9E,+BAA+B;IAC/B,EAAE;IACF,8EAA8E;IAC9E,iCAAiC;IACjC,IAAIsD,kBAAkB;IACtB,MAAMC,SAASH,qBAAqBI,SAAS;IAC7C,OAAO,IAAIC,eAAe;QACxB,MAAMC,MAAKC,UAAU;YACnB,MAAO,KAAM;gBACX,MAAM,EAAEC,IAAI,EAAE5G,KAAK,EAAE,GAAG,MAAMuG,OAAOM,IAAI;gBACzC,IAAI,CAACD,MAAM;oBACT,mEAAmE;oBACnE,mBAAmB;oBACnBD,WAAWG,OAAO,CAAC9G;oBAEnB,+DAA+D;oBAC/D,kEAAkE;oBAClE,qEAAqE;oBACrE,6CAA6C;oBAC7CsG,mBAAmBtG,MAAM+G,UAAU;oBACnC/D,qBAAqBsD;oBACrB;gBACF;gBACA,qEAAqE;gBACrE,sDAAsD;gBACtDD;gBACA;YACF;QACF;IACF;AACF;AAEA,SAAS9D,sCACPT,GAAQ,EACRJ,WAA8B;IAE9B,IAAIzL,oBAAoB;QACtB,yEAAyE;QACzE,0DAA0D;QAC1D,MAAM+Q,YAAY,IAAIhL,IAAI8F;QAC1B,MAAMmF,WAAWD,UAAUlL,QAAQ,CAACtC,QAAQ,CAAC,OACzCwN,UAAUlL,QAAQ,CAACoL,SAAS,CAAC,GAAG,CAAC,KACjCF,UAAUlL,QAAQ;QACtB,MAAMqL,uBACJhS,yCAAyCuM;QAC3CsF,UAAUlL,QAAQ,GAAG,AAAGmL,WAAS,MAAGE;QACpC,OAAOH;IACT;IACA,OAAOlF;AACT;AAEA;;;;;;;;;;;;;;;;;;;;CAoBC,GACD,OAAO,SAASlF,sCACdwK,eAA8B,EAC9BC,WAA0B;IAE1B,OAAOD,kBAAkBC;AAC3B","ignoreList":[0]}