@pierre/diffs 1.3.5 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. package/dist/components/CodeView.d.ts +113 -68
  2. package/dist/components/CodeView.d.ts.map +1 -1
  3. package/dist/components/CodeView.js +153 -58
  4. package/dist/components/CodeView.js.map +1 -1
  5. package/dist/components/File.d.ts +75 -15
  6. package/dist/components/File.d.ts.map +1 -1
  7. package/dist/components/File.js +223 -62
  8. package/dist/components/File.js.map +1 -1
  9. package/dist/components/FileDiff.d.ts +97 -21
  10. package/dist/components/FileDiff.d.ts.map +1 -1
  11. package/dist/components/FileDiff.js +400 -100
  12. package/dist/components/FileDiff.js.map +1 -1
  13. package/dist/components/UnresolvedFile.d.ts +2 -2
  14. package/dist/components/UnresolvedFile.d.ts.map +1 -1
  15. package/dist/components/UnresolvedFile.js +2 -2
  16. package/dist/components/UnresolvedFile.js.map +1 -1
  17. package/dist/components/VirtualizedFile.d.ts +16 -7
  18. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  19. package/dist/components/VirtualizedFile.js +140 -51
  20. package/dist/components/VirtualizedFile.js.map +1 -1
  21. package/dist/components/VirtualizedFileDiff.d.ts +14 -8
  22. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  23. package/dist/components/VirtualizedFileDiff.js +183 -93
  24. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  25. package/dist/components/VirtulizerDevelopment.d.ts +1 -1
  26. package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
  27. package/dist/edit/index.d.ts +7 -4
  28. package/dist/edit/index.js +5 -1
  29. package/dist/editor/EditStateManager.d.ts +56 -0
  30. package/dist/editor/EditStateManager.d.ts.map +1 -0
  31. package/dist/editor/EditStateManager.js +135 -0
  32. package/dist/editor/EditStateManager.js.map +1 -0
  33. package/dist/editor/cloneRetainedDiffSessionSnapshot.d.ts +7 -0
  34. package/dist/editor/cloneRetainedDiffSessionSnapshot.d.ts.map +1 -0
  35. package/dist/editor/cloneRetainedDiffSessionSnapshot.js +16 -0
  36. package/dist/editor/cloneRetainedDiffSessionSnapshot.js.map +1 -0
  37. package/dist/editor/editPrediction.d.ts +76 -0
  38. package/dist/editor/editPrediction.d.ts.map +1 -0
  39. package/dist/editor/editPrediction.js +365 -0
  40. package/dist/editor/editPrediction.js.map +1 -0
  41. package/dist/editor/editStack.d.ts +19 -40
  42. package/dist/editor/editStack.d.ts.map +1 -1
  43. package/dist/editor/editStack.js +67 -4
  44. package/dist/editor/editStack.js.map +1 -1
  45. package/dist/editor/editor.d.ts +118 -29
  46. package/dist/editor/editor.d.ts.map +1 -1
  47. package/dist/editor/editor.js +1196 -403
  48. package/dist/editor/editor.js.map +1 -1
  49. package/dist/editor/editor2.js +1 -1
  50. package/dist/editor/languages.d.ts +3 -3
  51. package/dist/editor/languages.d.ts.map +1 -1
  52. package/dist/editor/languages.js.map +1 -1
  53. package/dist/editor/lineAnnotations.d.ts +3 -3
  54. package/dist/editor/lineAnnotations.d.ts.map +1 -1
  55. package/dist/editor/lineAnnotations.js +16 -7
  56. package/dist/editor/lineAnnotations.js.map +1 -1
  57. package/dist/editor/marker.d.ts +2 -2
  58. package/dist/editor/marker.d.ts.map +1 -1
  59. package/dist/editor/marker.js.map +1 -1
  60. package/dist/editor/matchBrackets.d.ts +2 -2
  61. package/dist/editor/matchBrackets.d.ts.map +1 -1
  62. package/dist/editor/matchBrackets.js.map +1 -1
  63. package/dist/editor/pieceTable.d.ts +1 -1
  64. package/dist/editor/pieceTable.js.map +1 -1
  65. package/dist/editor/searchPanel.d.ts +2 -2
  66. package/dist/editor/searchPanel.d.ts.map +1 -1
  67. package/dist/editor/searchPanel.js +3 -2
  68. package/dist/editor/searchPanel.js.map +1 -1
  69. package/dist/editor/selection.d.ts +33 -23
  70. package/dist/editor/selection.d.ts.map +1 -1
  71. package/dist/editor/selection.js +3 -3
  72. package/dist/editor/selection.js.map +1 -1
  73. package/dist/editor/selectionAction.d.ts +3 -3
  74. package/dist/editor/selectionAction.d.ts.map +1 -1
  75. package/dist/editor/selectionAction.js.map +1 -1
  76. package/dist/editor/textDocument.d.ts +11 -8
  77. package/dist/editor/textDocument.d.ts.map +1 -1
  78. package/dist/editor/textDocument.js +28 -5
  79. package/dist/editor/textDocument.js.map +1 -1
  80. package/dist/editor/textDocumentChangeTransaction.d.ts +15 -0
  81. package/dist/editor/textDocumentChangeTransaction.d.ts.map +1 -0
  82. package/dist/editor/textDocumentChangeTransaction.js +12 -0
  83. package/dist/editor/textDocumentChangeTransaction.js.map +1 -0
  84. package/dist/editor/textMeasure.d.ts +5 -0
  85. package/dist/editor/textMeasure.d.ts.map +1 -1
  86. package/dist/editor/textMeasure.js +10 -0
  87. package/dist/editor/textMeasure.js.map +1 -1
  88. package/dist/editor/tokenizer.d.ts +1 -1
  89. package/dist/editor/tokenizer.d.ts.map +1 -1
  90. package/dist/editor/tokenizer.js +6 -3
  91. package/dist/editor/tokenizer.js.map +1 -1
  92. package/dist/editor/types.d.ts +267 -0
  93. package/dist/editor/types.d.ts.map +1 -0
  94. package/dist/editor/types.js +0 -0
  95. package/dist/editor/utils.d.ts +2 -1
  96. package/dist/editor/utils.d.ts.map +1 -1
  97. package/dist/editor/utils.js +4 -1
  98. package/dist/editor/utils.js.map +1 -1
  99. package/dist/index.d.ts +8 -6
  100. package/dist/index.js +9 -8
  101. package/dist/managers/InteractionManager.d.ts.map +1 -1
  102. package/dist/managers/InteractionManager.js +7 -0
  103. package/dist/managers/InteractionManager.js.map +1 -1
  104. package/dist/react/CodeView.d.ts +36 -25
  105. package/dist/react/CodeView.d.ts.map +1 -1
  106. package/dist/react/CodeView.js +15 -14
  107. package/dist/react/CodeView.js.map +1 -1
  108. package/dist/react/EditContext.d.ts +8 -11
  109. package/dist/react/EditContext.d.ts.map +1 -1
  110. package/dist/react/EditContext.js +2 -9
  111. package/dist/react/EditContext.js.map +1 -1
  112. package/dist/react/File.d.ts +10 -6
  113. package/dist/react/File.d.ts.map +1 -1
  114. package/dist/react/File.js +8 -4
  115. package/dist/react/File.js.map +1 -1
  116. package/dist/react/FileDiff.d.ts +10 -5
  117. package/dist/react/FileDiff.d.ts.map +1 -1
  118. package/dist/react/FileDiff.js +8 -4
  119. package/dist/react/FileDiff.js.map +1 -1
  120. package/dist/react/MultiFileDiff.d.ts +8 -5
  121. package/dist/react/MultiFileDiff.d.ts.map +1 -1
  122. package/dist/react/MultiFileDiff.js +8 -12
  123. package/dist/react/MultiFileDiff.js.map +1 -1
  124. package/dist/react/PatchDiff.d.ts +7 -4
  125. package/dist/react/PatchDiff.d.ts.map +1 -1
  126. package/dist/react/PatchDiff.js +8 -4
  127. package/dist/react/PatchDiff.js.map +1 -1
  128. package/dist/react/UnresolvedFile.d.ts +3 -3
  129. package/dist/react/UnresolvedFile.d.ts.map +1 -1
  130. package/dist/react/UnresolvedFile.js.map +1 -1
  131. package/dist/react/index.d.ts +8 -5
  132. package/dist/react/types.d.ts +46 -9
  133. package/dist/react/types.d.ts.map +1 -1
  134. package/dist/react/utils/renderDiffChildren.d.ts +14 -12
  135. package/dist/react/utils/renderDiffChildren.d.ts.map +1 -1
  136. package/dist/react/utils/renderDiffChildren.js +2 -2
  137. package/dist/react/utils/renderDiffChildren.js.map +1 -1
  138. package/dist/react/utils/renderFileChildren.d.ts +14 -12
  139. package/dist/react/utils/renderFileChildren.d.ts.map +1 -1
  140. package/dist/react/utils/renderFileChildren.js +2 -2
  141. package/dist/react/utils/renderFileChildren.js.map +1 -1
  142. package/dist/react/utils/useFileDiffInstance.d.ts +22 -10
  143. package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
  144. package/dist/react/utils/useFileDiffInstance.js +112 -22
  145. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  146. package/dist/react/utils/useFileInstance.d.ts +15 -9
  147. package/dist/react/utils/useFileInstance.d.ts.map +1 -1
  148. package/dist/react/utils/useFileInstance.js +84 -25
  149. package/dist/react/utils/useFileInstance.js.map +1 -1
  150. package/dist/renderers/DiffHunksRenderer.d.ts +30 -15
  151. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  152. package/dist/renderers/DiffHunksRenderer.js +172 -108
  153. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  154. package/dist/renderers/FileRenderer.d.ts +27 -11
  155. package/dist/renderers/FileRenderer.d.ts.map +1 -1
  156. package/dist/renderers/FileRenderer.js +138 -64
  157. package/dist/renderers/FileRenderer.js.map +1 -1
  158. package/dist/renderers/UnresolvedFileHunksRenderer.d.ts +2 -2
  159. package/dist/renderers/UnresolvedFileHunksRenderer.d.ts.map +1 -1
  160. package/dist/renderers/UnresolvedFileHunksRenderer.js +2 -2
  161. package/dist/renderers/UnresolvedFileHunksRenderer.js.map +1 -1
  162. package/dist/shiki-stream/tokenizer.d.ts.map +1 -1
  163. package/dist/shiki-stream/tokenizer.js +2 -1
  164. package/dist/shiki-stream/tokenizer.js.map +1 -1
  165. package/dist/ssr/index.d.ts +2 -2
  166. package/dist/ssr/preloadDiffs.d.ts +21 -21
  167. package/dist/ssr/preloadDiffs.d.ts.map +1 -1
  168. package/dist/ssr/preloadDiffs.js +1 -1
  169. package/dist/ssr/preloadDiffs.js.map +1 -1
  170. package/dist/ssr/preloadFile.d.ts +6 -6
  171. package/dist/ssr/preloadFile.d.ts.map +1 -1
  172. package/dist/ssr/preloadFile.js.map +1 -1
  173. package/dist/ssr/preloadPatchFile.d.ts +4 -4
  174. package/dist/ssr/preloadPatchFile.d.ts.map +1 -1
  175. package/dist/ssr/preloadPatchFile.js.map +1 -1
  176. package/dist/style.js +1 -1
  177. package/dist/types.d.ts +13 -263
  178. package/dist/types.d.ts.map +1 -1
  179. package/dist/utils/appendItems.d.ts +5 -0
  180. package/dist/utils/appendItems.d.ts.map +1 -0
  181. package/dist/utils/appendItems.js +8 -0
  182. package/dist/utils/appendItems.js.map +1 -0
  183. package/dist/utils/areDiffTargetsEqual.js +1 -1
  184. package/dist/utils/areDiffTargetsEqual.js.map +1 -1
  185. package/dist/utils/areFileTargetsEqual.d.ts +7 -0
  186. package/dist/utils/areFileTargetsEqual.d.ts.map +1 -0
  187. package/dist/utils/areFileTargetsEqual.js +8 -0
  188. package/dist/utils/areFileTargetsEqual.js.map +1 -0
  189. package/dist/utils/areManagedSnapshotsEqual.d.ts +1 -1
  190. package/dist/utils/areManagedSnapshotsEqual.d.ts.map +1 -1
  191. package/dist/utils/areManagedSnapshotsEqual.js.map +1 -1
  192. package/dist/utils/areOptionsEqual.d.ts +3 -3
  193. package/dist/utils/areOptionsEqual.d.ts.map +1 -1
  194. package/dist/utils/areOptionsEqual.js.map +1 -1
  195. package/dist/utils/cloneFileDiffMetadata.d.ts +3 -2
  196. package/dist/utils/cloneFileDiffMetadata.d.ts.map +1 -1
  197. package/dist/utils/cloneFileDiffMetadata.js +8 -5
  198. package/dist/utils/cloneFileDiffMetadata.js.map +1 -1
  199. package/dist/utils/composeCacheKey.d.ts +6 -0
  200. package/dist/utils/composeCacheKey.d.ts.map +1 -0
  201. package/dist/utils/composeCacheKey.js +10 -0
  202. package/dist/utils/composeCacheKey.js.map +1 -0
  203. package/dist/utils/editSessionAnnotations.d.ts +69 -0
  204. package/dist/utils/editSessionAnnotations.d.ts.map +1 -0
  205. package/dist/utils/editSessionAnnotations.js +64 -0
  206. package/dist/utils/editSessionAnnotations.js.map +1 -0
  207. package/dist/utils/editSessionHunks.d.ts +5 -3
  208. package/dist/utils/editSessionHunks.d.ts.map +1 -1
  209. package/dist/utils/editSessionHunks.js +7 -5
  210. package/dist/utils/editSessionHunks.js.map +1 -1
  211. package/dist/utils/getDiffHunksRendererOptions.d.ts +1 -1
  212. package/dist/utils/getDiffHunksRendererOptions.d.ts.map +1 -1
  213. package/dist/utils/getDiffHunksRendererOptions.js.map +1 -1
  214. package/dist/utils/getFileRendererOptions.d.ts +1 -1
  215. package/dist/utils/getFileRendererOptions.d.ts.map +1 -1
  216. package/dist/utils/getFileRendererOptions.js.map +1 -1
  217. package/dist/utils/hydratePartialDiff.d.ts.map +1 -1
  218. package/dist/utils/hydratePartialDiff.js +2 -1
  219. package/dist/utils/hydratePartialDiff.js.map +1 -1
  220. package/dist/utils/lineAnnotationIdentity.d.ts +16 -0
  221. package/dist/utils/lineAnnotationIdentity.d.ts.map +1 -0
  222. package/dist/utils/lineAnnotationIdentity.js +17 -0
  223. package/dist/utils/lineAnnotationIdentity.js.map +1 -0
  224. package/dist/utils/parseDiffFromFile.d.ts +2 -2
  225. package/dist/utils/parseDiffFromFile.d.ts.map +1 -1
  226. package/dist/utils/parseDiffFromFile.js +6 -6
  227. package/dist/utils/parseDiffFromFile.js.map +1 -1
  228. package/dist/utils/parsePatchFiles.d.ts +6 -3
  229. package/dist/utils/parsePatchFiles.d.ts.map +1 -1
  230. package/dist/utils/parsePatchFiles.js +34 -9
  231. package/dist/utils/parsePatchFiles.js.map +1 -1
  232. package/dist/utils/renderDiffWithHighlighter.d.ts.map +1 -1
  233. package/dist/utils/renderDiffWithHighlighter.js +6 -5
  234. package/dist/utils/renderDiffWithHighlighter.js.map +1 -1
  235. package/dist/utils/renderFileWithHighlighter.d.ts.map +1 -1
  236. package/dist/utils/renderFileWithHighlighter.js +7 -4
  237. package/dist/utils/renderFileWithHighlighter.js.map +1 -1
  238. package/dist/utils/trimPatchContext.d.ts.map +1 -1
  239. package/dist/utils/trimPatchContext.js +3 -2
  240. package/dist/utils/trimPatchContext.js.map +1 -1
  241. package/dist/utils/updateDiffHunks.js +1 -1
  242. package/dist/utils/virtualDiffLayout.js +1 -1
  243. package/dist/worker/WorkerPoolManager.d.ts +4 -3
  244. package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
  245. package/dist/worker/WorkerPoolManager.js +33 -4
  246. package/dist/worker/WorkerPoolManager.js.map +1 -1
  247. package/dist/worker/types.d.ts +5 -0
  248. package/dist/worker/types.d.ts.map +1 -1
  249. package/dist/worker/worker-portable.js +14 -6
  250. package/dist/worker/worker-portable.js.map +1 -1
  251. package/dist/worker/worker.js +14 -6
  252. package/dist/worker/worker.js.map +1 -1
  253. package/package.json +9 -1
  254. package/dist/editor/stateStorage.d.ts +0 -15
  255. package/dist/editor/stateStorage.d.ts.map +0 -1
  256. package/dist/editor/stateStorage.js +0 -65
  257. package/dist/editor/stateStorage.js.map +0 -1
@@ -1,23 +1,25 @@
1
1
  import "../constants.js";
2
2
  import { areObjectsEqual } from "../utils/areObjectsEqual.js";
3
3
  import { areOptionsEqual } from "../utils/areOptionsEqual.js";
4
- import { parseDiffFromFile } from "../utils/parseDiffFromFile.js";
5
4
  import { computeVirtualFileMetrics, getVirtualFileHeaderRegion, getVirtualFilePaddingBottom } from "../utils/computeVirtualFileMetrics.js";
6
- import { getExpandedRegion, getLeadingHunkSeparatorLayout, getTrailingExpandedRegion, getTrailingHunkSeparatorLayout, isAdditionLineRenderable } from "../utils/virtualDiffLayout.js";
7
- import { areFilesEqual } from "../utils/areFilesEqual.js";
8
5
  import { FILE_ANNOTATION_DOM_KEY, includesFileAnnotations, shouldRenderFileAnnotations } from "../utils/includesFileAnnotations.js";
9
6
  import { areDiffTargetsEqual } from "../utils/areDiffTargetsEqual.js";
7
+ import { areFilesEqual } from "../utils/areFilesEqual.js";
10
8
  import { awaitWithTimeout } from "../utils/awaitWithTimeout.js";
9
+ import { getExpandedRegion, getLeadingHunkSeparatorLayout, getTrailingExpandedRegion, getTrailingHunkSeparatorLayout, isAdditionLineRenderable } from "../utils/virtualDiffLayout.js";
11
10
  import { computeEstimatedDiffHeights } from "../utils/computeEstimatedDiffHeights.js";
12
11
  import { getDiffFileInput } from "../utils/getDiffFileInput.js";
13
12
  import { hydratePartialDiff } from "../utils/hydratePartialDiff.js";
14
13
  import { iterateOverDiff } from "../utils/iterateOverDiff.js";
14
+ import { parseDiffFromFile } from "../utils/parseDiffFromFile.js";
15
15
  import { FileDiff } from "./FileDiff.js";
16
16
  //#region src/components/VirtualizedFileDiff.ts
17
17
  const VIRTUALIZED_FILE_DIFF_LAYOUT_CHECKPOINT_INTERVAL = 3e3;
18
+ const NO_GHOST_TEXT_ROWS = /* @__PURE__ */ new Map();
18
19
  let instanceId = -1;
19
20
  var VirtualizedFileDiff = class extends FileDiff {
20
21
  __id = `little-virtualized-file-diff:${++instanceId}`;
22
+ renderType = "virtualized";
21
23
  top;
22
24
  height = 0;
23
25
  metrics;
@@ -28,7 +30,9 @@ var VirtualizedFileDiff = class extends FileDiff {
28
30
  estimatedUnifiedHeight: void 0,
29
31
  checkpoints: [],
30
32
  totalLines: 0,
31
- fileAnnotationHeight: 0
33
+ fileAnnotationHeight: 0,
34
+ ghostTextRows: NO_GHOST_TEXT_ROWS,
35
+ ghostTextRowsByIndex: /* @__PURE__ */ new Map()
32
36
  };
33
37
  isVisible = false;
34
38
  isSetup = false;
@@ -36,9 +40,9 @@ var VirtualizedFileDiff = class extends FileDiff {
36
40
  layoutDirty = true;
37
41
  forceRenderOverride;
38
42
  currentCollapsed;
39
- currentExpandUnchanged;
40
43
  pendingHydratedDiff;
41
44
  pendingExpansions;
45
+ pendingRender;
42
46
  constructor(options, virtualizer, metrics, workerManager, isContainerManaged = false) {
43
47
  super(options, workerManager, isContainerManaged);
44
48
  this.virtualizer = virtualizer;
@@ -54,10 +58,17 @@ var VirtualizedFileDiff = class extends FileDiff {
54
58
  if (this.syncLineAnnotations(lineAnnotations)) this.resetLayoutCache({ includeEstimatedHeights: false });
55
59
  }
56
60
  syncLineAnnotations(lineAnnotations) {
57
- if (lineAnnotations == null || lineAnnotations === this.lineAnnotations || lineAnnotations.length === 0 && this.lineAnnotations.length === 0) return false;
61
+ if (lineAnnotations == null || !this.isNewAnnotations(lineAnnotations) || lineAnnotations.length === 0 && this.getLatestAnnotations().length === 0) return false;
58
62
  super.setLineAnnotations(lineAnnotations);
59
63
  return true;
60
64
  }
65
+ syncEditSessionAnnotationsFromEditor(lineAnnotations) {
66
+ if (super.syncEditSessionAnnotationsFromEditor(lineAnnotations)) {
67
+ this.resetLayoutCache({ includeEstimatedHeights: false });
68
+ return true;
69
+ }
70
+ return false;
71
+ }
61
72
  setFileAnnotationHeight(nextHeight) {
62
73
  const previousHeight = this.cache.fileAnnotationHeight;
63
74
  if (nextHeight === previousHeight) return false;
@@ -65,9 +76,10 @@ var VirtualizedFileDiff = class extends FileDiff {
65
76
  this.cache.measuredHeightDeltaTotal += nextHeight - previousHeight;
66
77
  return true;
67
78
  }
68
- hasFileAnnotations(fileDiff = this.fileDiff) {
69
- if (fileDiff == null || !includesFileAnnotations(this.lineAnnotations)) return false;
70
- return this.lineAnnotations.some((annotation) => {
79
+ hasFileAnnotations(fileDiff) {
80
+ const lineAnnotations = this.getLatestAnnotations();
81
+ if (!includesFileAnnotations(lineAnnotations)) return false;
82
+ return lineAnnotations.some((annotation) => {
71
83
  if (annotation.lineNumber !== 0) return false;
72
84
  if (fileDiff.type === "new") return annotation.side === "additions";
73
85
  if (fileDiff.type === "deleted") return annotation.side === "deletions";
@@ -102,8 +114,10 @@ var VirtualizedFileDiff = class extends FileDiff {
102
114
  resetLayoutCache({ forceSimpleRecompute = false, includeEstimatedHeights = false, resetRenderRange = true } = {}) {
103
115
  this.layoutDirty = true;
104
116
  this.cache.fileAnnotationHeight = 0;
105
- if (this.cache.heightDeltas.size > 0) this.cache.heightDeltas.clear();
106
- if (this.cache.measuredHeightDeltaTotal !== 0) this.cache.measuredHeightDeltaTotal = 0;
117
+ this.cache.heightDeltas.clear();
118
+ this.cache.measuredHeightDeltaTotal = 0;
119
+ this.cache.ghostTextRows = NO_GHOST_TEXT_ROWS;
120
+ if (this.cache.ghostTextRowsByIndex.size > 0) this.cache.ghostTextRowsByIndex.clear();
107
121
  this.invalidateDerivedLayoutCache(includeEstimatedHeights, resetRenderRange);
108
122
  if (forceSimpleRecompute && this.isSimpleMode()) this.computeApproximateSize();
109
123
  }
@@ -117,19 +131,49 @@ var VirtualizedFileDiff = class extends FileDiff {
117
131
  }
118
132
  if (this.renderRange != null && resetRenderRange) this.renderRange = void 0;
119
133
  }
134
+ applyGhostTextRows(fileDiff, ghostTextRows) {
135
+ const { cache: { heightDeltas, ghostTextRows: folded, ghostTextRowsByIndex: previous }, metrics: { lineHeight } } = this;
136
+ if (folded === ghostTextRows) return false;
137
+ const diffStyle = this.getDiffStyle();
138
+ const next = /* @__PURE__ */ new Map();
139
+ for (const [line, rows] of ghostTextRows) {
140
+ const indexes = this.getLineIndexForDiff(fileDiff, line + 1, "additions");
141
+ if (indexes == null) continue;
142
+ next.set(diffStyle === "split" ? indexes[1] : indexes[0], rows);
143
+ }
144
+ let changed = false;
145
+ for (const rowIndex of /* @__PURE__ */ new Set([...previous.keys(), ...next.keys()])) {
146
+ const delta = ((next.get(rowIndex) ?? 0) - (previous.get(rowIndex) ?? 0)) * lineHeight;
147
+ if (delta === 0) continue;
148
+ const nextDelta = (heightDeltas.get(rowIndex) ?? 0) + delta;
149
+ if (nextDelta === 0) heightDeltas.delete(rowIndex);
150
+ else heightDeltas.set(rowIndex, nextDelta);
151
+ this.cache.measuredHeightDeltaTotal += delta;
152
+ changed = true;
153
+ }
154
+ this.cache.ghostTextRows = ghostTextRows;
155
+ this.cache.ghostTextRowsByIndex = next;
156
+ return changed;
157
+ }
120
158
  reconcileHeights() {
121
159
  let hasHeightChange = false;
122
- const { overflow = "scroll" } = this.options;
123
- if (this.fileContainer == null || this.fileDiff == null) {
160
+ const { options: { overflow = "scroll" }, cache: { ghostTextRowsByIndex }, metrics: { lineHeight } } = this;
161
+ const fileDiff = this.getRenderedDiff();
162
+ if (this.fileContainer == null || fileDiff == null) {
124
163
  if (this.height !== 0) hasHeightChange = true;
125
164
  this.height = 0;
126
165
  return hasHeightChange;
127
166
  }
128
167
  this.top = this.getVirtualizedTop();
129
- if (overflow === "scroll" && this.lineAnnotations.length === 0 && !this.isResizeDebuggingEnabled()) return hasHeightChange;
168
+ hasHeightChange = this.applyGhostTextRows(fileDiff, this.editor?.__getGhostTextRows() ?? NO_GHOST_TEXT_ROWS);
169
+ const lineAnnotations = this.getLatestAnnotations();
170
+ if (overflow === "scroll" && lineAnnotations.length === 0 && !this.isResizeDebuggingEnabled()) {
171
+ if (hasHeightChange) this.computeApproximateSize(true);
172
+ return hasHeightChange;
173
+ }
130
174
  const diffStyle = this.getDiffStyle();
131
175
  const codeGroups = diffStyle === "split" ? [this.codeDeletions, this.codeAdditions] : [this.codeUnified];
132
- const hasFileAnnotations = this.hasFileAnnotations(this.fileDiff);
176
+ const hasFileAnnotations = this.hasFileAnnotations(fileDiff);
133
177
  if (this.renderRange != null && hasFileAnnotations && shouldRenderFileAnnotations(this.renderRange)) {
134
178
  const nextFileAnnotationHeight = measureFileAnnotationHeight(codeGroups) ?? 0;
135
179
  if (this.setFileAnnotationHeight(nextFileAnnotationHeight)) hasHeightChange = true;
@@ -138,12 +182,15 @@ var VirtualizedFileDiff = class extends FileDiff {
138
182
  if (codeGroup == null) continue;
139
183
  const content = codeGroup.children[1];
140
184
  if (!(content instanceof HTMLElement)) continue;
185
+ const skipsGhostRows = diffStyle === "split" && codeGroup === this.codeDeletions;
141
186
  for (const line of content.children) {
142
187
  if (!(line instanceof HTMLElement)) continue;
143
188
  const lineIndexAttr = line.dataset.lineIndex;
144
189
  if (lineIndexAttr == null) continue;
145
190
  const lineIndex = parseLineIndex(lineIndexAttr, diffStyle);
146
- let measuredHeight = line.getBoundingClientRect().height;
191
+ const ghostRows = ghostTextRowsByIndex.get(lineIndex) ?? 0;
192
+ if (skipsGhostRows && ghostRows > 0) continue;
193
+ let measuredHeight = line.getBoundingClientRect().height + ghostRows * lineHeight;
147
194
  let hasMetadata = false;
148
195
  if (line.nextElementSibling instanceof HTMLElement && ("lineAnnotation" in line.nextElementSibling.dataset || "noNewline" in line.nextElementSibling.dataset)) {
149
196
  if ("noNewline" in line.nextElementSibling.dataset) hasMetadata = true;
@@ -171,41 +218,59 @@ var VirtualizedFileDiff = class extends FileDiff {
171
218
  super.flushManagers();
172
219
  if (this.lineStateRefreshPending) this.flushDeferredLineState();
173
220
  }
174
- prepareCodeViewItem(fileDiff, top, reset, lineAnnotations) {
175
- const targetChanged = !areDiffTargetsEqual(this.fileDiff, fileDiff);
176
- const annotationsChanged = this.syncLineAnnotations(lineAnnotations);
177
- let shouldResetLayoutCache = reset?.resetDiffLayoutCache === true || targetChanged || annotationsChanged;
178
- let includeEstimatedHeights = targetChanged || reset?.resetDiffLayoutCache === true && reset.includeEstimatedDiffHeights;
221
+ updateCodeViewLayout(fileDiff, top, reset, lineAnnotations) {
222
+ let resetLayoutCache = false;
223
+ let resetEstimatedHeights = false;
224
+ const { pendingExpansions, pendingHydratedDiff, options: { collapsed = false } } = this;
225
+ if (pendingHydratedDiff != null) {
226
+ this.pendingHydratedDiff = void 0;
227
+ if (pendingHydratedDiff.expectedDiff === fileDiff) {
228
+ Object.assign(fileDiff, pendingHydratedDiff.nextDiff);
229
+ this.setHydratedState(pendingHydratedDiff.files);
230
+ this.startHydratedEditSession(fileDiff);
231
+ this.forceRenderOverride = true;
232
+ resetLayoutCache = true;
233
+ resetEstimatedHeights = true;
234
+ }
235
+ }
236
+ if (pendingExpansions != null) {
237
+ this.pendingExpansions = void 0;
238
+ for (const { hunkIndex, direction, expansionLineCountOverride } of pendingExpansions) {
239
+ this.hunksRenderer.expandHunk(hunkIndex, direction, expansionLineCountOverride);
240
+ this.forceRenderOverride = true;
241
+ resetEstimatedHeights = true;
242
+ }
243
+ }
244
+ const diffChanged = this.updateExternalDiff(fileDiff, lineAnnotations);
245
+ const { pendingRenderDiff, layoutDiffChanged, renderedDiffChanged, annotationsChanged } = this.updatePendingRender(fileDiff, lineAnnotations);
246
+ if (!this.forceRenderOverride && (diffChanged || renderedDiffChanged || annotationsChanged)) this.forceRenderOverride = true;
247
+ if (reset?.resetDiffLayoutCache === true || layoutDiffChanged || annotationsChanged) resetLayoutCache = true;
248
+ if (layoutDiffChanged || reset?.resetDiffLayoutCache === true && reset.includeEstimatedDiffHeights) resetEstimatedHeights = true;
179
249
  if (reset?.metrics != null) {
180
250
  this.metrics = computeVirtualFileMetrics(reset.metrics);
181
- shouldResetLayoutCache = true;
182
- includeEstimatedHeights = true;
251
+ resetLayoutCache = true;
252
+ resetEstimatedHeights = true;
183
253
  }
184
- const { collapsed = false, expandUnchanged = false } = this.options;
185
254
  if (this.currentCollapsed !== collapsed) {
186
255
  this.currentCollapsed = collapsed;
187
- shouldResetLayoutCache = true;
188
- }
189
- if (this.currentExpandUnchanged !== expandUnchanged) {
190
- this.currentExpandUnchanged = expandUnchanged;
191
- shouldResetLayoutCache = true;
192
- includeEstimatedHeights = true;
256
+ resetLayoutCache = true;
193
257
  }
194
- if (shouldResetLayoutCache) this.resetLayoutCache({ includeEstimatedHeights });
195
- this.fileDiff = fileDiff;
258
+ if (resetLayoutCache) this.resetLayoutCache({ includeEstimatedHeights: resetEstimatedHeights });
259
+ else if (resetEstimatedHeights) this.invalidateDerivedLayoutCache(true);
196
260
  this.top = top;
197
- this.computeApproximateSize();
261
+ this.computeApproximateSize(false, pendingRenderDiff);
198
262
  return this.height;
199
263
  }
200
264
  getLinePosition(lineNumber, side = "additions") {
201
- if (this.fileDiff == null || lineNumber < 1) return;
202
- const targetLineIndexes = this.getLineIndex(lineNumber, side);
265
+ const fileDiff = this.getLayoutDiff();
266
+ if (fileDiff == null || lineNumber < 1) return;
267
+ const targetLineIndexes = this.getLineIndexForDiff(fileDiff, lineNumber, side);
203
268
  if (targetLineIndexes == null) return;
204
269
  const { disableFileHeader = false, expandUnchanged = false, collapsed = false, collapsedContextThreshold = 1 } = this.options;
205
270
  const diffStyle = this.getDiffStyle();
206
271
  const hunkSeparators = this.getHunkSeparatorType();
207
272
  const targetLineIndex = diffStyle === "split" ? targetLineIndexes[1] : targetLineIndexes[0];
208
- this.approximateLayoutCheckpoints();
273
+ this.approximateLayoutCheckpoints(fileDiff);
209
274
  const headerRegion = getVirtualFileHeaderRegion(this.metrics, disableFileHeader);
210
275
  const checkpoint = this.getLayoutCheckpointBeforeLineIndex(targetLineIndex);
211
276
  let top = checkpoint?.top ?? headerRegion + this.cache.fileAnnotationHeight;
@@ -215,7 +280,7 @@ var VirtualizedFileDiff = class extends FileDiff {
215
280
  };
216
281
  let position;
217
282
  iterateOverDiff({
218
- diff: this.fileDiff,
283
+ diff: fileDiff,
219
284
  diffStyle,
220
285
  startingLine: checkpoint?.renderedLineIndex ?? 0,
221
286
  expandedHunks: expandUnchanged ? true : this.hunksRenderer.getExpandedHunksMap(),
@@ -276,17 +341,18 @@ var VirtualizedFileDiff = class extends FileDiff {
276
341
  return this.virtualizer.type === "simple" ? this.virtualizer.getRoot() : this.virtualizer.getContainerElement();
277
342
  }
278
343
  getNumericScrollAnchor(localViewportTop) {
279
- if (this.fileDiff == null) return;
344
+ const fileDiff = this.getLayoutDiff();
345
+ if (fileDiff == null) return;
280
346
  const { disableFileHeader = false, expandUnchanged = false, collapsed = false, collapsedContextThreshold = 1 } = this.options;
281
347
  if (collapsed) return;
282
348
  const diffStyle = this.getDiffStyle();
283
349
  const hunkSeparators = this.getHunkSeparatorType();
284
- this.approximateLayoutCheckpoints();
350
+ this.approximateLayoutCheckpoints(fileDiff);
285
351
  const checkpoint = this.getLayoutCheckpointBeforeTop(localViewportTop);
286
352
  let top = checkpoint?.top ?? getVirtualFileHeaderRegion(this.metrics, disableFileHeader) + this.cache.fileAnnotationHeight;
287
353
  let anchor;
288
354
  iterateOverDiff({
289
- diff: this.fileDiff,
355
+ diff: fileDiff,
290
356
  diffStyle,
291
357
  startingLine: checkpoint?.renderedLineIndex ?? 0,
292
358
  expandedHunks: expandUnchanged ? true : this.hunksRenderer.getExpandedHunksMap(),
@@ -334,12 +400,13 @@ var VirtualizedFileDiff = class extends FileDiff {
334
400
  return this.height;
335
401
  }
336
402
  getAdvancedStickySpecs(windowSpecs) {
337
- if (this.top == null || this.fileDiff == null) return;
403
+ const fileDiff = this.getLayoutDiff();
404
+ if (this.top == null || fileDiff == null) return;
338
405
  if (this.options.collapsed === true) return {
339
406
  topOffset: this.top,
340
407
  height: this.height
341
408
  };
342
- const renderRange = windowSpecs != null ? this.computeRenderRangeFromWindow(this.fileDiff, this.top, windowSpecs) : this.renderRange;
409
+ const renderRange = windowSpecs != null ? this.computeRenderRangeFromWindow(fileDiff, this.top, windowSpecs) : this.renderRange;
343
410
  if (renderRange == null) return;
344
411
  const { bufferBefore, bufferAfter, totalLines } = renderRange;
345
412
  let headerOnlyOffset = 0;
@@ -353,14 +420,19 @@ var VirtualizedFileDiff = class extends FileDiff {
353
420
  };
354
421
  }
355
422
  cleanUp(recycle = false) {
423
+ const hadGhostTextRows = this.cache.ghostTextRows.size > 0;
424
+ if (hadGhostTextRows) this.layoutDirty = true;
425
+ const shouldRecomputeLayout = recycle && this.isAdvancedMode() && this.fileContainer != null && (hadGhostTextRows || !areDiffTargetsEqual(this.getRenderedDiff(), this.getLatestDiff()));
356
426
  if (this.fileContainer != null && this.isSimpleMode()) this.getSimpleVirtualizer()?.disconnect(this.fileContainer);
357
427
  if (!recycle) {
358
428
  this.resetLayoutCache({ includeEstimatedHeights: true });
359
429
  this.pendingExpansions = void 0;
360
430
  this.pendingHydratedDiff = void 0;
361
431
  }
432
+ this.pendingRender = void 0;
362
433
  this.isSetup = false;
363
434
  super.cleanUp(recycle);
435
+ if (shouldRecomputeLayout) this.virtualizer.instanceChanged(this, true);
364
436
  }
365
437
  expandHunk = (hunkIndex, direction, expansionLineCountOverride) => {
366
438
  if (this.fileDiff == null) return;
@@ -394,41 +466,16 @@ var VirtualizedFileDiff = class extends FileDiff {
394
466
  } else {
395
467
  hydratePartialDiff("merge", expectedDiff, files);
396
468
  this.setHydratedState(files);
397
- await awaitWithTimeout(() => this.primeHighlightCache(expectedDiff));
398
- if (!this.enabled || this.fileDiff !== expectedDiff) return;
469
+ if (!this.startHydratedEditSession(expectedDiff)) {
470
+ await awaitWithTimeout(() => this.primeHighlightCache(expectedDiff));
471
+ if (!this.enabled || this.fileDiff !== expectedDiff) return;
472
+ }
399
473
  this.resetLayoutCache({ includeEstimatedHeights: true });
400
474
  this.computeApproximateSize();
401
475
  }
402
476
  this.forceRenderOverride = true;
403
477
  this.virtualizer.instanceChanged(this, true);
404
478
  }
405
- consumeCodeViewLayoutChanges(expectedFileDiff) {
406
- let hasLayoutChange = false;
407
- let nextDiff;
408
- const { pendingExpansions, pendingHydratedDiff } = this;
409
- if (pendingExpansions != null) {
410
- this.pendingExpansions = void 0;
411
- for (const pendingExpansion of pendingExpansions) {
412
- this.hunksRenderer.expandHunk(pendingExpansion.hunkIndex, pendingExpansion.direction, pendingExpansion.expansionLineCountOverride);
413
- hasLayoutChange = true;
414
- }
415
- }
416
- if (pendingHydratedDiff != null) {
417
- this.pendingHydratedDiff = void 0;
418
- if (pendingHydratedDiff.expectedDiff === expectedFileDiff) {
419
- this.setHydratedState(pendingHydratedDiff.files);
420
- nextDiff = pendingHydratedDiff.nextDiff;
421
- }
422
- }
423
- if (nextDiff != null) {
424
- this.forceRenderOverride = true;
425
- this.resetLayoutCache({ includeEstimatedHeights: true });
426
- } else if (hasLayoutChange) {
427
- this.forceRenderOverride = true;
428
- this.invalidateDerivedLayoutCache(true);
429
- }
430
- return nextDiff;
431
- }
432
479
  loadFilesIfNecessary() {
433
480
  if (this.pendingHydratedDiff != null) {
434
481
  if (this.pendingHydratedDiff.expectedDiff === this.fileDiff) return;
@@ -439,7 +486,7 @@ var VirtualizedFileDiff = class extends FileDiff {
439
486
  isLineRenderable(lineNumber) {
440
487
  if (super.isLineRenderable(lineNumber)) return true;
441
488
  const { pendingExpansions } = this;
442
- const fileDiff = this.fileDiffCache;
489
+ const fileDiff = this.getRenderedDiff();
443
490
  if (pendingExpansions == null || pendingExpansions.length === 0 || fileDiff == null) return false;
444
491
  const { expansionLineCount = 100, collapsedContextThreshold = 1 } = this.options;
445
492
  const staged = new Map(this.hunksRenderer.getExpandedHunksMap());
@@ -500,8 +547,18 @@ var VirtualizedFileDiff = class extends FileDiff {
500
547
  }
501
548
  rerender() {
502
549
  if (!this.enabled || this.fileDiff == null && this.additionFile == null && this.deletionFile == null) return;
550
+ const latestDiff = this.getLatestDiff();
551
+ const nextRenderDiff = latestDiff == null ? void 0 : this.hunksRenderer.getDiffForNextRender(latestDiff);
503
552
  this.forceRenderOverride = true;
504
- this.virtualizer.instanceChanged(this, false);
553
+ this.virtualizer.instanceChanged(this, !areDiffTargetsEqual(this.getRenderedDiff(), nextRenderDiff));
554
+ }
555
+ syncGhostTextRows() {
556
+ const codeView = this.getAdvancedVirtualizer();
557
+ if (codeView != null) {
558
+ codeView.capturePendingLayoutAnchor();
559
+ this.layoutDirty = true;
560
+ codeView.instanceChanged(this, true);
561
+ } else this.getSimpleVirtualizer()?.requestHeightReconcile(this);
505
562
  }
506
563
  applyDocumentChange(textDocument, newLineAnnotations, shouldUpdateBuffer = false) {
507
564
  const { renderRange: previousRenderRange } = this;
@@ -513,16 +570,17 @@ var VirtualizedFileDiff = class extends FileDiff {
513
570
  includeEstimatedHeights: true,
514
571
  resetRenderRange: false
515
572
  });
573
+ const fileDiff = this.getRenderedDiff();
516
574
  if (!this.isSimpleMode()) this.computeApproximateSize(true);
517
- else if (shouldUpdateBuffer && previousRenderRange !== void 0 && this.fileDiff !== void 0) {
575
+ else if (shouldUpdateBuffer && previousRenderRange != null && fileDiff != null) {
518
576
  const windowSpecs = this.virtualizer.getWindowSpecs();
519
- const renderRange = this.computeRenderRangeFromWindow(this.fileDiff, this.top ?? 0, windowSpecs);
577
+ const renderRange = this.computeRenderRangeFromWindow(fileDiff, this.top ?? 0, windowSpecs);
520
578
  if (renderRange.bufferAfter !== previousRenderRange.bufferAfter) this.updateBuffers(renderRange);
521
579
  }
522
580
  this.forceRenderOverride = true;
523
581
  this.virtualizer.instanceChanged(this, true);
524
582
  }
525
- computeApproximateSize(force = false, fileDiff = this.fileDiff) {
583
+ computeApproximateSize(force = false, fileDiff = this.getLayoutDiff()) {
526
584
  const shouldValidateSize = this.isResizeDebuggingEnabled();
527
585
  if (!force && !this.layoutDirty && !shouldValidateSize) return;
528
586
  const isFirstCompute = this.height === 0;
@@ -533,6 +591,7 @@ var VirtualizedFileDiff = class extends FileDiff {
533
591
  this.layoutDirty = false;
534
592
  return;
535
593
  }
594
+ this.applyGhostTextRows(fileDiff, this.editor?.__getGhostTextRows() ?? NO_GHOST_TEXT_ROWS);
536
595
  const { disableFileHeader = false, collapsed = false } = this.options;
537
596
  const headerRegion = getVirtualFileHeaderRegion(this.metrics, disableFileHeader);
538
597
  this.height += headerRegion;
@@ -544,13 +603,16 @@ var VirtualizedFileDiff = class extends FileDiff {
544
603
  if (shouldValidateSize && !isFirstCompute) this.validateComputedHeight(fileDiff);
545
604
  this.layoutDirty = false;
546
605
  }
547
- getActiveEstimatedHeight(fileDiff = this.fileDiff) {
606
+ getLayoutDiff() {
607
+ return this.pendingRender?.diff ?? this.getRenderedDiff();
608
+ }
609
+ getActiveEstimatedHeight(fileDiff = this.getLayoutDiff()) {
548
610
  this.ensureEstimatedDiffHeights(fileDiff);
549
611
  const estimatedHeight = this.getDiffStyle() === "split" ? this.cache.estimatedSplitHeight : this.cache.estimatedUnifiedHeight;
550
612
  if (estimatedHeight == null) throw new Error("VirtualizedFileDiff.getActiveEstimatedHeight: missing estimated height");
551
613
  return estimatedHeight;
552
614
  }
553
- ensureEstimatedDiffHeights(fileDiff = this.fileDiff) {
615
+ ensureEstimatedDiffHeights(fileDiff = this.getLayoutDiff()) {
554
616
  if (fileDiff == null) {
555
617
  this.cache.estimatedSplitHeight = void 0;
556
618
  this.cache.estimatedUnifiedHeight = void 0;
@@ -571,7 +633,7 @@ var VirtualizedFileDiff = class extends FileDiff {
571
633
  this.cache.estimatedSplitHeight = splitHeight;
572
634
  this.cache.estimatedUnifiedHeight = unifiedHeight;
573
635
  }
574
- validateComputedHeight(fileDiff = this.fileDiff) {
636
+ validateComputedHeight(fileDiff = this.getLayoutDiff()) {
575
637
  if (this.fileContainer == null || fileDiff == null) return;
576
638
  const rect = this.fileContainer.getBoundingClientRect();
577
639
  if (rect.height !== this.height) console.log("VirtualizedFileDiff.computeApproximateSize: computed height doesnt match", {
@@ -591,19 +653,26 @@ var VirtualizedFileDiff = class extends FileDiff {
591
653
  if (fileDiff == null && hasFileInput && (filesDidChange || this.fileDiff == null)) nextFileDiff = parseDiffFromFile(fileInput.oldFile, fileInput.newFile, this.options.parseDiffOptions);
592
654
  const { forceRenderOverride, isSetup } = this;
593
655
  this.forceRenderOverride = void 0;
594
- const annotationsChanged = this.syncLineAnnotations(lineAnnotations);
595
- if (annotationsChanged) this.resetLayoutCache({ includeEstimatedHeights: false });
596
- const diffInputChanged = fileDiff != null && fileDiff !== this.fileDiff;
597
656
  const targetChanged = nextFileDiff != null && !areDiffTargetsEqual(this.fileDiff, nextFileDiff);
598
- const dataChanged = diffInputChanged || filesDidChange;
599
- if (targetChanged) this.resetLayoutCache({ includeEstimatedHeights: true });
657
+ const dataChanged = targetChanged || filesDidChange;
600
658
  fileContainer = this.getOrCreateFileContainer(fileContainer);
601
659
  if (nextFileDiff == null) {
602
660
  console.error("VirtualizedFileDiff.render: attempting to virtually render when we dont have the correct data");
603
661
  return false;
604
662
  }
663
+ if (targetChanged) this.updateExternalDiff(nextFileDiff, lineAnnotations);
664
+ const { pendingRenderDiff, layoutDiffChanged, renderedDiffChanged, annotationsChanged } = (() => {
665
+ if (this.pendingRender != null && areDiffTargetsEqual(this.pendingRender.latestDiff, this.getLatestDiff(nextFileDiff) ?? nextFileDiff)) return {
666
+ pendingRenderDiff: this.pendingRender.diff,
667
+ layoutDiffChanged: false,
668
+ renderedDiffChanged: false,
669
+ annotationsChanged: false
670
+ };
671
+ return this.updatePendingRender(nextFileDiff, lineAnnotations);
672
+ })();
673
+ if (annotationsChanged || layoutDiffChanged) this.resetLayoutCache({ includeEstimatedHeights: layoutDiffChanged });
605
674
  if (!isSetup) {
606
- this.computeApproximateSize(false, nextFileDiff);
675
+ this.computeApproximateSize(false, pendingRenderDiff);
607
676
  const virtualizer = this.getSimpleVirtualizer();
608
677
  this.top ??= this.getVirtualizedTop();
609
678
  if (this.isAdvancedMode()) this.isVisible = true;
@@ -615,35 +684,56 @@ var VirtualizedFileDiff = class extends FileDiff {
615
684
  this.isSetup = true;
616
685
  } else {
617
686
  this.top ??= this.getVirtualizedTop();
618
- if (targetChanged) {
687
+ if (layoutDiffChanged) {
619
688
  this.getSimpleVirtualizer()?.markDOMDirty();
620
- this.computeApproximateSize(false, nextFileDiff);
689
+ this.computeApproximateSize(false, pendingRenderDiff);
621
690
  }
622
691
  }
623
692
  if (!this.isVisible && this.isSimpleMode() && (!dataChanged || !isSetup)) {
624
- this.fileDiff = nextFileDiff;
625
693
  if (fileInput != null) {
626
694
  this.deletionFile = oldFile;
627
695
  this.additionFile = newFile;
628
696
  }
629
- if (targetChanged) this.cachedHeaderHTML = void 0;
697
+ if (targetChanged) this.clearReusableHeader();
698
+ this.pendingRender = void 0;
630
699
  return this.renderPlaceholder(this.height);
631
700
  }
632
701
  const windowSpecs = this.virtualizer.getWindowSpecs();
633
702
  const fileTop = this.top ?? 0;
634
- const renderRange = this.computeRenderRangeFromWindow(nextFileDiff, fileTop, windowSpecs);
703
+ const renderRange = this.computeRenderRangeFromWindow(pendingRenderDiff, fileTop, windowSpecs);
635
704
  const rendered = super.render({
636
705
  fileDiff: nextFileDiff,
637
706
  fileContainer,
638
707
  renderRange,
639
708
  lineAnnotations,
640
- forceRender: (forceRenderOverride ?? forceRender) || annotationsChanged || targetChanged,
709
+ forceRender: (forceRenderOverride ?? forceRender) || annotationsChanged || renderedDiffChanged || targetChanged,
641
710
  ...fileInput,
642
711
  ...fileInputProps
643
712
  });
713
+ if (rendered) {
714
+ if (this.getRenderedDiff() !== pendingRenderDiff) throw new Error("VirtualizedFileDiff.render: rendered a different diff than its prepared layout");
715
+ this.pendingRender = void 0;
716
+ }
644
717
  if (this.isSimpleMode() && rendered) this.getSimpleVirtualizer()?.requestHeightReconcile(this);
645
718
  return rendered;
646
719
  }
720
+ updatePendingRender(nextFileDiff, lineAnnotations) {
721
+ const latestDiff = this.getLatestDiff(nextFileDiff) ?? nextFileDiff;
722
+ const previousRenderedDiff = this.getRenderedDiff();
723
+ const { pendingRender } = this;
724
+ const previousLayoutDiff = pendingRender?.diff ?? previousRenderedDiff;
725
+ const pendingRenderDiff = this.hunksRenderer.getDiffForNextRender(latestDiff);
726
+ this.pendingRender = {
727
+ latestDiff,
728
+ diff: pendingRenderDiff
729
+ };
730
+ return {
731
+ pendingRenderDiff,
732
+ annotationsChanged: this.syncLineAnnotations(lineAnnotations),
733
+ layoutDiffChanged: !areDiffTargetsEqual(previousLayoutDiff, pendingRenderDiff),
734
+ renderedDiffChanged: !areDiffTargetsEqual(previousRenderedDiff, pendingRenderDiff)
735
+ };
736
+ }
647
737
  syncVirtualizedTop() {
648
738
  this.top = this.getVirtualizedTop();
649
739
  }
@@ -678,8 +768,8 @@ var VirtualizedFileDiff = class extends FileDiff {
678
768
  getHunkSeparatorType() {
679
769
  return getOptionHunkSeparatorType(this.options.hunkSeparators);
680
770
  }
681
- approximateLayoutCheckpoints(fileDiff = this.fileDiff) {
682
- if (!this.layoutDirty && this.cache.checkpoints.length > 0 || fileDiff == null || fileDiff.hunks.length === 0 || this.options.collapsed === true) return;
771
+ approximateLayoutCheckpoints(fileDiff) {
772
+ if (!this.layoutDirty && this.cache.checkpoints.length > 0 || fileDiff.hunks.length === 0 || this.options.collapsed === true) return;
683
773
  const { disableFileHeader = false, expandUnchanged = false, collapsedContextThreshold = 1 } = this.options;
684
774
  const finalHunkIndex = fileDiff.hunks.length - 1;
685
775
  const canHydratePartialDiff = canHydrateCollapsedContext(fileDiff, this.options.loadDiffFiles != null);