{"version":3,"sources":["../../../src/server/app-render/postponed-state.ts"],"sourcesContent":["import type {\n  OpaqueFallbackRouteParamEntries,\n  OpaqueFallbackRouteParams,\n} from '../../server/request/fallback-params'\nimport { getDynamicParam } from '../../shared/lib/router/utils/get-dynamic-param'\nimport type { Params } from '../request/params'\nimport {\n  createPrerenderResumeDataCache,\n  createRenderResumeDataCache,\n  type PrerenderResumeDataCache,\n  type RenderResumeDataCache,\n} from '../resume-data-cache/resume-data-cache'\nimport { stringifyResumeDataCache } from '../resume-data-cache/resume-data-cache'\n\nexport enum DynamicState {\n  /**\n   * The dynamic access occurred during the RSC render phase.\n   */\n  DATA = 1,\n\n  /**\n   * The dynamic access occurred during the HTML shell render phase.\n   */\n  HTML = 2,\n}\n\n/**\n * The postponed state for dynamic data.\n */\nexport type DynamicDataPostponedState = {\n  /**\n   * The type of dynamic state.\n   */\n  readonly type: DynamicState.DATA\n\n  /**\n   * The immutable resume data cache.\n   */\n  readonly renderResumeDataCache: RenderResumeDataCache\n}\n\n/**\n * The postponed state for dynamic HTML.\n */\nexport type DynamicHTMLPostponedState = {\n  /**\n   * The type of dynamic state.\n   */\n  readonly type: DynamicState.HTML\n\n  /**\n   * The postponed data used by React.\n   */\n  readonly data: [\n    preludeState: DynamicHTMLPreludeState,\n    postponed: ReactPostponed,\n  ]\n\n  /**\n   * The immutable resume data cache.\n   */\n  readonly renderResumeDataCache: RenderResumeDataCache\n}\n\nexport const enum DynamicHTMLPreludeState {\n  Empty = 0,\n  Full = 1,\n}\n\ntype ReactPostponed = NonNullable<\n  import('react-dom/static').PrerenderResult['postponed']\n>\n\nexport type PostponedState =\n  | DynamicDataPostponedState\n  | DynamicHTMLPostponedState\n\nexport async function getDynamicHTMLPostponedState(\n  postponed: ReactPostponed,\n  preludeState: DynamicHTMLPreludeState,\n  fallbackRouteParams: OpaqueFallbackRouteParams | null,\n  resumeDataCache: PrerenderResumeDataCache | RenderResumeDataCache,\n  isCacheComponentsEnabled: boolean\n): Promise<string> {\n  const data: DynamicHTMLPostponedState['data'] = [preludeState, postponed]\n  const dataString = JSON.stringify(data)\n\n  // If there are no fallback route params, we can just serialize the postponed\n  // state as is.\n  if (!fallbackRouteParams || fallbackRouteParams.size === 0) {\n    // Serialized as `<postponedString.length>:<postponedString><renderResumeDataCache>`\n    return `${dataString.length}:${dataString}${await stringifyResumeDataCache(\n      createRenderResumeDataCache(resumeDataCache),\n      isCacheComponentsEnabled\n    )}`\n  }\n\n  const replacements: OpaqueFallbackRouteParamEntries = Array.from(\n    fallbackRouteParams.entries()\n  )\n  const replacementsString = JSON.stringify(replacements)\n\n  // Serialized as `<replacements.length><replacements><data>`\n  const postponedString = `${replacementsString.length}${replacementsString}${dataString}`\n\n  // Serialized as `<postponedString.length>:<postponedString><renderResumeDataCache>`\n  return `${postponedString.length}:${postponedString}${await stringifyResumeDataCache(resumeDataCache, isCacheComponentsEnabled)}`\n}\n\nexport async function getDynamicDataPostponedState(\n  resumeDataCache: PrerenderResumeDataCache | RenderResumeDataCache,\n  isCacheComponentsEnabled: boolean\n): Promise<string> {\n  return `4:null${await stringifyResumeDataCache(createRenderResumeDataCache(resumeDataCache), isCacheComponentsEnabled)}`\n}\n\nexport function parsePostponedState(\n  state: string,\n  interpolatedParams: Params,\n  maxPostponedStateSizeBytes: number | undefined\n): PostponedState {\n  try {\n    const postponedStringLengthMatch = state.match(/^([0-9]*):/)?.[1]\n    if (!postponedStringLengthMatch) {\n      throw new Error(`Invariant: invalid postponed state ${state}`)\n    }\n\n    const postponedStringLength = parseInt(postponedStringLengthMatch)\n\n    // We add a `:` to the end of the length as the first character of the\n    // postponed string is the length of the replacement entries.\n    const postponedString = state.slice(\n      postponedStringLengthMatch.length + 1,\n      postponedStringLengthMatch.length + postponedStringLength + 1\n    )\n\n    const renderResumeDataCache = createRenderResumeDataCache(\n      state.slice(\n        postponedStringLengthMatch.length + postponedStringLength + 1\n      ),\n      maxPostponedStateSizeBytes\n    )\n\n    try {\n      if (postponedString === 'null') {\n        return { type: DynamicState.DATA, renderResumeDataCache }\n      }\n\n      if (/^[0-9]/.test(postponedString)) {\n        const match = postponedString.match(/^([0-9]*)/)?.[1]\n        if (!match) {\n          throw new Error(\n            `Invariant: invalid postponed state ${JSON.stringify(postponedString)}`\n          )\n        }\n\n        // This is the length of the replacements entries.\n        const length = parseInt(match)\n        const replacements = JSON.parse(\n          postponedString.slice(\n            match.length,\n            // We then go to the end of the string.\n            match.length + length\n          )\n        ) as OpaqueFallbackRouteParamEntries\n\n        let postponed = postponedString.slice(match.length + length)\n        for (const [\n          segmentKey,\n          [searchValue, dynamicParamType],\n        ] of replacements) {\n          const {\n            treeSegment: [\n              ,\n              // This is the same value that'll be used in the postponed state\n              // as it's part of the tree data. That's why we use it as the\n              // replacement value.\n              value,\n            ],\n          } = getDynamicParam(\n            interpolatedParams,\n            segmentKey,\n            dynamicParamType,\n            null,\n            null // staticSiblings not needed for postponed state\n          )\n\n          postponed = postponed.replaceAll(searchValue, value)\n        }\n\n        return {\n          type: DynamicState.HTML,\n          data: JSON.parse(postponed),\n          renderResumeDataCache,\n        }\n      }\n\n      return {\n        type: DynamicState.HTML,\n        data: JSON.parse(postponedString),\n        renderResumeDataCache,\n      }\n    } catch (err) {\n      console.error('Failed to parse postponed state', err)\n      return { type: DynamicState.DATA, renderResumeDataCache }\n    }\n  } catch (err) {\n    console.error('Failed to parse postponed state', err)\n    return {\n      type: DynamicState.DATA,\n      renderResumeDataCache: createPrerenderResumeDataCache(),\n    }\n  }\n}\n\nexport function getPostponedFromState(state: DynamicHTMLPostponedState) {\n  const [preludeState, postponed] = state.data\n  return { preludeState, postponed }\n}\n"],"names":["DynamicHTMLPreludeState","DynamicState","getDynamicDataPostponedState","getDynamicHTMLPostponedState","getPostponedFromState","parsePostponedState","postponed","preludeState","fallbackRouteParams","resumeDataCache","isCacheComponentsEnabled","data","dataString","JSON","stringify","size","length","stringifyResumeDataCache","createRenderResumeDataCache","replacements","Array","from","entries","replacementsString","postponedString","state","interpolatedParams","maxPostponedStateSizeBytes","postponedStringLengthMatch","match","Error","postponedStringLength","parseInt","slice","renderResumeDataCache","type","test","parse","segmentKey","searchValue","dynamicParamType","treeSegment","value","getDynamicParam","replaceAll","err","console","error","createPrerenderResumeDataCache"],"mappings":"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","ignoreList":[0]}