@fluidframework/merge-tree 2.12.0 → 2.20.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 (307) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/api-report/merge-tree.legacy.alpha.api.md +0 -108
  3. package/dist/MergeTreeTextHelper.d.ts.map +1 -1
  4. package/dist/MergeTreeTextHelper.js +0 -2
  5. package/dist/MergeTreeTextHelper.js.map +1 -1
  6. package/dist/attributionPolicy.d.ts.map +1 -1
  7. package/dist/attributionPolicy.js +6 -16
  8. package/dist/attributionPolicy.js.map +1 -1
  9. package/dist/client.d.ts +3 -4
  10. package/dist/client.d.ts.map +1 -1
  11. package/dist/client.js +39 -28
  12. package/dist/client.js.map +1 -1
  13. package/dist/endOfTreeSegment.d.ts +2 -1
  14. package/dist/endOfTreeSegment.d.ts.map +1 -1
  15. package/dist/endOfTreeSegment.js.map +1 -1
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +2 -4
  19. package/dist/index.js.map +1 -1
  20. package/dist/legacy.d.ts +0 -4
  21. package/dist/localReference.d.ts +5 -7
  22. package/dist/localReference.d.ts.map +1 -1
  23. package/dist/localReference.js +1 -3
  24. package/dist/localReference.js.map +1 -1
  25. package/dist/mergeTree.d.ts +8 -7
  26. package/dist/mergeTree.d.ts.map +1 -1
  27. package/dist/mergeTree.js +187 -228
  28. package/dist/mergeTree.js.map +1 -1
  29. package/dist/mergeTreeNodeWalk.d.ts.map +1 -1
  30. package/dist/mergeTreeNodeWalk.js +3 -2
  31. package/dist/mergeTreeNodeWalk.js.map +1 -1
  32. package/dist/mergeTreeNodes.d.ts +65 -325
  33. package/dist/mergeTreeNodes.d.ts.map +1 -1
  34. package/dist/mergeTreeNodes.js +96 -130
  35. package/dist/mergeTreeNodes.js.map +1 -1
  36. package/dist/mergeTreeTracking.d.ts.map +1 -1
  37. package/dist/mergeTreeTracking.js +0 -2
  38. package/dist/mergeTreeTracking.js.map +1 -1
  39. package/dist/opBuilder.d.ts +0 -5
  40. package/dist/opBuilder.d.ts.map +1 -1
  41. package/dist/opBuilder.js +0 -5
  42. package/dist/opBuilder.js.map +1 -1
  43. package/dist/package.json +2 -1
  44. package/dist/partialLengths.d.ts +2 -2
  45. package/dist/partialLengths.d.ts.map +1 -1
  46. package/dist/partialLengths.js +29 -31
  47. package/dist/partialLengths.js.map +1 -1
  48. package/dist/perspective.d.ts +3 -2
  49. package/dist/perspective.d.ts.map +1 -1
  50. package/dist/perspective.js +5 -2
  51. package/dist/perspective.js.map +1 -1
  52. package/dist/referencePositions.d.ts.map +1 -1
  53. package/dist/referencePositions.js +4 -1
  54. package/dist/referencePositions.js.map +1 -1
  55. package/dist/revertibles.d.ts.map +1 -1
  56. package/dist/revertibles.js +10 -14
  57. package/dist/revertibles.js.map +1 -1
  58. package/dist/segmentGroupCollection.d.ts +4 -4
  59. package/dist/segmentGroupCollection.d.ts.map +1 -1
  60. package/dist/segmentGroupCollection.js +0 -6
  61. package/dist/segmentGroupCollection.js.map +1 -1
  62. package/dist/segmentInfos.d.ts +251 -0
  63. package/dist/segmentInfos.d.ts.map +1 -0
  64. package/dist/segmentInfos.js +166 -0
  65. package/dist/segmentInfos.js.map +1 -0
  66. package/dist/snapshotLoader.d.ts.map +1 -1
  67. package/dist/snapshotLoader.js +36 -44
  68. package/dist/snapshotLoader.js.map +1 -1
  69. package/dist/snapshotV1.d.ts.map +1 -1
  70. package/dist/snapshotV1.js +9 -12
  71. package/dist/snapshotV1.js.map +1 -1
  72. package/dist/snapshotlegacy.d.ts +2 -2
  73. package/dist/snapshotlegacy.d.ts.map +1 -1
  74. package/dist/snapshotlegacy.js +5 -3
  75. package/dist/snapshotlegacy.js.map +1 -1
  76. package/dist/sortedSegmentSet.d.ts.map +1 -1
  77. package/dist/sortedSegmentSet.js +5 -8
  78. package/dist/sortedSegmentSet.js.map +1 -1
  79. package/dist/test/beastTest.spec.d.ts +0 -2
  80. package/dist/test/beastTest.spec.d.ts.map +1 -1
  81. package/dist/test/beastTest.spec.js +1 -5
  82. package/dist/test/beastTest.spec.js.map +1 -1
  83. package/dist/test/client.annotateMarker.spec.js.map +1 -1
  84. package/dist/test/client.applyMsg.spec.js +15 -12
  85. package/dist/test/client.applyMsg.spec.js.map +1 -1
  86. package/dist/test/client.attributionFarm.spec.js.map +1 -1
  87. package/dist/test/client.getPosition.spec.js +3 -2
  88. package/dist/test/client.getPosition.spec.js.map +1 -1
  89. package/dist/test/client.localReference.spec.js +6 -6
  90. package/dist/test/client.localReference.spec.js.map +1 -1
  91. package/dist/test/client.localReferenceFarm.spec.js.map +1 -1
  92. package/dist/test/client.rollback.spec.js.map +1 -1
  93. package/dist/test/dirname.cjs +0 -1
  94. package/dist/test/dirname.cjs.map +1 -1
  95. package/dist/test/index.d.ts +1 -1
  96. package/dist/test/index.d.ts.map +1 -1
  97. package/dist/test/index.js +2 -4
  98. package/dist/test/index.js.map +1 -1
  99. package/dist/test/mergeTree.annotate.spec.js +3 -0
  100. package/dist/test/mergeTree.annotate.spec.js.map +1 -1
  101. package/dist/test/mergeTree.insertingWalk.spec.js +1 -1
  102. package/dist/test/mergeTree.insertingWalk.spec.js.map +1 -1
  103. package/dist/test/mergeTree.markRangeRemoved.spec.js +2 -0
  104. package/dist/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
  105. package/dist/test/mergeTree.walk.spec.js.map +1 -1
  106. package/dist/test/mergeTreeOperationRunner.d.ts.map +1 -1
  107. package/dist/test/mergeTreeOperationRunner.js +2 -3
  108. package/dist/test/mergeTreeOperationRunner.js.map +1 -1
  109. package/dist/test/obliterate.spec.js.map +1 -1
  110. package/dist/test/propertyManager.spec.js.map +1 -1
  111. package/dist/test/reconnectHelper.d.ts +2 -1
  112. package/dist/test/reconnectHelper.d.ts.map +1 -1
  113. package/dist/test/reconnectHelper.js.map +1 -1
  114. package/dist/test/resetPendingSegmentsToOp.spec.js.map +1 -1
  115. package/dist/test/revertibleFarm.spec.js.map +1 -1
  116. package/dist/test/segmentGroupCollection.spec.js +15 -3
  117. package/dist/test/segmentGroupCollection.spec.js.map +1 -1
  118. package/dist/test/snapshot.utils.d.ts +2 -2
  119. package/dist/test/snapshot.utils.d.ts.map +1 -1
  120. package/dist/test/snapshot.utils.js.map +1 -1
  121. package/dist/test/sortedSegmentSet.spec.js +4 -3
  122. package/dist/test/sortedSegmentSet.spec.js.map +1 -1
  123. package/dist/test/testClient.d.ts +8 -6
  124. package/dist/test/testClient.d.ts.map +1 -1
  125. package/dist/test/testClient.js +28 -27
  126. package/dist/test/testClient.js.map +1 -1
  127. package/dist/test/testClientLogger.d.ts.map +1 -1
  128. package/dist/test/testClientLogger.js +6 -4
  129. package/dist/test/testClientLogger.js.map +1 -1
  130. package/dist/test/testUtils.d.ts +2 -2
  131. package/dist/test/testUtils.d.ts.map +1 -1
  132. package/dist/test/testUtils.js +32 -8
  133. package/dist/test/testUtils.js.map +1 -1
  134. package/dist/test/text.d.ts +2 -2
  135. package/dist/test/text.d.ts.map +1 -1
  136. package/dist/test/text.js +12 -6
  137. package/dist/test/text.js.map +1 -1
  138. package/dist/test/tracking.spec.js.map +1 -1
  139. package/dist/test/wordUnitTests.spec.js +1 -1
  140. package/dist/test/wordUnitTests.spec.js.map +1 -1
  141. package/dist/zamboni.d.ts.map +1 -1
  142. package/dist/zamboni.js +8 -7
  143. package/dist/zamboni.js.map +1 -1
  144. package/lib/MergeTreeTextHelper.d.ts.map +1 -1
  145. package/lib/MergeTreeTextHelper.js +0 -2
  146. package/lib/MergeTreeTextHelper.js.map +1 -1
  147. package/lib/attributionPolicy.d.ts.map +1 -1
  148. package/lib/attributionPolicy.js +6 -16
  149. package/lib/attributionPolicy.js.map +1 -1
  150. package/lib/client.d.ts +3 -4
  151. package/lib/client.d.ts.map +1 -1
  152. package/lib/client.js +40 -29
  153. package/lib/client.js.map +1 -1
  154. package/lib/endOfTreeSegment.d.ts +2 -1
  155. package/lib/endOfTreeSegment.d.ts.map +1 -1
  156. package/lib/endOfTreeSegment.js.map +1 -1
  157. package/lib/index.d.ts +1 -1
  158. package/lib/index.d.ts.map +1 -1
  159. package/lib/index.js +1 -1
  160. package/lib/index.js.map +1 -1
  161. package/lib/legacy.d.ts +0 -4
  162. package/lib/localReference.d.ts +5 -7
  163. package/lib/localReference.d.ts.map +1 -1
  164. package/lib/localReference.js +1 -3
  165. package/lib/localReference.js.map +1 -1
  166. package/lib/mergeTree.d.ts +8 -7
  167. package/lib/mergeTree.d.ts.map +1 -1
  168. package/lib/mergeTree.js +175 -220
  169. package/lib/mergeTree.js.map +1 -1
  170. package/lib/mergeTreeNodeWalk.d.ts.map +1 -1
  171. package/lib/mergeTreeNodeWalk.js +3 -2
  172. package/lib/mergeTreeNodeWalk.js.map +1 -1
  173. package/lib/mergeTreeNodes.d.ts +65 -325
  174. package/lib/mergeTreeNodes.d.ts.map +1 -1
  175. package/lib/mergeTreeNodes.js +92 -127
  176. package/lib/mergeTreeNodes.js.map +1 -1
  177. package/lib/mergeTreeTracking.d.ts.map +1 -1
  178. package/lib/mergeTreeTracking.js +0 -2
  179. package/lib/mergeTreeTracking.js.map +1 -1
  180. package/lib/opBuilder.d.ts +0 -5
  181. package/lib/opBuilder.d.ts.map +1 -1
  182. package/lib/opBuilder.js +0 -5
  183. package/lib/opBuilder.js.map +1 -1
  184. package/lib/partialLengths.d.ts +2 -2
  185. package/lib/partialLengths.d.ts.map +1 -1
  186. package/lib/partialLengths.js +26 -28
  187. package/lib/partialLengths.js.map +1 -1
  188. package/lib/perspective.d.ts +3 -2
  189. package/lib/perspective.d.ts.map +1 -1
  190. package/lib/perspective.js +5 -2
  191. package/lib/perspective.js.map +1 -1
  192. package/lib/referencePositions.d.ts.map +1 -1
  193. package/lib/referencePositions.js +4 -1
  194. package/lib/referencePositions.js.map +1 -1
  195. package/lib/revertibles.d.ts.map +1 -1
  196. package/lib/revertibles.js +8 -12
  197. package/lib/revertibles.js.map +1 -1
  198. package/lib/segmentGroupCollection.d.ts +4 -4
  199. package/lib/segmentGroupCollection.d.ts.map +1 -1
  200. package/lib/segmentGroupCollection.js +0 -6
  201. package/lib/segmentGroupCollection.js.map +1 -1
  202. package/lib/segmentInfos.d.ts +251 -0
  203. package/lib/segmentInfos.d.ts.map +1 -0
  204. package/lib/segmentInfos.js +145 -0
  205. package/lib/segmentInfos.js.map +1 -0
  206. package/lib/snapshotLoader.d.ts.map +1 -1
  207. package/lib/snapshotLoader.js +36 -44
  208. package/lib/snapshotLoader.js.map +1 -1
  209. package/lib/snapshotV1.d.ts.map +1 -1
  210. package/lib/snapshotV1.js +9 -12
  211. package/lib/snapshotV1.js.map +1 -1
  212. package/lib/snapshotlegacy.d.ts +2 -2
  213. package/lib/snapshotlegacy.d.ts.map +1 -1
  214. package/lib/snapshotlegacy.js +5 -3
  215. package/lib/snapshotlegacy.js.map +1 -1
  216. package/lib/sortedSegmentSet.d.ts.map +1 -1
  217. package/lib/sortedSegmentSet.js +5 -8
  218. package/lib/sortedSegmentSet.js.map +1 -1
  219. package/lib/test/beastTest.spec.d.ts +0 -2
  220. package/lib/test/beastTest.spec.d.ts.map +1 -1
  221. package/lib/test/beastTest.spec.js +0 -3
  222. package/lib/test/beastTest.spec.js.map +1 -1
  223. package/lib/test/client.annotateMarker.spec.js.map +1 -1
  224. package/lib/test/client.applyMsg.spec.js +15 -12
  225. package/lib/test/client.applyMsg.spec.js.map +1 -1
  226. package/lib/test/client.attributionFarm.spec.js.map +1 -1
  227. package/lib/test/client.getPosition.spec.js +3 -2
  228. package/lib/test/client.getPosition.spec.js.map +1 -1
  229. package/lib/test/client.localReference.spec.js +1 -1
  230. package/lib/test/client.localReference.spec.js.map +1 -1
  231. package/lib/test/client.localReferenceFarm.spec.js.map +1 -1
  232. package/lib/test/client.rollback.spec.js +1 -1
  233. package/lib/test/client.rollback.spec.js.map +1 -1
  234. package/lib/test/dirname.cjs +0 -1
  235. package/lib/test/dirname.cjs.map +1 -1
  236. package/lib/test/index.d.ts +1 -1
  237. package/lib/test/index.d.ts.map +1 -1
  238. package/lib/test/index.js +1 -1
  239. package/lib/test/index.js.map +1 -1
  240. package/lib/test/mergeTree.annotate.spec.js +3 -0
  241. package/lib/test/mergeTree.annotate.spec.js.map +1 -1
  242. package/lib/test/mergeTree.insertingWalk.spec.js +2 -2
  243. package/lib/test/mergeTree.insertingWalk.spec.js.map +1 -1
  244. package/lib/test/mergeTree.markRangeRemoved.spec.js +2 -0
  245. package/lib/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
  246. package/lib/test/mergeTree.walk.spec.js.map +1 -1
  247. package/lib/test/mergeTreeOperationRunner.d.ts.map +1 -1
  248. package/lib/test/mergeTreeOperationRunner.js +1 -2
  249. package/lib/test/mergeTreeOperationRunner.js.map +1 -1
  250. package/lib/test/obliterate.spec.js.map +1 -1
  251. package/lib/test/propertyManager.spec.js.map +1 -1
  252. package/lib/test/reconnectHelper.d.ts +2 -1
  253. package/lib/test/reconnectHelper.d.ts.map +1 -1
  254. package/lib/test/reconnectHelper.js.map +1 -1
  255. package/lib/test/resetPendingSegmentsToOp.spec.js.map +1 -1
  256. package/lib/test/revertibleFarm.spec.js.map +1 -1
  257. package/lib/test/segmentGroupCollection.spec.js +15 -3
  258. package/lib/test/segmentGroupCollection.spec.js.map +1 -1
  259. package/lib/test/snapshot.utils.d.ts +2 -2
  260. package/lib/test/snapshot.utils.d.ts.map +1 -1
  261. package/lib/test/snapshot.utils.js.map +1 -1
  262. package/lib/test/sortedSegmentSet.spec.js +4 -3
  263. package/lib/test/sortedSegmentSet.spec.js.map +1 -1
  264. package/lib/test/testClient.d.ts +8 -6
  265. package/lib/test/testClient.d.ts.map +1 -1
  266. package/lib/test/testClient.js +29 -28
  267. package/lib/test/testClient.js.map +1 -1
  268. package/lib/test/testClientLogger.d.ts.map +1 -1
  269. package/lib/test/testClientLogger.js +5 -3
  270. package/lib/test/testClientLogger.js.map +1 -1
  271. package/lib/test/testUtils.d.ts +2 -2
  272. package/lib/test/testUtils.d.ts.map +1 -1
  273. package/lib/test/testUtils.js +9 -8
  274. package/lib/test/testUtils.js.map +1 -1
  275. package/lib/test/text.d.ts +2 -2
  276. package/lib/test/text.d.ts.map +1 -1
  277. package/lib/test/text.js +12 -6
  278. package/lib/test/text.js.map +1 -1
  279. package/lib/test/tracking.spec.js.map +1 -1
  280. package/lib/test/wordUnitTests.spec.js +1 -1
  281. package/lib/test/wordUnitTests.spec.js.map +1 -1
  282. package/lib/zamboni.d.ts.map +1 -1
  283. package/lib/zamboni.js +7 -6
  284. package/lib/zamboni.js.map +1 -1
  285. package/package.json +77 -19
  286. package/src/MergeTreeTextHelper.ts +2 -4
  287. package/src/attributionPolicy.ts +5 -13
  288. package/src/client.ts +55 -44
  289. package/src/endOfTreeSegment.ts +3 -5
  290. package/src/index.ts +0 -7
  291. package/src/localReference.ts +6 -8
  292. package/src/mergeTree.ts +233 -290
  293. package/src/mergeTreeNodeWalk.ts +3 -2
  294. package/src/mergeTreeNodes.ts +160 -490
  295. package/src/mergeTreeTracking.ts +0 -3
  296. package/src/opBuilder.ts +0 -5
  297. package/src/partialLengths.ts +40 -29
  298. package/src/perspective.ts +23 -4
  299. package/src/referencePositions.ts +4 -1
  300. package/src/revertibles.ts +19 -16
  301. package/src/segmentGroupCollection.ts +7 -18
  302. package/src/segmentInfos.ts +371 -0
  303. package/src/snapshotLoader.ts +56 -57
  304. package/src/snapshotV1.ts +14 -16
  305. package/src/snapshotlegacy.ts +12 -17
  306. package/src/sortedSegmentSet.ts +6 -8
  307. package/src/zamboni.ts +10 -12
package/src/mergeTree.ts CHANGED
@@ -20,7 +20,6 @@ import {
20
20
  } from "./constants.js";
21
21
  import { EndOfTreeSegment, StartOfTreeSegment } from "./endOfTreeSegment.js";
22
22
  import {
23
- // eslint-disable-next-line import/no-deprecated
24
23
  LocalReferenceCollection,
25
24
  LocalReferencePosition,
26
25
  SlidingPreference,
@@ -43,29 +42,24 @@ import {
43
42
  walkAllChildSegments,
44
43
  } from "./mergeTreeNodeWalk.js";
45
44
  import {
46
- BlockAction,
47
- // eslint-disable-next-line import/no-deprecated
48
45
  CollaborationWindow,
49
46
  IMergeNode,
50
- // eslint-disable-next-line import/no-deprecated
51
- IMoveInfo,
52
- // eslint-disable-next-line import/no-deprecated
53
- IRemovalInfo,
54
47
  ISegmentAction,
55
48
  ISegmentChanges,
56
- ISegmentLeaf,
57
49
  InsertContext,
58
50
  Marker,
59
51
  MaxNodesInBlock,
60
52
  MergeBlock,
61
- // eslint-disable-next-line import/no-deprecated
62
53
  SegmentGroup,
54
+ assertSegmentLeaf,
55
+ assignChild,
56
+ isSegmentLeaf,
63
57
  reservedMarkerIdKey,
64
58
  seqLTE,
65
- toMoveInfo,
66
- toRemovalInfo,
59
+ type IMergeNodeBuilder,
67
60
  type ISegmentInternal,
68
- // eslint-disable-next-line import/no-deprecated
61
+ type ISegmentLeaf,
62
+ type ISegmentPrivate,
69
63
  type ObliterateInfo,
70
64
  } from "./mergeTreeNodes.js";
71
65
  import type { TrackingGroup } from "./mergeTreeTracking.js";
@@ -90,9 +84,22 @@ import {
90
84
  refHasTileLabel,
91
85
  refTypeIncludesFlag,
92
86
  } from "./referencePositions.js";
93
- // eslint-disable-next-line import/no-deprecated
94
87
  import { SegmentGroupCollection } from "./segmentGroupCollection.js";
95
- // eslint-disable-next-line import/no-deprecated
88
+ import {
89
+ assertMoved,
90
+ assertRemoved,
91
+ isMergeNodeInfo,
92
+ isMoved,
93
+ isRemoved,
94
+ overwriteInfo,
95
+ removeRemovalInfo,
96
+ toMoveInfo,
97
+ toRemovalInfo,
98
+ type IInsertionInfo,
99
+ type IMoveInfo,
100
+ type IRemovalInfo,
101
+ type SegmentWithInfo,
102
+ } from "./segmentInfos.js";
96
103
  import {
97
104
  copyPropertiesAndManager,
98
105
  PropertiesManager,
@@ -103,39 +110,17 @@ import { Side, type InteriorSequencePlace } from "./sequencePlace.js";
103
110
  import { SortedSegmentSet } from "./sortedSegmentSet.js";
104
111
  import { zamboniSegments } from "./zamboni.js";
105
112
 
106
- // eslint-disable-next-line import/no-deprecated
107
- function markSegmentMoved(seg: ISegmentLeaf, moveInfo: IMoveInfo): void {
108
- seg.moveDst = moveInfo.moveDst;
109
- seg.movedClientIds = [...moveInfo.movedClientIds];
110
- seg.movedSeqs = [moveInfo.movedSeq];
111
- seg.movedSeq = moveInfo.movedSeq;
112
- seg.localMovedSeq = moveInfo.localMovedSeq;
113
- seg.wasMovedOnInsert = moveInfo.wasMovedOnInsert;
114
- }
115
-
116
- // eslint-disable-next-line import/no-deprecated
117
- function isMoved(segment: ISegmentLeaf): segment is ISegmentLeaf & IMoveInfo {
118
- return toMoveInfo(segment) !== undefined;
119
- }
120
-
121
- // eslint-disable-next-line import/no-deprecated
122
- function isRemoved(segment: ISegmentLeaf): segment is ISegmentLeaf & IRemovalInfo {
123
- return toRemovalInfo(segment) !== undefined;
124
- }
125
-
126
- // eslint-disable-next-line import/no-deprecated
127
- function isRemovedAndAcked(segment: ISegmentLeaf): segment is ISegmentLeaf & IRemovalInfo {
113
+ function isRemovedAndAcked(segment: ISegmentPrivate): segment is ISegmentLeaf & IRemovalInfo {
128
114
  const removalInfo = toRemovalInfo(segment);
129
115
  return removalInfo !== undefined && removalInfo.removedSeq !== UnassignedSequenceNumber;
130
116
  }
131
117
 
132
- // eslint-disable-next-line import/no-deprecated
133
- function isMovedAndAcked(segment: ISegmentLeaf): segment is ISegmentLeaf & IMoveInfo {
118
+ function isMovedAndAcked(segment: ISegmentPrivate): segment is ISegmentLeaf & IMoveInfo {
134
119
  const moveInfo = toMoveInfo(segment);
135
120
  return moveInfo !== undefined && moveInfo.movedSeq !== UnassignedSequenceNumber;
136
121
  }
137
122
 
138
- function isRemovedAndAckedOrMovedAndAcked(segment: ISegmentLeaf): boolean {
123
+ function isRemovedAndAckedOrMovedAndAcked(segment: ISegmentPrivate): boolean {
139
124
  return isRemovedAndAcked(segment) || isMovedAndAcked(segment);
140
125
  }
141
126
 
@@ -188,12 +173,10 @@ function ackSegment(
188
173
  }
189
174
 
190
175
  case MergeTreeDeltaType.REMOVE: {
191
- // eslint-disable-next-line import/no-deprecated
192
- const removalInfo: IRemovalInfo | undefined = toRemovalInfo(segment);
193
- assert(removalInfo !== undefined, 0x046 /* "On remove ack, missing removal info!" */);
176
+ assertRemoved(segment);
194
177
  segment.localRemovedSeq = undefined;
195
- if (removalInfo.removedSeq === UnassignedSequenceNumber) {
196
- removalInfo.removedSeq = sequenceNumber;
178
+ if (segment.removedSeq === UnassignedSequenceNumber) {
179
+ segment.removedSeq = sequenceNumber;
197
180
  return true;
198
181
  }
199
182
  return false;
@@ -201,18 +184,16 @@ function ackSegment(
201
184
 
202
185
  case MergeTreeDeltaType.OBLITERATE:
203
186
  case MergeTreeDeltaType.OBLITERATE_SIDED: {
204
- // eslint-disable-next-line import/no-deprecated
205
- const moveInfo: IMoveInfo | undefined = toMoveInfo(segment);
206
- assert(moveInfo !== undefined, 0x86e /* On obliterate ack, missing move info! */);
187
+ assertMoved(segment);
207
188
  const obliterateInfo = segmentGroup.obliterateInfo;
208
189
  assert(obliterateInfo !== undefined, 0xa40 /* must have obliterate info */);
209
190
  segment.localMovedSeq = obliterateInfo.localSeq = undefined;
210
- const seqIdx = moveInfo.movedSeqs.indexOf(UnassignedSequenceNumber);
191
+ const seqIdx = segment.movedSeqs.indexOf(UnassignedSequenceNumber);
211
192
  assert(seqIdx !== -1, 0x86f /* expected movedSeqs to contain unacked seq */);
212
- moveInfo.movedSeqs[seqIdx] = sequenceNumber;
193
+ segment.movedSeqs[seqIdx] = sequenceNumber;
213
194
 
214
- if (moveInfo.movedSeq === UnassignedSequenceNumber) {
215
- moveInfo.movedSeq = sequenceNumber;
195
+ if (segment.movedSeq === UnassignedSequenceNumber) {
196
+ segment.movedSeq = sequenceNumber;
216
197
  return true;
217
198
  }
218
199
 
@@ -405,7 +386,6 @@ export function findRootMergeBlock(
405
386
  * entries for all segments visited during excursion.
406
387
  * This can reduce the number of times the tree needs to be scanned if a range containing many
407
388
  * SlideOnRemove references is removed.
408
- * @internal
409
389
  */
410
390
  function getSlideToSegment(
411
391
  segment: ISegmentLeaf | undefined,
@@ -434,7 +414,8 @@ function getSlideToSegment(
434
414
  }
435
415
  if (
436
416
  cache !== undefined &&
437
- (seg.removedSeq === segment.removedSeq || seg.movedSeq === segment.movedSeq)
417
+ (toRemovalInfo(seg)?.removedSeq === toRemovalInfo(segment)?.removedSeq ||
418
+ toMoveInfo(seg)?.movedSeq === toMoveInfo(segment)?.movedSeq)
438
419
  ) {
439
420
  cache.set(seg, result);
440
421
  }
@@ -492,7 +473,7 @@ export function getSlideToSegoff(
492
473
  segment: ISegmentInternal | undefined;
493
474
  offset: number | undefined;
494
475
  } {
495
- if (segoff.segment === undefined) {
476
+ if (!isSegmentLeaf(segoff.segment)) {
496
477
  return segoff;
497
478
  }
498
479
  const [segment, _] = getSlideToSegment(
@@ -527,7 +508,7 @@ class Obliterates {
527
508
  * See https://github.com/microsoft/FluidFramework/blob/main/packages/dds/merge-tree/docs/Obliterate.md#remote-perspective
528
509
  * for additional context
529
510
  */
530
- // eslint-disable-next-line import/no-deprecated
511
+
531
512
  private readonly seqOrdered = new DoublyLinkedList<ObliterateInfo>();
532
513
 
533
514
  /**
@@ -549,7 +530,6 @@ class Obliterates {
549
530
  }
550
531
  }
551
532
 
552
- // eslint-disable-next-line import/no-deprecated
553
533
  public addOrUpdate(obliterateInfo: ObliterateInfo): void {
554
534
  const { seq, start } = obliterateInfo;
555
535
  if (seq !== UnassignedSequenceNumber) {
@@ -562,14 +542,14 @@ class Obliterates {
562
542
  return this.startOrdered.size === 0;
563
543
  }
564
544
 
565
- // eslint-disable-next-line import/no-deprecated
566
545
  public findOverlapping(seg: ISegmentLeaf): Iterable<ObliterateInfo> {
567
- // eslint-disable-next-line import/no-deprecated
568
546
  const overlapping: ObliterateInfo[] = [];
569
547
  for (const start of this.startOrdered.items) {
570
- if (start.getSegment()!.ordinal <= seg.ordinal) {
548
+ const startSeg = start.getSegment();
549
+ if (isMergeNodeInfo(startSeg) && startSeg.ordinal <= seg.ordinal) {
571
550
  const ob = start.properties?.obliterate as ObliterateInfo;
572
- if (ob.end.getSegment()!.ordinal >= seg.ordinal) {
551
+ const endSeg = ob.end.getSegment();
552
+ if (isMergeNodeInfo(endSeg) && endSeg.ordinal >= seg.ordinal) {
573
553
  overlapping.push(ob);
574
554
  }
575
555
  } else {
@@ -593,10 +573,8 @@ export class MergeTree {
593
573
 
594
574
  private static readonly theUnfinishedNode = { childCount: -1 } as unknown as MergeBlock;
595
575
 
596
- // eslint-disable-next-line import/no-deprecated
597
576
  public readonly collabWindow = new CollaborationWindow();
598
577
 
599
- // eslint-disable-next-line import/no-deprecated
600
578
  public readonly pendingSegments = new DoublyLinkedList<SegmentGroup>();
601
579
 
602
580
  public readonly segmentsToScour = new Heap<LRUSegment>(LRUSegmentComparer);
@@ -675,7 +653,9 @@ export class MergeTree {
675
653
  0x398 /* localSeq provided for local length without refSeq */,
676
654
  );
677
655
  assert(segment.seq !== undefined, 0x399 /* segment with no seq in mergeTree */);
678
- const { seq, removedSeq, localRemovedSeq, movedSeq, localMovedSeq } = segment;
656
+ const { seq } = segment;
657
+ const { removedSeq, localRemovedSeq } = removalInfo ?? {};
658
+ const { movedSeq, localMovedSeq } = moveInfo ?? {};
679
659
  if (seq === UnassignedSequenceNumber) {
680
660
  assert(
681
661
  segment.localSeq !== undefined,
@@ -717,13 +697,13 @@ export class MergeTree {
717
697
  }
718
698
  }
719
699
 
720
- private addNode(block: MergeBlock, node: IMergeNode): number {
700
+ private addNode(block: MergeBlock, node: IMergeNodeBuilder): number {
721
701
  const index = block.childCount++;
722
- block.assignChild(node, index, false);
702
+ assignChild(block, node, index, false);
723
703
  return index;
724
704
  }
725
705
 
726
- public reloadFromSegments(segments: ISegmentLeaf[]): void {
706
+ public reloadFromSegments(segments: SegmentWithInfo<IInsertionInfo>[]): void {
727
707
  // This code assumes that a later call to `startCollaboration()` will initialize partial lengths.
728
708
  assert(
729
709
  !this.collabWindow.collaborating,
@@ -733,7 +713,7 @@ export class MergeTree {
733
713
  const maxChildren = MaxNodesInBlock - 1;
734
714
 
735
715
  // Starting with the leaf segments, recursively builds the B-Tree layer by layer from the bottom up.
736
- const buildMergeBlock = (nodes: IMergeNode[]): IRootMergeBlock => {
716
+ const buildMergeBlock = (nodes: IMergeNodeBuilder[]): IRootMergeBlock => {
737
717
  const blockCount = Math.ceil(nodes.length / maxChildren); // Compute # blocks require for this level of B-Tree
738
718
  const blocks: MergeBlock[] = Array.from({ length: blockCount }); // Pre-alloc array to collect nodes
739
719
 
@@ -789,8 +769,8 @@ export class MergeTree {
789
769
 
790
770
  // TODO: 'seq' may be less than the current sequence number when inserting pre-ACKed
791
771
  // segments from a snapshot. We currently skip these for now.
792
- if (leaf.parent!.needsScour !== true && seq > this.collabWindow.currentSeq) {
793
- leaf.parent!.needsScour = true;
772
+ if (leaf.parent.needsScour !== true && seq > this.collabWindow.currentSeq) {
773
+ leaf.parent.needsScour = true;
794
774
  this.segmentsToScour.add({ segment: leaf, maxSeq: seq });
795
775
  }
796
776
  }
@@ -834,34 +814,28 @@ export class MergeTree {
834
814
  return totalOffset;
835
815
  }
836
816
 
837
- public getContainingSegment<T extends ISegmentLeaf>(
817
+ public getContainingSegment(
838
818
  pos: number,
839
819
  refSeq: number,
840
820
  clientId: number,
841
821
  localSeq?: number,
842
822
  ): {
843
- segment: T | undefined;
823
+ segment: ISegmentLeaf | undefined;
844
824
  offset: number | undefined;
845
825
  } {
846
826
  assert(
847
827
  localSeq === undefined || clientId === this.collabWindow.clientId,
848
828
  0x39b /* localSeq provided for non-local client */,
849
829
  );
850
- let segment: T | undefined;
830
+ let segment: ISegmentLeaf | undefined;
851
831
  let offset: number | undefined;
852
832
 
853
- const leaf = (
854
- leafSeg: ISegmentLeaf,
855
- segpos: number,
856
- _refSeq: number,
857
- _clientId: number,
858
- start: number,
859
- ): boolean => {
860
- segment = leafSeg as T;
833
+ const leaf = (leafSeg: ISegmentLeaf, _: number, start: number): boolean => {
834
+ segment = leafSeg;
861
835
  offset = start;
862
836
  return false;
863
837
  };
864
- this.nodeMap(refSeq, clientId, leaf, undefined, undefined, pos, pos + 1, localSeq);
838
+ this.nodeMap(refSeq, clientId, leaf, undefined, pos, pos + 1, localSeq);
865
839
  return { segment, offset };
866
840
  }
867
841
 
@@ -887,9 +861,7 @@ export class MergeTree {
887
861
  */
888
862
  private slideAckedRemovedSegmentReferences(segments: ISegmentLeaf[]): void {
889
863
  // References are slid in groups to preserve their order.
890
- // eslint-disable-next-line import/no-deprecated
891
864
  let currentForwardSlideGroup: LocalReferenceCollection[] = [];
892
- // eslint-disable-next-line import/no-deprecated
893
865
  let currentBackwardSlideGroup: LocalReferenceCollection[] = [];
894
866
 
895
867
  let currentForwardMaybeEndpoint: "start" | "end" | undefined;
@@ -903,7 +875,6 @@ export class MergeTree {
903
875
  const slideGroup = (
904
876
  currentSlideDestination: ISegmentLeaf | undefined,
905
877
  currentSlideIsForward: boolean | undefined,
906
- // eslint-disable-next-line import/no-deprecated
907
878
  currentSlideGroup: LocalReferenceCollection[],
908
879
  pred: (ref: LocalReferencePosition) => boolean,
909
880
  maybeEndpoint: "start" | "end" | undefined,
@@ -928,7 +899,6 @@ export class MergeTree {
928
899
 
929
900
  if (maybeEndpoint) {
930
901
  const endpoint = maybeEndpoint === "start" ? this.startOfTree : this.endOfTree;
931
- // eslint-disable-next-line import/no-deprecated
932
902
  const localRefs = LocalReferenceCollection.setOrGet(endpoint);
933
903
  if (currentSlideIsForward) {
934
904
  localRefs.addBeforeTombstones(...endpointRefsToAdd);
@@ -948,7 +918,6 @@ export class MergeTree {
948
918
  }
949
919
  }
950
920
  } else {
951
- // eslint-disable-next-line import/no-deprecated
952
921
  const localRefs = LocalReferenceCollection.setOrGet(currentSlideDestination);
953
922
  if (currentSlideIsForward) {
954
923
  localRefs.addBeforeTombstones(...nonEndpointRefsToAdd);
@@ -962,13 +931,11 @@ export class MergeTree {
962
931
  segment: ISegmentLeaf,
963
932
  currentSlideDestination: ISegmentLeaf | undefined,
964
933
  currentSlideIsForward: boolean | undefined,
965
- // eslint-disable-next-line import/no-deprecated
966
934
  currentSlideGroup: LocalReferenceCollection[],
967
935
  pred: (ref: LocalReferencePosition) => boolean,
968
936
  slidingPreference: SlidingPreference,
969
937
  currentMaybeEndpoint: "start" | "end" | undefined,
970
938
  reassign: (
971
- // eslint-disable-next-line import/no-deprecated
972
939
  localRefs: LocalReferenceCollection,
973
940
  slideToSegment: ISegmentLeaf | undefined,
974
941
  slideIsForward: boolean,
@@ -1091,7 +1058,6 @@ export class MergeTree {
1091
1058
  return;
1092
1059
  }
1093
1060
 
1094
- // eslint-disable-next-line import/no-deprecated
1095
1061
  const rebaseCollabWindow = new CollaborationWindow();
1096
1062
  rebaseCollabWindow.loadFrom(this.collabWindow);
1097
1063
  if (refSeq < this.collabWindow.minSeq) {
@@ -1214,13 +1180,13 @@ export class MergeTree {
1214
1180
  clientId = this.collabWindow.clientId,
1215
1181
  localSeq: number | undefined = this.collabWindow.localSeq,
1216
1182
  ): number {
1217
- const seg: ISegmentLeaf | undefined = refPos.getSegment();
1218
- if (seg?.parent === undefined) {
1183
+ const seg = refPos.getSegment();
1184
+ if (!isSegmentLeaf(seg)) {
1219
1185
  // We have no idea where this reference is, because it refers to a segment which is not in the tree.
1220
1186
  return DetachedReferencePosition;
1221
1187
  }
1222
1188
  if (refPos.isLeaf()) {
1223
- return this.getPosition(refPos, refSeq, clientId, localSeq);
1189
+ return this.getPosition(seg, refSeq, clientId, localSeq);
1224
1190
  }
1225
1191
  if (refTypeIncludesFlag(refPos, ReferenceType.Transient) || seg.localRefs?.has(refPos)) {
1226
1192
  if (
@@ -1229,13 +1195,15 @@ export class MergeTree {
1229
1195
  !isSegmentPresent(seg, { refSeq, localSeq })
1230
1196
  ) {
1231
1197
  const forward = refPos.slidingPreference === SlidingPreference.FORWARD;
1198
+ const moveInfo = toMoveInfo(seg);
1199
+ const removeInfo = toRemovalInfo(seg);
1232
1200
  const slideSeq =
1233
- seg.movedSeq !== UnassignedSequenceNumber && seg.movedSeq !== undefined
1234
- ? seg.movedSeq
1235
- : seg.removedSeq !== UnassignedSequenceNumber && seg.removedSeq !== undefined
1236
- ? seg.removedSeq
1201
+ moveInfo !== undefined && moveInfo.movedSeq !== UnassignedSequenceNumber
1202
+ ? moveInfo.movedSeq
1203
+ : removeInfo !== undefined && removeInfo.removedSeq !== UnassignedSequenceNumber
1204
+ ? removeInfo.removedSeq
1237
1205
  : refSeq;
1238
- const slideLocalSeq = seg.localMovedSeq ?? seg.localRemovedSeq;
1206
+ const slideLocalSeq = moveInfo?.localMovedSeq ?? removeInfo?.localRemovedSeq;
1239
1207
  const perspective = new PerspectiveImpl(this, {
1240
1208
  refSeq: slideSeq,
1241
1209
  localSeq: slideLocalSeq,
@@ -1272,14 +1240,13 @@ export class MergeTree {
1272
1240
  let foundMarker: Marker | undefined;
1273
1241
 
1274
1242
  const { segment } = this.getContainingSegment(startPos, UniversalSequenceNumber, clientId);
1275
- const segWithParent: ISegmentLeaf | undefined = segment;
1276
- if (segWithParent?.parent === undefined) {
1243
+ if (!isSegmentLeaf(segment)) {
1277
1244
  return undefined;
1278
1245
  }
1279
1246
 
1280
1247
  depthFirstNodeWalk(
1281
- segWithParent.parent,
1282
- segWithParent,
1248
+ segment.parent,
1249
+ segment,
1283
1250
  (node) => {
1284
1251
  if (node.isLeaf()) {
1285
1252
  if (Marker.is(node) && refHasTileLabel(node, markerLabel)) {
@@ -1310,8 +1277,8 @@ export class MergeTree {
1310
1277
  private updateRoot(splitNode: MergeBlock | undefined): void {
1311
1278
  if (splitNode !== undefined) {
1312
1279
  const newRoot = this.makeBlock(2);
1313
- newRoot.assignChild(this.root, 0, false);
1314
- newRoot.assignChild(splitNode, 1, false);
1280
+ assignChild(newRoot, this.root, 0, false);
1281
+ assignChild(newRoot, splitNode, 1, false);
1315
1282
  this.root = newRoot;
1316
1283
  this.nodeUpdateOrdinals(this.root);
1317
1284
  this.nodeUpdateLengthNewStructure(this.root);
@@ -1339,8 +1306,8 @@ export class MergeTree {
1339
1306
  if (MergeTree.options.zamboniSegments) {
1340
1307
  this.addToLRUSet(pendingSegment, seq);
1341
1308
  }
1342
- if (!nodesToUpdate.includes(pendingSegment.parent!)) {
1343
- nodesToUpdate.push(pendingSegment.parent!);
1309
+ if (!nodesToUpdate.includes(pendingSegment.parent)) {
1310
+ nodesToUpdate.push(pendingSegment.parent);
1344
1311
  }
1345
1312
  deltaSegments.push({
1346
1313
  segment: pendingSegment,
@@ -1381,11 +1348,10 @@ export class MergeTree {
1381
1348
 
1382
1349
  private addToPendingList(
1383
1350
  segment: ISegmentLeaf,
1384
- // eslint-disable-next-line import/no-deprecated
1351
+
1385
1352
  segmentGroup?: SegmentGroup,
1386
1353
  localSeq?: number,
1387
1354
  previousProps?: PropertySet,
1388
- // eslint-disable-next-line import/no-deprecated
1389
1355
  ): SegmentGroup {
1390
1356
  let _segmentGroup = segmentGroup;
1391
1357
  if (_segmentGroup === undefined) {
@@ -1409,7 +1375,7 @@ export class MergeTree {
1409
1375
  if (previousProps) {
1410
1376
  _segmentGroup.previousProps!.push(previousProps);
1411
1377
  }
1412
- // eslint-disable-next-line import/no-deprecated
1378
+
1413
1379
  const segmentGroups = (segment.segmentGroups ??= new SegmentGroupCollection(segment));
1414
1380
  segmentGroups.enqueue(_segmentGroup);
1415
1381
  return _segmentGroup;
@@ -1442,7 +1408,7 @@ export class MergeTree {
1442
1408
  if (relativePos.id) {
1443
1409
  marker = this.getMarkerFromId(relativePos.id);
1444
1410
  }
1445
- if (marker) {
1411
+ if (isSegmentLeaf(marker)) {
1446
1412
  pos = this.getPosition(marker, refseq, clientId);
1447
1413
  if (relativePos.before) {
1448
1414
  if (relativePos.offset !== undefined) {
@@ -1460,7 +1426,7 @@ export class MergeTree {
1460
1426
 
1461
1427
  public insertSegments(
1462
1428
  pos: number,
1463
- segments: ISegmentLeaf[],
1429
+ segments: ISegmentPrivate[],
1464
1430
  refSeq: number,
1465
1431
  clientId: number,
1466
1432
  seq: number,
@@ -1527,7 +1493,7 @@ export class MergeTree {
1527
1493
 
1528
1494
  const { currentSeq, clientId } = this.collabWindow;
1529
1495
 
1530
- if (segmentInfo?.segment) {
1496
+ if (isSegmentLeaf(segmentInfo?.segment)) {
1531
1497
  const segmentPosition = this.getPosition(segmentInfo.segment, currentSeq, clientId);
1532
1498
  return segmentPosition + segmentInfo.offset!;
1533
1499
  } else {
@@ -1537,7 +1503,7 @@ export class MergeTree {
1537
1503
  }
1538
1504
  }
1539
1505
 
1540
- private blockInsert<T extends ISegmentLeaf>(
1506
+ private blockInsert<T extends ISegmentPrivate>(
1541
1507
  pos: number,
1542
1508
  refSeq: number,
1543
1509
  clientId: number,
@@ -1555,7 +1521,7 @@ export class MergeTree {
1555
1521
  });
1556
1522
  return siblingExists;
1557
1523
  };
1558
- // eslint-disable-next-line import/no-deprecated
1524
+
1559
1525
  let segmentGroup: SegmentGroup;
1560
1526
  const saveIfLocal = (locSegment: ISegmentLeaf): void => {
1561
1527
  // Save segment so we can assign sequence number when acked by server
@@ -1570,10 +1536,10 @@ export class MergeTree {
1570
1536
  // In all other cases this has to be true (checked by addToLRUSet):
1571
1537
  // locSegment.seq > this.collabWindow.currentSeq
1572
1538
  else if (
1573
- locSegment.seq! > this.collabWindow.minSeq &&
1539
+ locSegment.seq > this.collabWindow.minSeq &&
1574
1540
  MergeTree.options.zamboniSegments
1575
1541
  ) {
1576
- this.addToLRUSet(locSegment, locSegment.seq!);
1542
+ this.addToLRUSet(locSegment, locSegment.seq);
1577
1543
  }
1578
1544
  }
1579
1545
  };
@@ -1582,6 +1548,7 @@ export class MergeTree {
1582
1548
  _pos: number,
1583
1549
  context: InsertContext,
1584
1550
  // Keeping this function within the scope of blockInsert for readability.
1551
+ // eslint-disable-next-line unicorn/consistent-function-scoping
1585
1552
  ): ISegmentChanges => {
1586
1553
  const segmentChanges: ISegmentChanges = {};
1587
1554
  if (segment) {
@@ -1594,107 +1561,108 @@ export class MergeTree {
1594
1561
  return segmentChanges;
1595
1562
  };
1596
1563
 
1564
+ const insertInfo: IInsertionInfo = {
1565
+ clientId,
1566
+ seq,
1567
+ localSeq,
1568
+ };
1597
1569
  // TODO: build tree from segs and insert all at once
1598
1570
  let insertPos = pos;
1599
- for (const newSegment of newSegments) {
1600
- if (newSegment.cachedLength > 0) {
1601
- newSegment.seq = seq;
1602
- newSegment.localSeq = localSeq;
1603
- newSegment.clientId = clientId;
1604
- if (Marker.is(newSegment)) {
1605
- const markerId = newSegment.getId();
1606
- if (markerId) {
1607
- this.idToMarker.set(markerId, newSegment);
1608
- }
1571
+ for (const newSegment of newSegments
1572
+ .filter((s) => s.cachedLength > 0)
1573
+ .map((s) => overwriteInfo(s, insertInfo))) {
1574
+ if (Marker.is(newSegment)) {
1575
+ const markerId = newSegment.getId();
1576
+ if (markerId) {
1577
+ this.idToMarker.set(markerId, newSegment);
1609
1578
  }
1579
+ }
1610
1580
 
1611
- const splitNode = this.insertingWalk(this.root, insertPos, refSeq, clientId, seq, {
1612
- leaf: onLeaf,
1613
- candidateSegment: newSegment,
1614
- continuePredicate: continueFrom,
1615
- });
1581
+ const splitNode = this.insertingWalk(this.root, insertPos, refSeq, clientId, seq, {
1582
+ leaf: onLeaf,
1583
+ candidateSegment: newSegment,
1584
+ continuePredicate: continueFrom,
1585
+ });
1616
1586
 
1617
- if (newSegment.parent === undefined) {
1618
- // Indicates an attempt to insert past the end of the merge-tree's content.
1619
- const errorConstructor = localSeq === undefined ? DataProcessingError : UsageError;
1620
- throw new errorConstructor("MergeTree insert failed", {
1621
- currentSeq: this.collabWindow.currentSeq,
1622
- minSeq: this.collabWindow.minSeq,
1623
- segSeq: newSegment.seq,
1624
- });
1625
- }
1587
+ if (!isSegmentLeaf(newSegment)) {
1588
+ // Indicates an attempt to insert past the end of the merge-tree's content.
1589
+ const errorConstructor = localSeq === undefined ? DataProcessingError : UsageError;
1590
+ throw new errorConstructor("MergeTree insert failed", {
1591
+ currentSeq: this.collabWindow.currentSeq,
1592
+ minSeq: this.collabWindow.minSeq,
1593
+ segSeq: insertInfo.seq,
1594
+ });
1595
+ }
1626
1596
 
1627
- this.updateRoot(splitNode);
1597
+ this.updateRoot(splitNode);
1628
1598
 
1629
- insertPos += newSegment.cachedLength;
1599
+ insertPos += newSegment.cachedLength;
1630
1600
 
1631
- if (!this.options?.mergeTreeEnableObliterate || this.obliterates.empty()) {
1632
- saveIfLocal(newSegment);
1633
- continue;
1634
- }
1601
+ if (!this.options?.mergeTreeEnableObliterate || this.obliterates.empty()) {
1602
+ saveIfLocal(newSegment);
1603
+ continue;
1604
+ }
1635
1605
 
1636
- let oldest: ObliterateInfo | undefined;
1637
- let normalizedOldestSeq: number = 0;
1638
- let newest: ObliterateInfo | undefined;
1639
- let normalizedNewestSeq: number = 0;
1640
- const movedClientIds: number[] = [];
1641
- const movedSeqs: number[] = [];
1642
- for (const ob of this.obliterates.findOverlapping(newSegment)) {
1643
- // compute a normalized seq that takes into account local seqs
1644
- // but is still comparable to remote seqs to keep the checks below easy
1645
- // REMOTE SEQUENCE NUMBERS LOCAL SEQUENCE NUMBERS
1646
- // [0, 1, 2, 3, ..., 100, ..., 1000, ..., (MAX - MaxLocalSeq), L1, L2, L3, L4, ..., L100, ..., L1000, ...(MAX)]
1647
- const normalizedObSeq =
1648
- ob.seq === UnassignedSequenceNumber
1649
- ? Number.MAX_SAFE_INTEGER - this.collabWindow.localSeq + ob.localSeq!
1650
- : ob.seq;
1651
- if (normalizedObSeq > refSeq) {
1652
- if (oldest === undefined || normalizedOldestSeq > normalizedObSeq) {
1653
- normalizedOldestSeq = normalizedObSeq;
1654
- oldest = ob;
1655
- movedClientIds.unshift(ob.clientId);
1656
- movedSeqs.unshift(ob.seq);
1657
- } else {
1658
- movedClientIds.push(ob.clientId);
1659
- movedSeqs.push(ob.seq);
1660
- }
1661
- if (newest === undefined || normalizedNewestSeq < normalizedObSeq) {
1662
- normalizedNewestSeq = normalizedObSeq;
1663
- newest = ob;
1664
- }
1606
+ let oldest: ObliterateInfo | undefined;
1607
+ let normalizedOldestSeq: number = 0;
1608
+ let newest: ObliterateInfo | undefined;
1609
+ let normalizedNewestSeq: number = 0;
1610
+ const movedClientIds: number[] = [];
1611
+ const movedSeqs: number[] = [];
1612
+ for (const ob of this.obliterates.findOverlapping(newSegment)) {
1613
+ // compute a normalized seq that takes into account local seqs
1614
+ // but is still comparable to remote seqs to keep the checks below easy
1615
+ // REMOTE SEQUENCE NUMBERS LOCAL SEQUENCE NUMBERS
1616
+ // [0, 1, 2, 3, ..., 100, ..., 1000, ..., (MAX - MaxLocalSeq), L1, L2, L3, L4, ..., L100, ..., L1000, ...(MAX)]
1617
+ const normalizedObSeq =
1618
+ ob.seq === UnassignedSequenceNumber
1619
+ ? Number.MAX_SAFE_INTEGER - this.collabWindow.localSeq + ob.localSeq!
1620
+ : ob.seq;
1621
+ if (normalizedObSeq > refSeq) {
1622
+ if (oldest === undefined || normalizedOldestSeq > normalizedObSeq) {
1623
+ normalizedOldestSeq = normalizedObSeq;
1624
+ oldest = ob;
1625
+ movedClientIds.unshift(ob.clientId);
1626
+ movedSeqs.unshift(ob.seq);
1627
+ } else {
1628
+ movedClientIds.push(ob.clientId);
1629
+ movedSeqs.push(ob.seq);
1630
+ }
1631
+ if (newest === undefined || normalizedNewestSeq < normalizedObSeq) {
1632
+ normalizedNewestSeq = normalizedObSeq;
1633
+ newest = ob;
1665
1634
  }
1666
1635
  }
1636
+ }
1667
1637
 
1668
- if (oldest && newest?.clientId !== clientId) {
1669
- // eslint-disable-next-line import/no-deprecated
1670
- const moveInfo: IMoveInfo = {
1671
- movedClientIds,
1672
- movedSeq: oldest.seq,
1673
- movedSeqs,
1674
- localMovedSeq: oldest.localSeq,
1675
- wasMovedOnInsert: oldest.seq !== UnassignedSequenceNumber,
1676
- };
1638
+ if (oldest && newest?.clientId !== clientId) {
1639
+ const moveInfo: IMoveInfo = {
1640
+ movedClientIds,
1641
+ movedSeq: oldest.seq,
1642
+ movedSeqs,
1643
+ localMovedSeq: oldest.localSeq,
1644
+ wasMovedOnInsert: oldest.seq !== UnassignedSequenceNumber,
1645
+ };
1677
1646
 
1678
- markSegmentMoved(newSegment, moveInfo);
1647
+ overwriteInfo(newSegment, moveInfo);
1679
1648
 
1680
- if (moveInfo.localMovedSeq !== undefined) {
1681
- assert(
1682
- oldest.segmentGroup !== undefined,
1683
- 0x86c /* expected segment group to exist */,
1684
- );
1685
-
1686
- this.addToPendingList(newSegment, oldest.segmentGroup);
1687
- }
1649
+ if (moveInfo.localMovedSeq !== undefined) {
1650
+ assert(
1651
+ oldest.segmentGroup !== undefined,
1652
+ 0x86c /* expected segment group to exist */,
1653
+ );
1688
1654
 
1689
- if (newSegment.parent) {
1690
- this.blockUpdatePathLengths(newSegment.parent, seq, clientId);
1691
- }
1692
- } else if (oldest && newest?.clientId === clientId) {
1693
- newSegment.prevObliterateByInserter = newest;
1655
+ this.addToPendingList(newSegment, oldest.segmentGroup);
1694
1656
  }
1695
1657
 
1696
- saveIfLocal(newSegment);
1658
+ if (newSegment.parent) {
1659
+ this.blockUpdatePathLengths(newSegment.parent, seq, clientId);
1660
+ }
1661
+ } else if (oldest && newest?.clientId === clientId) {
1662
+ newSegment.prevObliterateByInserter = newest;
1697
1663
  }
1664
+
1665
+ saveIfLocal(newSegment);
1698
1666
  }
1699
1667
  }
1700
1668
 
@@ -1706,7 +1674,8 @@ export class MergeTree {
1706
1674
  return {};
1707
1675
  }
1708
1676
 
1709
- const next: ISegmentLeaf = segment.splitAt(pos)!;
1677
+ const next = segment.splitAt(pos)!;
1678
+ assertSegmentLeaf(next);
1710
1679
 
1711
1680
  if (segment?.segmentGroups) {
1712
1681
  next.segmentGroups ??= new SegmentGroupCollection(next);
@@ -1762,10 +1731,8 @@ export class MergeTree {
1762
1731
 
1763
1732
  return (
1764
1733
  newSeq > segSeq ||
1765
- (node.movedSeq !== undefined &&
1766
- node.movedSeq !== UnassignedSequenceNumber &&
1767
- node.movedSeq > seq) ||
1768
- (node.removedSeq !== undefined &&
1734
+ (isMoved(node) && node.movedSeq !== UnassignedSequenceNumber && node.movedSeq > seq) ||
1735
+ (isRemoved(node) &&
1769
1736
  node.removedSeq !== UnassignedSequenceNumber &&
1770
1737
  node.removedSeq > seq)
1771
1738
  );
@@ -1788,7 +1755,7 @@ export class MergeTree {
1788
1755
  const children = block.children;
1789
1756
  let childIndex: number;
1790
1757
  let child: IMergeNode;
1791
- let newNode: IMergeNode | undefined;
1758
+ let newNode: IMergeNodeBuilder | undefined;
1792
1759
  let fromSplit: MergeBlock | undefined;
1793
1760
  for (childIndex = 0; childIndex < block.childCount; childIndex++) {
1794
1761
  child = children[childIndex];
@@ -1812,7 +1779,7 @@ export class MergeTree {
1812
1779
  const segment = child;
1813
1780
  const segmentChanges = context.leaf(segment, _pos, context);
1814
1781
  if (segmentChanges.replaceCurrent) {
1815
- block.assignChild(segmentChanges.replaceCurrent, childIndex, false);
1782
+ assignChild(block, segmentChanges.replaceCurrent, childIndex, false);
1816
1783
  segmentChanges.replaceCurrent.ordinal = child.ordinal;
1817
1784
  }
1818
1785
  if (segmentChanges.next) {
@@ -1865,7 +1832,7 @@ export class MergeTree {
1865
1832
  block.children[i] = block.children[i - 1];
1866
1833
  block.children[i].index = i;
1867
1834
  }
1868
- block.assignChild(newNode, childIndex, false);
1835
+ assignChild(block, newNode, childIndex, false);
1869
1836
  block.childCount++;
1870
1837
  block.setOrdinal(newNode, childIndex);
1871
1838
  if (block.childCount < MaxNodesInBlock) {
@@ -1900,7 +1867,7 @@ export class MergeTree {
1900
1867
  // Update ordinals to reflect lowered child count
1901
1868
  this.nodeUpdateOrdinals(node);
1902
1869
  for (let i = 0; i < halfCount; i++) {
1903
- newNode.assignChild(node.children[halfCount + i], i, false);
1870
+ assignChild(newNode, node.children[halfCount + i], i, false);
1904
1871
  node.children[halfCount + i] = undefined!;
1905
1872
  }
1906
1873
  this.nodeUpdateLengthNewStructure(node);
@@ -1937,7 +1904,7 @@ export class MergeTree {
1937
1904
  clientId: number,
1938
1905
  seq: number,
1939
1906
  opArgs: IMergeTreeDeltaOpArgs,
1940
- // eslint-disable-next-line import/no-deprecated
1907
+
1941
1908
  rollback: PropertiesRollback = PropertiesRollback.None,
1942
1909
  ): void {
1943
1910
  if (propsOrAdjust.adjust !== undefined) {
@@ -1949,7 +1916,7 @@ export class MergeTree {
1949
1916
  const deltaSegments: IMergeTreeSegmentDelta[] = [];
1950
1917
  const localSeq =
1951
1918
  seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
1952
- // eslint-disable-next-line import/no-deprecated
1919
+
1953
1920
  let segmentGroup: SegmentGroup | undefined;
1954
1921
  const opObj = propsOrAdjust.props ?? propsOrAdjust.adjust;
1955
1922
  const annotateSegment = (segment: ISegmentLeaf): boolean => {
@@ -1990,7 +1957,7 @@ export class MergeTree {
1990
1957
  return true;
1991
1958
  };
1992
1959
 
1993
- this.nodeMap(refSeq, clientId, annotateSegment, undefined, undefined, start, end);
1960
+ this.nodeMap(refSeq, clientId, annotateSegment, undefined, start, end);
1994
1961
 
1995
1962
  // OpArgs == undefined => test code
1996
1963
  if (deltaSegments.length > 0) {
@@ -2024,10 +1991,10 @@ export class MergeTree {
2024
1991
 
2025
1992
  let _overwrite = false;
2026
1993
  const localOverlapWithRefs: ISegmentLeaf[] = [];
2027
- const movedSegments: IMergeTreeSegmentDelta[] = [];
1994
+ const movedSegments: SegmentWithInfo<IMoveInfo, ISegmentLeaf>[] = [];
2028
1995
  const localSeq =
2029
1996
  seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
2030
- // eslint-disable-next-line import/no-deprecated
1997
+
2031
1998
  const obliterate: ObliterateInfo = {
2032
1999
  clientId,
2033
2000
  end: createDetachedLocalReferencePosition(undefined),
@@ -2041,7 +2008,7 @@ export class MergeTree {
2041
2008
  const { segment: startSeg } = this.getContainingSegment(start.pos, refSeq, clientId);
2042
2009
  const { segment: endSeg } = this.getContainingSegment(end.pos, refSeq, clientId);
2043
2010
  assert(
2044
- startSeg !== undefined && endSeg !== undefined,
2011
+ isSegmentLeaf(startSeg) && isSegmentLeaf(endSeg),
2045
2012
  0xa3f /* segments cannot be undefined */,
2046
2013
  );
2047
2014
 
@@ -2078,12 +2045,7 @@ export class MergeTree {
2078
2045
  }
2079
2046
  this.obliterates.addOrUpdate(obliterate);
2080
2047
 
2081
- const markMoved = (
2082
- segment: ISegmentLeaf,
2083
- pos: number,
2084
- _start: number,
2085
- _end: number,
2086
- ): boolean => {
2048
+ const markMoved = (segment: ISegmentLeaf, pos: number): boolean => {
2087
2049
  if (
2088
2050
  (start.side === Side.After && startPos === pos + segment.cachedLength) || // exclusive start segment
2089
2051
  (end.side === Side.Before &&
@@ -2103,26 +2065,28 @@ export class MergeTree {
2103
2065
  return true;
2104
2066
  }
2105
2067
 
2106
- if (
2068
+ const wasMovedOnInsert =
2107
2069
  clientId !== segment.clientId &&
2108
2070
  segment.seq !== undefined &&
2109
2071
  seq !== UnassignedSequenceNumber &&
2110
- (refSeq < segment.seq || segment.seq === UnassignedSequenceNumber)
2111
- ) {
2112
- segment.wasMovedOnInsert = true;
2113
- }
2072
+ (refSeq < segment.seq || segment.seq === UnassignedSequenceNumber);
2114
2073
 
2115
2074
  if (existingMoveInfo === undefined) {
2116
- segment.movedClientIds = [clientId];
2117
- segment.movedSeq = seq;
2118
- segment.localMovedSeq = localSeq;
2119
- segment.movedSeqs = [seq];
2075
+ const movedSeg = overwriteInfo<IMoveInfo, ISegmentLeaf>(segment, {
2076
+ movedClientIds: [clientId],
2077
+ movedSeq: seq,
2078
+ localMovedSeq: localSeq,
2079
+ movedSeqs: [seq],
2080
+ wasMovedOnInsert,
2081
+ });
2120
2082
 
2121
- if (!toRemovalInfo(segment)) {
2122
- movedSegments.push({ segment });
2083
+ if (!toRemovalInfo(movedSeg)) {
2084
+ movedSegments.push(movedSeg);
2123
2085
  }
2124
2086
  } else {
2125
2087
  _overwrite = true;
2088
+ // never move wasMovedOnInsert from true to false
2089
+ existingMoveInfo.wasMovedOnInsert ||= wasMovedOnInsert;
2126
2090
  if (existingMoveInfo.movedSeq === UnassignedSequenceNumber) {
2127
2091
  // we moved this locally, but someone else moved it first
2128
2092
  // so put them at the head of the list
@@ -2141,7 +2105,7 @@ export class MergeTree {
2141
2105
  existingMoveInfo.movedSeqs.push(seq);
2142
2106
  }
2143
2107
  }
2144
-
2108
+ assertMoved(segment);
2145
2109
  // Save segment so can assign moved sequence number when acked by server
2146
2110
  if (this.collabWindow.collaborating) {
2147
2111
  if (
@@ -2162,12 +2126,7 @@ export class MergeTree {
2162
2126
  return true;
2163
2127
  };
2164
2128
 
2165
- const afterMarkMoved = (
2166
- node: MergeBlock,
2167
- pos: number,
2168
- _start: number,
2169
- _end: number,
2170
- ): boolean => {
2129
+ const afterMarkMoved = (node: MergeBlock): boolean => {
2171
2130
  if (_overwrite) {
2172
2131
  this.nodeUpdateLengthNewStructure(node);
2173
2132
  } else {
@@ -2180,7 +2139,6 @@ export class MergeTree {
2180
2139
  refSeq,
2181
2140
  clientId,
2182
2141
  markMoved,
2183
- undefined,
2184
2142
  afterMarkMoved,
2185
2143
  start.pos,
2186
2144
  end.pos + 1, // include the segment containing the end reference
@@ -2193,7 +2151,7 @@ export class MergeTree {
2193
2151
  if (start.pos !== end.pos || start.side !== end.side) {
2194
2152
  this.mergeTreeDeltaCallback?.(opArgs, {
2195
2153
  operation: MergeTreeDeltaType.OBLITERATE,
2196
- deltaSegments: movedSegments,
2154
+ deltaSegments: movedSegments.map((segment) => ({ segment })),
2197
2155
  });
2198
2156
  }
2199
2157
 
@@ -2201,7 +2159,7 @@ export class MergeTree {
2201
2159
  // so we slide after eventing in case the consumer wants to make reference
2202
2160
  // changes at remove time, like add a ref to track undo redo.
2203
2161
  if (!this.collabWindow.collaborating || clientId !== this.collabWindow.clientId) {
2204
- this.slideAckedRemovedSegmentReferences(movedSegments.map(({ segment }) => segment));
2162
+ this.slideAckedRemovedSegmentReferences(movedSegments);
2205
2163
  }
2206
2164
 
2207
2165
  if (
@@ -2255,9 +2213,9 @@ export class MergeTree {
2255
2213
  let _overwrite = false;
2256
2214
  this.ensureIntervalBoundary(start, refSeq, clientId);
2257
2215
  this.ensureIntervalBoundary(end, refSeq, clientId);
2258
- // eslint-disable-next-line import/no-deprecated
2216
+
2259
2217
  let segmentGroup: SegmentGroup;
2260
- const removedSegments: IMergeTreeSegmentDelta[] = [];
2218
+ const removedSegments: SegmentWithInfo<IRemovalInfo, ISegmentLeaf>[] = [];
2261
2219
  const localOverlapWithRefs: ISegmentLeaf[] = [];
2262
2220
  const localSeq =
2263
2221
  seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
@@ -2270,12 +2228,14 @@ export class MergeTree {
2270
2228
  const existingRemovalInfo = toRemovalInfo(segment);
2271
2229
 
2272
2230
  if (existingRemovalInfo === undefined) {
2273
- segment.removedClientIds = [clientId];
2274
- segment.removedSeq = seq;
2275
- segment.localRemovedSeq = localSeq;
2231
+ const removed = overwriteInfo<IRemovalInfo, ISegmentLeaf>(segment, {
2232
+ removedClientIds: [clientId],
2233
+ removedSeq: seq,
2234
+ localRemovedSeq: localSeq,
2235
+ });
2276
2236
 
2277
- if (!toMoveInfo(segment)) {
2278
- removedSegments.push({ segment });
2237
+ if (!toMoveInfo(removed)) {
2238
+ removedSegments.push(removed);
2279
2239
  }
2280
2240
  } else {
2281
2241
  _overwrite = true;
@@ -2295,7 +2255,7 @@ export class MergeTree {
2295
2255
  existingRemovalInfo.removedClientIds.push(clientId);
2296
2256
  }
2297
2257
  }
2298
-
2258
+ assertRemoved(segment);
2299
2259
  // Save segment so we can assign removed sequence number when acked by server
2300
2260
  if (this.collabWindow.collaborating) {
2301
2261
  if (
@@ -2311,12 +2271,7 @@ export class MergeTree {
2311
2271
  }
2312
2272
  return true;
2313
2273
  };
2314
- const afterMarkRemoved = (
2315
- node: MergeBlock,
2316
- pos: number,
2317
- _start: number,
2318
- _end: number,
2319
- ): boolean => {
2274
+ const afterMarkRemoved = (node: MergeBlock): boolean => {
2320
2275
  if (_overwrite) {
2321
2276
  this.nodeUpdateLengthNewStructure(node);
2322
2277
  } else {
@@ -2324,7 +2279,7 @@ export class MergeTree {
2324
2279
  }
2325
2280
  return true;
2326
2281
  };
2327
- this.nodeMap(refSeq, clientId, markRemoved, undefined, afterMarkRemoved, start, end);
2282
+ this.nodeMap(refSeq, clientId, markRemoved, afterMarkRemoved, start, end);
2328
2283
  // these segments are already viewed as being removed locally and are not event-ed
2329
2284
  // so can slide non-StayOnRemove refs immediately
2330
2285
  this.slideAckedRemovedSegmentReferences(localOverlapWithRefs);
@@ -2332,14 +2287,14 @@ export class MergeTree {
2332
2287
  if (removedSegments.length > 0) {
2333
2288
  this.mergeTreeDeltaCallback?.(opArgs, {
2334
2289
  operation: MergeTreeDeltaType.REMOVE,
2335
- deltaSegments: removedSegments,
2290
+ deltaSegments: removedSegments.map((segment) => ({ segment })),
2336
2291
  });
2337
2292
  }
2338
2293
  // these events are newly removed
2339
2294
  // so we slide after eventing in case the consumer wants to make reference
2340
2295
  // changes at remove time, like add a ref to track undo redo.
2341
2296
  if (!this.collabWindow.collaborating || clientId !== this.collabWindow.clientId) {
2342
- this.slideAckedRemovedSegmentReferences(removedSegments.map(({ segment }) => segment));
2297
+ this.slideAckedRemovedSegmentReferences(removedSegments);
2343
2298
  }
2344
2299
 
2345
2300
  if (
@@ -2354,36 +2309,30 @@ export class MergeTree {
2354
2309
  /**
2355
2310
  * Revert an unacked local op
2356
2311
  */
2357
- // eslint-disable-next-line import/no-deprecated
2312
+
2358
2313
  public rollback(op: IMergeTreeDeltaOp, localOpMetadata: SegmentGroup): void {
2359
2314
  if (op.type === MergeTreeDeltaType.REMOVE) {
2360
- const pendingSegmentGroup = this.pendingSegments.pop?.()?.data;
2315
+ const pendingSegmentGroup = this.pendingSegments.pop()?.data;
2361
2316
  if (pendingSegmentGroup === undefined || pendingSegmentGroup !== localOpMetadata) {
2362
2317
  throw new Error("Rollback op doesn't match last edit");
2363
2318
  }
2364
2319
  // Disabling because a for of loop causes the type of segment to be ISegmentLeaf, which does not have parent information stored
2365
2320
  // eslint-disable-next-line unicorn/no-array-for-each
2366
2321
  pendingSegmentGroup.segments.forEach((segment: ISegmentLeaf) => {
2367
- const segmentSegmentGroup = segment?.segmentGroups?.pop?.();
2322
+ const segmentSegmentGroup = segment?.segmentGroups?.pop();
2368
2323
  assert(
2369
2324
  segmentSegmentGroup === pendingSegmentGroup,
2370
2325
  0x3ee /* Unexpected segmentGroup in segment */,
2371
2326
  );
2372
2327
 
2373
2328
  assert(
2374
- segment.removedClientIds !== undefined &&
2375
- segment.removedClientIds[0] === this.collabWindow.clientId,
2329
+ isRemoved(segment) && segment.removedClientIds[0] === this.collabWindow.clientId,
2376
2330
  0x39d /* Rollback segment removedClientId does not match local client */,
2377
2331
  );
2378
- segment.removedClientIds = undefined;
2379
- segment.removedSeq = undefined;
2380
- segment.localRemovedSeq = undefined;
2332
+ let updateNode: MergeBlock | undefined = segment.parent;
2333
+ removeRemovalInfo(segment);
2381
2334
 
2382
- for (
2383
- let updateNode = segment.parent;
2384
- updateNode !== undefined;
2385
- updateNode = updateNode.parent
2386
- ) {
2335
+ for (updateNode; updateNode !== undefined; updateNode = updateNode.parent) {
2387
2336
  this.blockUpdateLength(
2388
2337
  updateNode,
2389
2338
  UnassignedSequenceNumber,
@@ -2405,7 +2354,7 @@ export class MergeTree {
2405
2354
  op.type === MergeTreeDeltaType.INSERT ||
2406
2355
  op.type === MergeTreeDeltaType.ANNOTATE
2407
2356
  ) {
2408
- const pendingSegmentGroup = this.pendingSegments.pop?.()?.data;
2357
+ const pendingSegmentGroup = this.pendingSegments.pop()?.data;
2409
2358
  if (
2410
2359
  pendingSegmentGroup === undefined ||
2411
2360
  pendingSegmentGroup !== localOpMetadata ||
@@ -2414,8 +2363,8 @@ export class MergeTree {
2414
2363
  throw new Error("Rollback op doesn't match last edit");
2415
2364
  }
2416
2365
  let i = 0;
2417
- for (const segment of pendingSegmentGroup.segments as ISegmentLeaf[]) {
2418
- const segmentSegmentGroup = segment?.segmentGroups?.pop?.();
2366
+ for (const segment of pendingSegmentGroup.segments) {
2367
+ const segmentSegmentGroup = segment?.segmentGroups?.pop();
2419
2368
  assert(
2420
2369
  segmentSegmentGroup === pendingSegmentGroup,
2421
2370
  0x3ef /* Unexpected segmentGroup in segment */,
@@ -2467,7 +2416,7 @@ export class MergeTree {
2467
2416
  }
2468
2417
 
2469
2418
  // If not removed, increase position
2470
- if (seg.removedSeq === undefined) {
2419
+ if (!isRemoved(seg)) {
2471
2420
  segmentPosition += seg.cachedLength;
2472
2421
  }
2473
2422
 
@@ -2488,7 +2437,7 @@ export class MergeTree {
2488
2437
  public removeLocalReferencePosition(
2489
2438
  lref: LocalReferencePosition,
2490
2439
  ): LocalReferencePosition | undefined {
2491
- const segment: ISegmentLeaf | undefined = lref.getSegment();
2440
+ const segment: ISegmentPrivate | undefined = lref.getSegment();
2492
2441
  return segment?.localRefs?.removeLocalRef(lref);
2493
2442
  }
2494
2443
 
@@ -2496,7 +2445,7 @@ export class MergeTree {
2496
2445
  endOfTree = new EndOfTreeSegment(this);
2497
2446
 
2498
2447
  public createLocalReferencePosition(
2499
- _segment: ISegmentLeaf | "start" | "end",
2448
+ _segment: ISegmentPrivate | "start" | "end",
2500
2449
  offset: number,
2501
2450
  refType: ReferenceType,
2502
2451
  properties: PropertySet | undefined,
@@ -2517,7 +2466,6 @@ export class MergeTree {
2517
2466
  "Can only create SlideOnRemove or Transient local reference position on a removed or obliterated segment",
2518
2467
  );
2519
2468
  }
2520
-
2521
2469
  let segment: ISegmentLeaf;
2522
2470
 
2523
2471
  if (_segment === "start") {
@@ -2525,10 +2473,10 @@ export class MergeTree {
2525
2473
  } else if (_segment === "end") {
2526
2474
  segment = this.endOfTree;
2527
2475
  } else {
2476
+ assertSegmentLeaf(_segment);
2528
2477
  segment = _segment;
2529
2478
  }
2530
2479
 
2531
- // eslint-disable-next-line import/no-deprecated
2532
2480
  const localRefs = LocalReferenceCollection.setOrGet(segment);
2533
2481
 
2534
2482
  const segRef = localRefs.createLocalRef(
@@ -2613,7 +2561,7 @@ export class MergeTree {
2613
2561
  for (let i = 0; i < newOrder.length; i++) {
2614
2562
  const seg = newOrder[i];
2615
2563
  const { parent, index, ordinal } = currentOrder[i];
2616
- parent?.assignChild(seg, index, false);
2564
+ assignChild(parent, seg, index, false);
2617
2565
  seg.ordinal = ordinal;
2618
2566
  }
2619
2567
 
@@ -2811,8 +2759,7 @@ export class MergeTree {
2811
2759
  this.nodeMap(
2812
2760
  refSeq,
2813
2761
  clientId,
2814
- handler,
2815
- accum,
2762
+ (seg, pos, _start, _end) => handler(seg, pos, refSeq, clientId, _start, _end, accum),
2816
2763
  undefined,
2817
2764
  start,
2818
2765
  end,
@@ -2844,12 +2791,11 @@ export class MergeTree {
2844
2791
  * but it will not count as a segment within the range. That is, it will be
2845
2792
  * ignored for the purposes of tracking when traversal should end.
2846
2793
  */
2847
- private nodeMap<TClientData>(
2794
+ private nodeMap(
2848
2795
  refSeq: number,
2849
2796
  clientId: number,
2850
- leaf: ISegmentAction<TClientData>,
2851
- accum: TClientData,
2852
- post?: BlockAction<TClientData>,
2797
+ leaf: (segment: ISegmentLeaf, pos: number, start: number, end: number) => boolean,
2798
+ post?: (block: MergeBlock) => boolean,
2853
2799
  start: number = 0,
2854
2800
  end?: number,
2855
2801
  localSeq?: number,
@@ -2895,17 +2841,14 @@ export class MergeTree {
2895
2841
  }
2896
2842
 
2897
2843
  if (node.isLeaf()) {
2898
- if (leaf(node, pos, refSeq, clientId, start - pos, endPos - pos, accum) === false) {
2844
+ if (leaf(node, pos, start - pos, endPos - pos) === false) {
2899
2845
  return NodeAction.Exit;
2900
2846
  }
2901
2847
  pos = nextPos;
2902
2848
  }
2903
2849
  },
2904
2850
  undefined,
2905
- post === undefined
2906
- ? undefined
2907
- : (block): boolean =>
2908
- post(block, pos, refSeq, clientId, start - pos, endPos - pos, accum),
2851
+ post,
2909
2852
  );
2910
2853
  }
2911
2854
  }