{
  "version": 3,
  "sources": ["../../../src/core/mutation-invalidation.ts"],
  "sourcesContent": [
    "import type { WorkbookManager } from \"./managers/workbook-manager.mjs\";\nimport type {\n  CellAddress,\n  RangeAddress,\n  SerializedCellValue,\n  TableDefinition,\n} from \"./types.mjs\";\nimport { getNamedExpressionResourceKey } from \"./resource-keys.mjs\";\nimport { getCellReference, parseCellReference } from \"./utils.mjs\";\n\ntype CellContentKind = \"empty\" | \"scalar\" | \"formula\";\n\nexport type RemovedScope =\n  | { type: \"workbook\"; workbookName: string }\n  | { type: \"sheet\"; workbookName: string; sheetName: string };\n\nexport type MutationInvalidation = {\n  touchedCells: Array<{\n    address: CellAddress;\n    beforeKind: CellContentKind;\n    afterKind: CellContentKind;\n  }>;\n  /**\n   * Cells whose table membership or implicit current-row table context changed\n   * without necessarily changing their formula text.\n   */\n  tableContextChangedCells?: CellAddress[];\n  resourceKeys: string[];\n  removedScopes?: RemovedScope[];\n};\n\nfunction getSerializedCellValueKind(\n  value: SerializedCellValue | undefined\n): CellContentKind {\n  if (\n    value === undefined ||\n    (typeof value === \"string\" && value.length === 0)\n  ) {\n    return \"empty\";\n  }\n  if (typeof value === \"string\" && value.startsWith(\"=\")) {\n    return \"formula\";\n  }\n  return \"scalar\";\n}\n\nfunction emptyMutationInvalidation(): MutationInvalidation {\n  return {\n    touchedCells: [],\n    resourceKeys: [],\n  };\n}\n\nexport function getMutationAddressKey(address: CellAddress): string {\n  return `${address.workbookName}:${address.sheetName}:${getCellReference(\n    address\n  )}`;\n}\n\nexport function buildTouchedCells(\n  cells: Array<{\n    address: CellAddress;\n    before: SerializedCellValue | undefined;\n    after: SerializedCellValue | undefined;\n  }>\n): MutationInvalidation[\"touchedCells\"] {\n  const deduped = new Map<\n    string,\n    MutationInvalidation[\"touchedCells\"][number]\n  >();\n\n  for (const cell of cells) {\n    deduped.set(getMutationAddressKey(cell.address), {\n      address: cell.address,\n      beforeKind: getSerializedCellValueKind(cell.before),\n      afterKind: getSerializedCellValueKind(cell.after),\n    });\n  }\n\n  return Array.from(deduped.values());\n}\n\nexport function buildFormulaTouchedCells(\n  cells: CellAddress[]\n): MutationInvalidation[\"touchedCells\"] {\n  return cells.map((address) => ({\n    address,\n    beforeKind: \"formula\",\n    afterKind: \"formula\",\n  }));\n}\n\nexport function captureCellContents(\n  workbookManager: WorkbookManager,\n  addresses: CellAddress[]\n): Map<string, SerializedCellValue | undefined> {\n  const contents = new Map<string, SerializedCellValue | undefined>();\n  for (const address of addresses) {\n    try {\n      contents.set(\n        getMutationAddressKey(address),\n        workbookManager.getCellContent(address)\n      );\n    } catch {\n      contents.set(getMutationAddressKey(address), undefined);\n    }\n  }\n  return contents;\n}\n\nexport function buildSheetContentTouchedCells(\n  opts: { workbookName: string; sheetName: string },\n  beforeContent: Map<string, SerializedCellValue> | undefined,\n  afterContent: Map<string, SerializedCellValue>\n): MutationInvalidation[\"touchedCells\"] {\n  const touchedKeys = new Set<string>([\n    ...Array.from(beforeContent?.keys() ?? []),\n    ...Array.from(afterContent.keys()),\n  ]);\n\n  return buildTouchedCells(\n    Array.from(touchedKeys, (key) => ({\n      address: {\n        workbookName: opts.workbookName,\n        sheetName: opts.sheetName,\n        ...parseCellReference(key),\n      },\n      before: beforeContent?.get(key),\n      after: afterContent.get(key),\n    }))\n  );\n}\n\nfunction getTableCellKey(address: CellAddress): string {\n  return `${address.workbookName}:${address.sheetName}:${address.rowIndex}:${address.colIndex}`;\n}\n\nfunction collectTableFootprintCells(\n  workbookManager: WorkbookManager,\n  table: TableDefinition\n): Array<{\n  address: CellAddress;\n  content: SerializedCellValue | undefined;\n}> {\n  const cells = new Map<\n    string,\n    {\n      address: CellAddress;\n      content: SerializedCellValue | undefined;\n    }\n  >();\n  const sheet = workbookManager.getSheet({\n    workbookName: table.workbookName,\n    sheetName: table.sheetName,\n  });\n  if (!sheet) {\n    return [];\n  }\n\n  const startColIndex = table.start.colIndex;\n  const endColIndex = startColIndex + table.headers.size - 1;\n\n  if (table.endRow.type === \"number\") {\n    for (\n      let rowIndex = table.start.rowIndex;\n      rowIndex <= table.endRow.value;\n      rowIndex++\n    ) {\n      for (\n        let colIndex = startColIndex;\n        colIndex <= endColIndex;\n        colIndex++\n      ) {\n        const address = {\n          workbookName: table.workbookName,\n          sheetName: table.sheetName,\n          rowIndex,\n          colIndex,\n        };\n        cells.set(getTableCellKey(address), {\n          address,\n          content: workbookManager.getCellContent(address),\n        });\n      }\n    }\n    return Array.from(cells.values());\n  }\n\n  for (const [ref, content] of sheet.content.entries()) {\n    const { rowIndex, colIndex } = parseCellReference(ref);\n    if (rowIndex < table.start.rowIndex) {\n      continue;\n    }\n    if (colIndex < startColIndex || colIndex > endColIndex) {\n      continue;\n    }\n\n    const address = {\n      workbookName: table.workbookName,\n      sheetName: table.sheetName,\n      rowIndex,\n      colIndex,\n    };\n    cells.set(getTableCellKey(address), {\n      address,\n      content,\n    });\n  }\n\n  return Array.from(cells.values());\n}\n\nexport function buildTableTouchedCells(\n  workbookManager: WorkbookManager,\n  tables: Array<TableDefinition | undefined>\n): MutationInvalidation[\"touchedCells\"] {\n  const touchedCells = new Map<\n    string,\n    MutationInvalidation[\"touchedCells\"][number]\n  >();\n\n  for (const table of tables) {\n    if (!table) {\n      continue;\n    }\n    for (const cell of collectTableFootprintCells(workbookManager, table)) {\n      touchedCells.set(getTableCellKey(cell.address), {\n        address: cell.address,\n        beforeKind: getSerializedCellValueKind(cell.content),\n        afterKind: getSerializedCellValueKind(cell.content),\n      });\n    }\n  }\n\n  return Array.from(touchedCells.values());\n}\n\nexport function buildTableContextChangedCells(\n  workbookManager: WorkbookManager,\n  tables: Array<TableDefinition | undefined>\n): CellAddress[] {\n  const changedCells = new Map<string, CellAddress>();\n\n  for (const table of tables) {\n    if (!table) {\n      continue;\n    }\n    for (const cell of collectTableFootprintCells(workbookManager, table)) {\n      changedCells.set(getTableCellKey(cell.address), cell.address);\n    }\n  }\n\n  return Array.from(changedCells.values());\n}\n\nexport function mergeTouchedCells(\n  ...groups: MutationInvalidation[\"touchedCells\"][]\n): MutationInvalidation[\"touchedCells\"] {\n  const precedence = {\n    empty: 0,\n    scalar: 1,\n    formula: 2,\n  } as const;\n  const merged = new Map<\n    string,\n    MutationInvalidation[\"touchedCells\"][number]\n  >();\n\n  for (const group of groups) {\n    for (const touchedCell of group) {\n      const key = getTableCellKey(touchedCell.address);\n      const existing = merged.get(key);\n      if (!existing) {\n        merged.set(key, touchedCell);\n        continue;\n      }\n\n      merged.set(key, {\n        address: touchedCell.address,\n        beforeKind:\n          precedence[touchedCell.beforeKind] >= precedence[existing.beforeKind]\n            ? touchedCell.beforeKind\n            : existing.beforeKind,\n        afterKind:\n          precedence[touchedCell.afterKind] >= precedence[existing.afterKind]\n            ? touchedCell.afterKind\n            : existing.afterKind,\n      });\n    }\n  }\n\n  return Array.from(merged.values());\n}\n\nexport function getNamedExpressionScopeResourceKeys(\n  expressions: Iterable<string>,\n  opts: {\n    workbookName?: string;\n    sheetName?: string;\n  }\n): string[] {\n  return Array.from(\n    new Set(\n      Array.from(expressions, (expressionName) =>\n        getNamedExpressionResourceKey({\n          expressionName,\n          workbookName: opts.workbookName,\n          sheetName: opts.sheetName,\n        })\n      )\n    )\n  );\n}\n\nexport function getFiniteRangeAddresses(address: RangeAddress): CellAddress[] {\n  if (\n    address.range.end.col.type === \"infinity\" ||\n    address.range.end.row.type === \"infinity\"\n  ) {\n    return [];\n  }\n\n  const cells: CellAddress[] = [];\n  for (\n    let colIndex = address.range.start.col;\n    colIndex <= address.range.end.col.value;\n    colIndex++\n  ) {\n    for (\n      let rowIndex = address.range.start.row;\n      rowIndex <= address.range.end.row.value;\n      rowIndex++\n    ) {\n      cells.push({\n        workbookName: address.workbookName,\n        sheetName: address.sheetName,\n        colIndex,\n        rowIndex,\n      });\n    }\n  }\n  return cells;\n}\n"
  ],
  "mappings": "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",
  "debugId": "94265036334F30FD64756E2164756E21",
  "names": []
}