{"version":3,"sources":["../../../../src/client/components/segment-cache-impl/navigation.ts"],"sourcesContent":["import type {\n  CacheNodeSeedData,\n  FlightRouterState,\n  FlightSegmentPath,\n} from '../../../server/app-render/types'\nimport type {\n  CacheNode,\n  HeadData,\n  LoadingModuleData,\n} from '../../../shared/lib/app-router-context.shared-runtime'\nimport type { NormalizedFlightData } from '../../flight-data-helpers'\nimport { fetchServerResponse } from '../router-reducer/fetch-server-response'\nimport {\n  startPPRNavigation,\n  listenForDynamicRequest,\n  type Task as PPRNavigationTask,\n} from '../router-reducer/ppr-navigations'\nimport { createHrefFromUrl as createCanonicalUrl } from '../router-reducer/create-href-from-url'\nimport {\n  EntryStatus,\n  readRouteCacheEntry,\n  readSegmentCacheEntry,\n  waitForSegmentCacheEntry,\n  requestOptimisticRouteCacheEntry,\n  type RouteTree,\n  type FulfilledRouteCacheEntry,\n} from './cache'\nimport { createCacheKey } from './cache-key'\nimport { addSearchParamsIfPageSegment } from '../../../shared/lib/segment'\nimport { NavigationResultTag } from '../segment-cache'\n\ntype MPANavigationResult = {\n  tag: NavigationResultTag.MPA\n  data: string\n}\n\ntype NoOpNavigationResult = {\n  tag: NavigationResultTag.NoOp\n  data: {\n    canonicalUrl: string\n    shouldScroll: boolean\n  }\n}\n\ntype SuccessfulNavigationResult = {\n  tag: NavigationResultTag.Success\n  data: {\n    flightRouterState: FlightRouterState\n    cacheNode: CacheNode\n    canonicalUrl: string\n    scrollableSegments: Array<FlightSegmentPath>\n    shouldScroll: boolean\n    hash: string\n  }\n}\n\ntype AsyncNavigationResult = {\n  tag: NavigationResultTag.Async\n  data: Promise<\n    MPANavigationResult | NoOpNavigationResult | SuccessfulNavigationResult\n  >\n}\n\nexport type NavigationResult =\n  | MPANavigationResult\n  | SuccessfulNavigationResult\n  | NoOpNavigationResult\n  | AsyncNavigationResult\n\n/**\n * Navigate to a new URL, using the Segment Cache to construct a response.\n *\n * To allow for synchronous navigations whenever possible, this is not an async\n * function. It returns a promise only if there's no matching prefetch in\n * the cache. Otherwise it returns an immediate result and uses Suspense/RSC to\n * stream in any missing data.\n */\nexport function navigate(\n  url: URL,\n  currentCacheNode: CacheNode,\n  currentFlightRouterState: FlightRouterState,\n  nextUrl: string | null,\n  shouldScroll: boolean\n): NavigationResult {\n  const now = Date.now()\n  const href = url.href\n\n  // We special case navigations to the exact same URL as the current location.\n  // It's a common UI pattern for apps to refresh when you click a link to the\n  // current page. So when this happens, we refresh the dynamic data in the page\n  // segments.\n  //\n  // Note that this does not apply if the any part of the hash or search query\n  // has changed. This might feel a bit weird but it makes more sense when you\n  // consider that the way to trigger this behavior is to click the same link\n  // multiple times.\n  //\n  // TODO: We should probably refresh the *entire* route when this case occurs,\n  // not just the page segments. Essentially treating it the same as a refresh()\n  // triggered by an action, which is the more explicit way of modeling the UI\n  // pattern described above.\n  //\n  // Also note that this only refreshes the dynamic data, not static/ cached\n  // data. If the page segment is fully static and prefetched, the request is\n  // skipped. (This is also how refresh() works.)\n  const isSamePageNavigation =\n    // TODO: This is not the only place we read from the location, but we should\n    // consider storing the current URL in the router state instead of reading\n    // from the location object. In practice I don't think this matters much\n    // since we keep them in sync anyway, but having two sources of truth can\n    // lead to subtle bugs and race conditions.\n    href === window.location.href\n\n  const cacheKey = createCacheKey(href, nextUrl)\n  const route = readRouteCacheEntry(now, cacheKey)\n  if (route !== null && route.status === EntryStatus.Fulfilled) {\n    // We have a matching prefetch.\n    const snapshot = readRenderSnapshotFromCache(now, route, route.tree)\n    const prefetchFlightRouterState = snapshot.flightRouterState\n    const prefetchSeedData = snapshot.seedData\n    const prefetchHead = route.head\n    const isPrefetchHeadPartial = route.isHeadPartial\n    const newCanonicalUrl = route.canonicalUrl\n    return navigateUsingPrefetchedRouteTree(\n      now,\n      url,\n      nextUrl,\n      isSamePageNavigation,\n      currentCacheNode,\n      currentFlightRouterState,\n      prefetchFlightRouterState,\n      prefetchSeedData,\n      prefetchHead,\n      isPrefetchHeadPartial,\n      newCanonicalUrl,\n      shouldScroll,\n      url.hash\n    )\n  }\n\n  // There was no matching route tree in the cache. Let's see if we can\n  // construct an \"optimistic\" route tree.\n  const optimisticRoute = requestOptimisticRouteCacheEntry(now, url, nextUrl)\n  if (optimisticRoute !== null) {\n    // We have an optimistic route tree. Proceed with the normal flow.\n    const snapshot = readRenderSnapshotFromCache(\n      now,\n      optimisticRoute,\n      optimisticRoute.tree\n    )\n    const prefetchFlightRouterState = snapshot.flightRouterState\n    const prefetchSeedData = snapshot.seedData\n    const prefetchHead = optimisticRoute.head\n    const isPrefetchHeadPartial = optimisticRoute.isHeadPartial\n    const newCanonicalUrl = optimisticRoute.canonicalUrl\n    return navigateUsingPrefetchedRouteTree(\n      now,\n      url,\n      nextUrl,\n      isSamePageNavigation,\n      currentCacheNode,\n      currentFlightRouterState,\n      prefetchFlightRouterState,\n      prefetchSeedData,\n      prefetchHead,\n      isPrefetchHeadPartial,\n      newCanonicalUrl,\n      shouldScroll,\n      url.hash\n    )\n  }\n\n  // There's no matching prefetch for this route in the cache.\n  return {\n    tag: NavigationResultTag.Async,\n    data: navigateDynamicallyWithNoPrefetch(\n      now,\n      url,\n      nextUrl,\n      isSamePageNavigation,\n      currentCacheNode,\n      currentFlightRouterState,\n      shouldScroll,\n      url.hash\n    ),\n  }\n}\n\nfunction navigateUsingPrefetchedRouteTree(\n  now: number,\n  url: URL,\n  nextUrl: string | null,\n  isSamePageNavigation: boolean,\n  currentCacheNode: CacheNode,\n  currentFlightRouterState: FlightRouterState,\n  prefetchFlightRouterState: FlightRouterState,\n  prefetchSeedData: CacheNodeSeedData | null,\n  prefetchHead: HeadData | null,\n  isPrefetchHeadPartial: boolean,\n  canonicalUrl: string,\n  shouldScroll: boolean,\n  hash: string\n): SuccessfulNavigationResult | NoOpNavigationResult | MPANavigationResult {\n  // Recursively construct a prefetch tree by reading from the Segment Cache. To\n  // maintain compatibility, we output the same data structures as the old\n  // prefetching implementation: FlightRouterState and CacheNodeSeedData.\n  // TODO: Eventually updateCacheNodeOnNavigation (or the equivalent) should\n  // read from the Segment Cache directly. It's only structured this way for now\n  // so we can share code with the old prefetching implementation.\n  const scrollableSegments: Array<FlightSegmentPath> = []\n  const task = startPPRNavigation(\n    now,\n    currentCacheNode,\n    currentFlightRouterState,\n    prefetchFlightRouterState,\n    prefetchSeedData,\n    prefetchHead,\n    isPrefetchHeadPartial,\n    isSamePageNavigation,\n    scrollableSegments\n  )\n  if (task !== null) {\n    const dynamicRequestTree = task.dynamicRequestTree\n    if (dynamicRequestTree !== null) {\n      const promiseForDynamicServerResponse = fetchServerResponse(\n        new URL(canonicalUrl, url.origin),\n        {\n          flightRouterState: dynamicRequestTree,\n          nextUrl,\n        }\n      )\n      listenForDynamicRequest(task, promiseForDynamicServerResponse)\n    } else {\n      // The prefetched tree does not contain dynamic holes — it's\n      // fully static. We can skip the dynamic request.\n    }\n    return navigationTaskToResult(\n      task,\n      currentCacheNode,\n      canonicalUrl,\n      scrollableSegments,\n      shouldScroll,\n      hash\n    )\n  }\n  // The server sent back an empty tree patch. There's nothing to update, except\n  // possibly the URL.\n  return {\n    tag: NavigationResultTag.NoOp,\n    data: {\n      canonicalUrl,\n      shouldScroll,\n    },\n  }\n}\n\nfunction navigationTaskToResult(\n  task: PPRNavigationTask,\n  currentCacheNode: CacheNode,\n  canonicalUrl: string,\n  scrollableSegments: Array<FlightSegmentPath>,\n  shouldScroll: boolean,\n  hash: string\n): SuccessfulNavigationResult | MPANavigationResult {\n  const flightRouterState = task.route\n  if (flightRouterState === null) {\n    // When no router state is provided, it signals that we should perform an\n    // MPA navigation.\n    return {\n      tag: NavigationResultTag.MPA,\n      data: canonicalUrl,\n    }\n  }\n  const newCacheNode = task.node\n  return {\n    tag: NavigationResultTag.Success,\n    data: {\n      flightRouterState,\n      cacheNode: newCacheNode !== null ? newCacheNode : currentCacheNode,\n      canonicalUrl,\n      scrollableSegments,\n      shouldScroll,\n      hash,\n    },\n  }\n}\n\nfunction readRenderSnapshotFromCache(\n  now: number,\n  route: FulfilledRouteCacheEntry,\n  tree: RouteTree\n): { flightRouterState: FlightRouterState; seedData: CacheNodeSeedData } {\n  let childRouterStates: { [parallelRouteKey: string]: FlightRouterState } = {}\n  let childSeedDatas: {\n    [parallelRouteKey: string]: CacheNodeSeedData | null\n  } = {}\n  const slots = tree.slots\n  if (slots !== null) {\n    for (const parallelRouteKey in slots) {\n      const childTree = slots[parallelRouteKey]\n      const childResult = readRenderSnapshotFromCache(now, route, childTree)\n      childRouterStates[parallelRouteKey] = childResult.flightRouterState\n      childSeedDatas[parallelRouteKey] = childResult.seedData\n    }\n  }\n\n  let rsc: React.ReactNode | null = null\n  let loading: LoadingModuleData | Promise<LoadingModuleData> = null\n  let isPartial: boolean = true\n\n  const segmentEntry = readSegmentCacheEntry(now, route, tree.cacheKey)\n  if (segmentEntry !== null) {\n    switch (segmentEntry.status) {\n      case EntryStatus.Fulfilled: {\n        // Happy path: a cache hit\n        rsc = segmentEntry.rsc\n        loading = segmentEntry.loading\n        isPartial = segmentEntry.isPartial\n        break\n      }\n      case EntryStatus.Pending: {\n        // We haven't received data for this segment yet, but there's already\n        // an in-progress request. Since it's extremely likely to arrive\n        // before the dynamic data response, we might as well use it.\n        const promiseForFulfilledEntry = waitForSegmentCacheEntry(segmentEntry)\n        rsc = promiseForFulfilledEntry.then((entry) =>\n          entry !== null ? entry.rsc : null\n        )\n        loading = promiseForFulfilledEntry.then((entry) =>\n          entry !== null ? entry.loading : null\n        )\n        // Since we don't know yet whether the segment is partial or fully\n        // static, we must assume it's partial; we can't skip the\n        // dynamic request.\n        isPartial = true\n        break\n      }\n      case EntryStatus.Empty:\n      case EntryStatus.Rejected:\n        break\n      default:\n        segmentEntry satisfies never\n    }\n  }\n\n  // The navigation implementation expects the search params to be\n  // included in the segment. However, the Segment Cache tracks search\n  // params separately from the rest of the segment key. So we need to\n  // add them back here.\n  //\n  // See corresponding comment in convertFlightRouterStateToTree.\n  //\n  // TODO: What we should do instead is update the navigation diffing\n  // logic to compare search params explicitly. This is a temporary\n  // solution until more of the Segment Cache implementation has settled.\n  const segment = addSearchParamsIfPageSegment(\n    tree.segment,\n    Object.fromEntries(new URLSearchParams(route.renderedSearch))\n  )\n\n  return {\n    flightRouterState: [\n      segment,\n      childRouterStates,\n      null,\n      null,\n      tree.isRootLayout,\n    ],\n    seedData: [segment, rsc, childSeedDatas, loading, isPartial],\n  }\n}\n\nasync function navigateDynamicallyWithNoPrefetch(\n  now: number,\n  url: URL,\n  nextUrl: string | null,\n  isSamePageNavigation: boolean,\n  currentCacheNode: CacheNode,\n  currentFlightRouterState: FlightRouterState,\n  shouldScroll: boolean,\n  hash: string\n): Promise<\n  MPANavigationResult | SuccessfulNavigationResult | NoOpNavigationResult\n> {\n  // Runs when a navigation happens but there's no cached prefetch we can use.\n  // Don't bother to wait for a prefetch response; go straight to a full\n  // navigation that contains both static and dynamic data in a single stream.\n  // (This is unlike the old navigation implementation, which instead blocks\n  // the dynamic request until a prefetch request is received.)\n  //\n  // To avoid duplication of logic, we're going to pretend that the tree\n  // returned by the dynamic request is, in fact, a prefetch tree. Then we can\n  // use the same server response to write the actual data into the CacheNode\n  // tree. So it's the same flow as the \"happy path\" (prefetch, then\n  // navigation), except we use a single server response for both stages.\n\n  const promiseForDynamicServerResponse = fetchServerResponse(url, {\n    flightRouterState: currentFlightRouterState,\n    nextUrl,\n  })\n  const { flightData, canonicalUrl: canonicalUrlOverride } =\n    await promiseForDynamicServerResponse\n\n  if (typeof flightData === 'string') {\n    // This is an MPA navigation.\n    const newUrl = flightData\n    return {\n      tag: NavigationResultTag.MPA,\n      data: newUrl,\n    }\n  }\n\n  // Since the response format of dynamic requests and prefetches is slightly\n  // different, we'll need to massage the data a bit. Create FlightRouterState\n  // tree that simulates what we'd receive as the result of a prefetch.\n  const prefetchFlightRouterState = simulatePrefetchTreeUsingDynamicTreePatch(\n    currentFlightRouterState,\n    flightData\n  )\n\n  // In our simulated prefetch payload, we pretend that there's no seed data\n  // nor a prefetch head.\n  const prefetchSeedData = null\n  const prefetchHead = null\n  const isPrefetchHeadPartial = true\n\n  const canonicalUrl = createCanonicalUrl(\n    canonicalUrlOverride ? canonicalUrlOverride : url\n  )\n\n  // Now we proceed exactly as we would for normal navigation.\n  const scrollableSegments: Array<FlightSegmentPath> = []\n  const task = startPPRNavigation(\n    now,\n    currentCacheNode,\n    currentFlightRouterState,\n    prefetchFlightRouterState,\n    prefetchSeedData,\n    prefetchHead,\n    isPrefetchHeadPartial,\n    isSamePageNavigation,\n    scrollableSegments\n  )\n  if (task !== null) {\n    // In this case, we've already sent the dynamic request, so we don't\n    // actually use the request tree created by `startPPRNavigation`,\n    // except to check if it contains dynamic holes.\n    //\n    // This is almost always true, but it could be false if all the segment data\n    // was present in the cache, but the route tree was not. E.g. navigating\n    // to a URL that was not prefetched but rewrites to a different URL\n    // that was.\n    const hasDynamicHoles = task.dynamicRequestTree !== null\n    if (hasDynamicHoles) {\n      listenForDynamicRequest(task, promiseForDynamicServerResponse)\n    } else {\n      // The prefetched tree does not contain dynamic holes — it's\n      // fully static. We don't need to process the server response further.\n    }\n    return navigationTaskToResult(\n      task,\n      currentCacheNode,\n      canonicalUrl,\n      scrollableSegments,\n      shouldScroll,\n      hash\n    )\n  }\n  // The server sent back an empty tree patch. There's nothing to update, except\n  // possibly the URL.\n  return {\n    tag: NavigationResultTag.NoOp,\n    data: {\n      canonicalUrl,\n      shouldScroll,\n    },\n  }\n}\n\nfunction simulatePrefetchTreeUsingDynamicTreePatch(\n  currentTree: FlightRouterState,\n  flightData: Array<NormalizedFlightData>\n): FlightRouterState {\n  // Takes the current FlightRouterState and applies the router state patch\n  // received from the server, to create a full FlightRouterState tree that we\n  // can pretend was returned by a prefetch.\n  //\n  // (It sounds similar to what applyRouterStatePatch does, but it doesn't need\n  // to handle stuff like interception routes or diffing since that will be\n  // handled later.)\n  let baseTree = currentTree\n  for (const { segmentPath, tree: treePatch } of flightData) {\n    // If the server sends us multiple tree patches, we only need to clone the\n    // base tree when applying the first patch. After the first patch, we can\n    // apply the remaining patches in place without copying.\n    const canMutateInPlace = baseTree !== currentTree\n    baseTree = simulatePrefetchTreeUsingDynamicTreePatchImpl(\n      baseTree,\n      treePatch,\n      segmentPath,\n      canMutateInPlace,\n      0\n    )\n  }\n\n  return baseTree\n}\n\nfunction simulatePrefetchTreeUsingDynamicTreePatchImpl(\n  baseRouterState: FlightRouterState,\n  patch: FlightRouterState,\n  segmentPath: FlightSegmentPath,\n  canMutateInPlace: boolean,\n  index: number\n) {\n  if (index === segmentPath.length) {\n    // We reached the part of the tree that we need to patch.\n    return patch\n  }\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  //\n  // This path tells us which part of the base tree to apply the tree patch.\n  //\n  // NOTE: In the case of a fully dynamic request with no prefetch, we receive\n  // the FlightRouterState patch in the same request as the dynamic data.\n  // Therefore we don't need to worry about diffing the segment values; we can\n  // assume the server sent us a correct result.\n  const updatedParallelRouteKey: string = segmentPath[index]\n  // const segment: Segment = segmentPath[index + 1] <-- Not used, see note above\n\n  const baseChildren = baseRouterState[1]\n  const newChildren: { [parallelRouteKey: string]: FlightRouterState } = {}\n  for (const parallelRouteKey in baseChildren) {\n    if (parallelRouteKey === updatedParallelRouteKey) {\n      const childBaseRouterState = baseChildren[parallelRouteKey]\n      newChildren[parallelRouteKey] =\n        simulatePrefetchTreeUsingDynamicTreePatchImpl(\n          childBaseRouterState,\n          patch,\n          segmentPath,\n          canMutateInPlace,\n          // Advance the index by two and keep cloning until we reach\n          // the end of the segment path.\n          index + 2\n        )\n    } else {\n      // This child is not being patched. Copy it over as-is.\n      newChildren[parallelRouteKey] = baseChildren[parallelRouteKey]\n    }\n  }\n\n  if (canMutateInPlace) {\n    // We can mutate the base tree in place, because the base tree is already\n    // a clone.\n    baseRouterState[1] = newChildren\n    return baseRouterState\n  }\n\n  // Clone all the fields except the children.\n  //\n  // Based on equivalent logic in apply-router-state-patch-to-tree, but should\n  // confirm whether we need to copy all of these fields. Not sure the server\n  // ever sends, e.g. the refetch marker.\n  const clone: FlightRouterState = [baseRouterState[0], newChildren]\n  if (2 in baseRouterState) {\n    clone[2] = baseRouterState[2]\n  }\n  if (3 in baseRouterState) {\n    clone[3] = baseRouterState[3]\n  }\n  if (4 in baseRouterState) {\n    clone[4] = baseRouterState[4]\n  }\n  return clone\n}\n"],"names":["fetchServerResponse","startPPRNavigation","listenForDynamicRequest","createHrefFromUrl","createCanonicalUrl","EntryStatus","readRouteCacheEntry","readSegmentCacheEntry","waitForSegmentCacheEntry","requestOptimisticRouteCacheEntry","createCacheKey","addSearchParamsIfPageSegment","NavigationResultTag","navigate","url","currentCacheNode","currentFlightRouterState","nextUrl","shouldScroll","now","Date","href","isSamePageNavigation","window","location","cacheKey","route","status","Fulfilled","snapshot","readRenderSnapshotFromCache","tree","prefetchFlightRouterState","flightRouterState","prefetchSeedData","seedData","prefetchHead","head","isPrefetchHeadPartial","isHeadPartial","newCanonicalUrl","canonicalUrl","navigateUsingPrefetchedRouteTree","hash","optimisticRoute","tag","Async","data","navigateDynamicallyWithNoPrefetch","scrollableSegments","task","dynamicRequestTree","promiseForDynamicServerResponse","URL","origin","navigationTaskToResult","NoOp","MPA","newCacheNode","node","Success","cacheNode","childRouterStates","childSeedDatas","slots","parallelRouteKey","childTree","childResult","rsc","loading","isPartial","segmentEntry","Pending","promiseForFulfilledEntry","then","entry","Empty","Rejected","segment","Object","fromEntries","URLSearchParams","renderedSearch","isRootLayout","flightData","canonicalUrlOverride","newUrl","simulatePrefetchTreeUsingDynamicTreePatch","hasDynamicHoles","currentTree","baseTree","segmentPath","treePatch","canMutateInPlace","simulatePrefetchTreeUsingDynamicTreePatchImpl","baseRouterState","patch","index","length","updatedParallelRouteKey","baseChildren","newChildren","childBaseRouterState","clone"],"mappings":"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","ignoreList":[0]}