{"version":3,"sources":["../../../src/server/app-render/vary-params.ts"],"sourcesContent":["import type { Params } from '../request/params'\nimport type { SearchParams } from '../request/search-params'\nimport { workUnitAsyncStorage } from './work-unit-async-storage.external'\nimport type {\n  VaryParamsThenable,\n  VaryParams,\n} from '../../shared/lib/segment-cache/vary-params-decoding'\n\n/**\n * Accumulates vary params for a single segment (or for metadata/rootParams).\n *\n * VaryParamsAccumulator is also a thenable that can be serialized by React\n * Flight. The accumulator starts as 'pending' and accumulates param accesses\n * during render. Call `finishTrackingVaryParams()` after rendering to resolve\n * all accumulators.\n *\n * The `status` and `value` fields follow the React Flight thenable protocol:\n * when `status === 'fulfilled'`, Flight can read `value` synchronously without\n * scheduling a microtask via `.then()`.\n */\nexport type VaryParamsAccumulator = {\n  // Mutable during render - accumulates param access\n  varyParams: VaryParams\n\n  // React thenable protocol fields\n  status: 'pending' | 'fulfilled'\n  value: VaryParams\n  then(\n    onfulfilled?: ((value: Set<string>) => unknown) | null,\n    onrejected?: ((reason: unknown) => unknown) | null\n  ): void\n\n  // Internal - callbacks waiting for resolution\n  resolvers: Array<(value: Set<string>) => void>\n}\n\n/**\n * A mutable data structure for accumulating per-segment vary params for an\n * entire server response. It's only used during prerenders. It describes\n * metadata about the response itself.\n */\nexport type ResponseVaryParamsAccumulator = {\n  /** Vary params accumulator for metadata/viewport (the \"head\" segment) */\n  head: VaryParamsAccumulator\n  /** Vary params accumulator for root params access */\n  rootParams: VaryParamsAccumulator\n  /** Vary params accumulators for each route segment */\n  segments: Set<VaryParamsAccumulator>\n}\n\nfunction createSegmentVaryParamsAccumulator(): VaryParamsAccumulator {\n  const accumulator: VaryParamsAccumulator = {\n    varyParams: new Set(),\n    status: 'pending',\n    value: new Set(),\n    then(onfulfilled: ((value: Set<string>) => unknown) | null | undefined) {\n      if (onfulfilled) {\n        if (accumulator.status === 'pending') {\n          accumulator.resolvers.push(onfulfilled)\n        } else {\n          onfulfilled(accumulator.value)\n        }\n      }\n    },\n    resolvers: [],\n  }\n  return accumulator\n}\n\n/**\n * A singleton accumulator that's already resolved to an empty Set. Use this for\n * segments where we know upfront that no params will be accessed, such as\n * client components or segments without user code.\n *\n * Benefits:\n * - No need to accumulate or resolve later\n * - Resilient: resolves correctly even if other tracking fails\n * - Memory efficient: reuses the same object\n */\nconst emptySet: VaryParams = new Set()\nexport const emptyVaryParamsAccumulator: VaryParamsAccumulator = {\n  varyParams: emptySet,\n  status: 'fulfilled',\n  value: emptySet,\n  then(onfulfilled: ((value: Set<string>) => unknown) | null | undefined) {\n    if (onfulfilled) {\n      onfulfilled(emptySet)\n    }\n  },\n  resolvers: [],\n}\n\nexport function createResponseVaryParamsAccumulator(): ResponseVaryParamsAccumulator {\n  // Create the head and rootParams accumulators as top-level fields.\n  // Segment accumulators are added to the segments set as they are created.\n  const head = createSegmentVaryParamsAccumulator()\n  const rootParams = createSegmentVaryParamsAccumulator()\n  const segments = new Set<VaryParamsAccumulator>()\n\n  return {\n    head,\n    rootParams,\n    segments,\n  }\n}\n\n/**\n * Allocates a new VaryParamsAccumulator and adds it to the response accumulator\n * associated with the current WorkUnitStore.\n *\n * Returns a thenable that resolves to the segment's vary params once rendering\n * is complete. The thenable can be passed directly to React Flight for\n * serialization.\n */\nexport function createVaryParamsAccumulator(): VaryParamsAccumulator | null {\n  const workUnitStore = workUnitAsyncStorage.getStore()\n  if (workUnitStore) {\n    switch (workUnitStore.type) {\n      case 'prerender':\n      case 'prerender-runtime': {\n        const responseAccumulator = workUnitStore.varyParamsAccumulator\n        if (responseAccumulator !== null) {\n          const accumulator = createSegmentVaryParamsAccumulator()\n          responseAccumulator.segments.add(accumulator)\n          return accumulator\n        }\n        return null\n      }\n      case 'prerender-ppr':\n      case 'prerender-legacy':\n      case 'request':\n      case 'cache':\n      case 'private-cache':\n      case 'prerender-client':\n      case 'validation-client':\n      case 'unstable-cache':\n      case 'generate-static-params':\n        break\n      default:\n        workUnitStore satisfies never\n    }\n  }\n  return null\n}\n\nexport function getMetadataVaryParamsAccumulator(): VaryParamsAccumulator | null {\n  const workUnitStore = workUnitAsyncStorage.getStore()\n  if (workUnitStore) {\n    switch (workUnitStore.type) {\n      case 'prerender':\n      case 'prerender-runtime': {\n        const responseAccumulator = workUnitStore.varyParamsAccumulator\n        if (responseAccumulator !== null) {\n          return responseAccumulator.head\n        }\n        return null\n      }\n      case 'prerender-ppr':\n      case 'prerender-legacy':\n      case 'request':\n      case 'cache':\n      case 'private-cache':\n      case 'prerender-client':\n      case 'validation-client':\n      case 'unstable-cache':\n      case 'generate-static-params':\n        return null\n      default:\n        workUnitStore satisfies never\n    }\n  }\n  return null\n}\n\nexport function getVaryParamsThenable(\n  accumulator: VaryParamsAccumulator\n): VaryParamsThenable | null {\n  return accumulator as unknown as VaryParamsThenable | null\n}\n\nexport function getMetadataVaryParamsThenable(): VaryParamsThenable | null {\n  const accumulator = getMetadataVaryParamsAccumulator()\n  if (accumulator !== null) {\n    return getVaryParamsThenable(accumulator)\n  }\n  return null\n}\n\n// The metadata and viewport are always delivered in a single payload, so they\n// don't need to be tracked separately. This may change in the future, but for\n// now this is just an alias.\nexport const getViewportVaryParamsAccumulator = getMetadataVaryParamsAccumulator\n\nexport function getRootParamsVaryParamsAccumulator(): VaryParamsAccumulator | null {\n  const workUnitStore = workUnitAsyncStorage.getStore()\n  if (workUnitStore) {\n    switch (workUnitStore.type) {\n      case 'prerender':\n      case 'prerender-runtime': {\n        const responseAccumulator = workUnitStore.varyParamsAccumulator\n        if (responseAccumulator !== null) {\n          return responseAccumulator.rootParams\n        }\n        return null\n      }\n      case 'prerender-ppr':\n      case 'prerender-legacy':\n      case 'request':\n      case 'cache':\n      case 'private-cache':\n      case 'prerender-client':\n      case 'validation-client':\n      case 'unstable-cache':\n      case 'generate-static-params':\n        return null\n      default:\n        workUnitStore satisfies never\n    }\n  }\n  return null\n}\n\n/**\n * Records that a param was accessed. Adds the param name to the accumulator's\n * varyParams set.\n */\nexport function accumulateVaryParam(\n  accumulator: VaryParamsAccumulator,\n  paramName: string\n): void {\n  accumulator.varyParams.add(paramName)\n}\n\n/**\n * Records a root param access.\n */\nexport function accumulateRootVaryParam(paramName: string): void {\n  const rootParamsAccumulator = getRootParamsVaryParamsAccumulator()\n  if (rootParamsAccumulator !== null) {\n    accumulateVaryParam(rootParamsAccumulator, paramName)\n  }\n}\n\nexport function createVaryingParams(\n  accumulator: VaryParamsAccumulator,\n  originalParamsObject: Params,\n  optionalCatchAllParamName: string | null\n): Params {\n  if (optionalCatchAllParamName !== null) {\n    // When there's an optional catch-all param with no value (e.g.,\n    // [[...slug]] at /), the param doesn't exist as a property on the params\n    // object. Use a Proxy to track all param access — both existing params\n    // and the missing optional param — including enumeration patterns like\n    // Object.keys(), spread, for...in, and `in` checks.\n    return new Proxy(originalParamsObject, {\n      get(target, prop, receiver) {\n        if (typeof prop === 'string') {\n          if (\n            prop === optionalCatchAllParamName ||\n            Object.prototype.hasOwnProperty.call(target, prop)\n          ) {\n            accumulateVaryParam(accumulator, prop)\n          }\n        }\n        return Reflect.get(target, prop, receiver)\n      },\n      has(target, prop) {\n        if (prop === optionalCatchAllParamName) {\n          accumulateVaryParam(accumulator, optionalCatchAllParamName)\n        }\n        return Reflect.has(target, prop)\n      },\n      ownKeys(target) {\n        // Enumerating the params object means the user's code may depend on\n        // which params are present, so conservatively track the optional\n        // param as accessed.\n        accumulateVaryParam(accumulator, optionalCatchAllParamName)\n        return Reflect.ownKeys(target)\n      },\n    })\n  }\n\n  // When there's no optional catch-all, all params exist as properties on the\n  // object, so we can use defineProperty getters instead of a Proxy. This is\n  // faster because the engine can optimize property access on regular objects\n  // more aggressively than Proxy trap calls.\n  const underlyingParamsWithVarying: Params = {}\n  for (const paramName in originalParamsObject) {\n    Object.defineProperty(underlyingParamsWithVarying, paramName, {\n      get() {\n        accumulateVaryParam(accumulator, paramName)\n        return originalParamsObject[paramName]\n      },\n      enumerable: true,\n    })\n  }\n  return underlyingParamsWithVarying\n}\n\nexport function createVaryingSearchParams(\n  accumulator: VaryParamsAccumulator,\n  originalSearchParamsObject: SearchParams\n): SearchParams {\n  const underlyingSearchParamsWithVarying: SearchParams = {}\n  for (const searchParamName in originalSearchParamsObject) {\n    Object.defineProperty(underlyingSearchParamsWithVarying, searchParamName, {\n      get() {\n        // TODO: Unlike path params, we don't vary track each search param\n        // individually. The entire search string is treated as a single param.\n        // This may change in the future.\n        accumulateVaryParam(accumulator, '?')\n        return originalSearchParamsObject[searchParamName]\n      },\n      enumerable: true,\n    })\n  }\n  return underlyingSearchParamsWithVarying\n}\n\n/**\n * Resolves all segment accumulators in a ResponseVaryParamsAccumulator with\n * their final vary params. Call this after rendering is complete.\n *\n * Each segment's thenable is resolved with its vary params merged with the\n * root params. If we can't track vary params (e.g., legacy prerender), simply\n * don't call this function - the client treats unresolved thenables as\n * \"unknown\" vary params.\n */\nexport async function finishAccumulatingVaryParams(\n  responseAccumulator: ResponseVaryParamsAccumulator\n): Promise<void> {\n  const rootVaryParams = responseAccumulator.rootParams.varyParams\n\n  // Resolve head\n  finishSegmentAccumulator(responseAccumulator.head, rootVaryParams)\n\n  // Resolve each segment\n  for (const segmentAccumulator of responseAccumulator.segments) {\n    finishSegmentAccumulator(segmentAccumulator, rootVaryParams)\n  }\n\n  // Now that the thenables are resolved, Flight should be able to flush the\n  // vary params into the response stream. This work gets scheduled internally\n  // by Flight using a microtask as soon as we notify the thenable listeners.\n  //\n  // We need to ensure that Flight's pending queues are emptied before this\n  // function returns; the caller will abort the prerender immediately after.\n  // We can't use a macrotask, because that would allow dynamic IO to sneak\n  // into the response. So we use microtasks instead.\n  //\n  // The exact number of awaits here isn't important (indeed, one seems to be\n  // sufficient, at the time of writing), as long as we wait enough ticks for\n  // Flight to finish writing the response.\n  //\n  // Anything that remains in Flight's internal queue after these awaits must\n  // be actual dynamic IO, not caused by pending vary params tasks. In other\n  // words, failing to do this would cause us to treat a fully static prerender\n  // as if it were partially dynamic.\n  await Promise.resolve()\n  await Promise.resolve()\n  await Promise.resolve()\n}\n\nfunction finishSegmentAccumulator(\n  accumulator: VaryParamsAccumulator,\n  rootVaryParams: VaryParams\n): void {\n  if (accumulator.status !== 'pending') {\n    return\n  }\n  const merged = new Set<string>(accumulator.varyParams)\n  for (const param of rootVaryParams) {\n    merged.add(param)\n  }\n  accumulator.value = merged\n  accumulator.status = 'fulfilled'\n  for (const resolver of accumulator.resolvers) {\n    resolver(merged)\n  }\n  accumulator.resolvers = []\n}\n"],"names":["accumulateRootVaryParam","accumulateVaryParam","createResponseVaryParamsAccumulator","createVaryParamsAccumulator","createVaryingParams","createVaryingSearchParams","emptyVaryParamsAccumulator","finishAccumulatingVaryParams","getMetadataVaryParamsAccumulator","getMetadataVaryParamsThenable","getRootParamsVaryParamsAccumulator","getVaryParamsThenable","getViewportVaryParamsAccumulator","createSegmentVaryParamsAccumulator","accumulator","varyParams","Set","status","value","then","onfulfilled","resolvers","push","emptySet","head","rootParams","segments","workUnitStore","workUnitAsyncStorage","getStore","type","responseAccumulator","varyParamsAccumulator","add","paramName","rootParamsAccumulator","originalParamsObject","optionalCatchAllParamName","Proxy","get","target","prop","receiver","Object","prototype","hasOwnProperty","call","Reflect","has","ownKeys","underlyingParamsWithVarying","defineProperty","enumerable","originalSearchParamsObject","underlyingSearchParamsWithVarying","searchParamName","rootVaryParams","finishSegmentAccumulator","segmentAccumulator","Promise","resolve","merged","param","resolver"],"mappings":"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","ignoreList":[0]}