@fluidframework/merge-tree 2.12.0 → 2.13.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 (285) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/MergeTreeTextHelper.d.ts.map +1 -1
  3. package/dist/MergeTreeTextHelper.js +0 -2
  4. package/dist/MergeTreeTextHelper.js.map +1 -1
  5. package/dist/attributionPolicy.d.ts.map +1 -1
  6. package/dist/attributionPolicy.js +6 -16
  7. package/dist/attributionPolicy.js.map +1 -1
  8. package/dist/client.d.ts +3 -4
  9. package/dist/client.d.ts.map +1 -1
  10. package/dist/client.js +39 -28
  11. package/dist/client.js.map +1 -1
  12. package/dist/endOfTreeSegment.d.ts +2 -1
  13. package/dist/endOfTreeSegment.d.ts.map +1 -1
  14. package/dist/endOfTreeSegment.js.map +1 -1
  15. package/dist/index.d.ts +2 -1
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +2 -4
  18. package/dist/index.js.map +1 -1
  19. package/dist/mergeTree.d.ts +8 -7
  20. package/dist/mergeTree.d.ts.map +1 -1
  21. package/dist/mergeTree.js +190 -216
  22. package/dist/mergeTree.js.map +1 -1
  23. package/dist/mergeTreeNodeWalk.d.ts.map +1 -1
  24. package/dist/mergeTreeNodeWalk.js +3 -2
  25. package/dist/mergeTreeNodeWalk.js.map +1 -1
  26. package/dist/mergeTreeNodes.d.ts +76 -162
  27. package/dist/mergeTreeNodes.d.ts.map +1 -1
  28. package/dist/mergeTreeNodes.js +100 -112
  29. package/dist/mergeTreeNodes.js.map +1 -1
  30. package/dist/mergeTreeTracking.d.ts.map +1 -1
  31. package/dist/mergeTreeTracking.js +0 -2
  32. package/dist/mergeTreeTracking.js.map +1 -1
  33. package/dist/partialLengths.d.ts +2 -2
  34. package/dist/partialLengths.d.ts.map +1 -1
  35. package/dist/partialLengths.js +28 -26
  36. package/dist/partialLengths.js.map +1 -1
  37. package/dist/perspective.d.ts +3 -2
  38. package/dist/perspective.d.ts.map +1 -1
  39. package/dist/perspective.js +11 -4
  40. package/dist/perspective.js.map +1 -1
  41. package/dist/referencePositions.d.ts.map +1 -1
  42. package/dist/referencePositions.js +4 -1
  43. package/dist/referencePositions.js.map +1 -1
  44. package/dist/revertibles.d.ts.map +1 -1
  45. package/dist/revertibles.js +10 -11
  46. package/dist/revertibles.js.map +1 -1
  47. package/dist/segmentGroupCollection.d.ts +4 -4
  48. package/dist/segmentGroupCollection.d.ts.map +1 -1
  49. package/dist/segmentGroupCollection.js +0 -6
  50. package/dist/segmentGroupCollection.js.map +1 -1
  51. package/dist/segmentInfos.d.ts +257 -0
  52. package/dist/segmentInfos.d.ts.map +1 -0
  53. package/dist/segmentInfos.js +166 -0
  54. package/dist/segmentInfos.js.map +1 -0
  55. package/dist/snapshotLoader.d.ts.map +1 -1
  56. package/dist/snapshotLoader.js +38 -44
  57. package/dist/snapshotLoader.js.map +1 -1
  58. package/dist/snapshotV1.d.ts.map +1 -1
  59. package/dist/snapshotV1.js +9 -12
  60. package/dist/snapshotV1.js.map +1 -1
  61. package/dist/snapshotlegacy.d.ts +2 -2
  62. package/dist/snapshotlegacy.d.ts.map +1 -1
  63. package/dist/snapshotlegacy.js +5 -3
  64. package/dist/snapshotlegacy.js.map +1 -1
  65. package/dist/sortedSegmentSet.d.ts.map +1 -1
  66. package/dist/sortedSegmentSet.js +5 -8
  67. package/dist/sortedSegmentSet.js.map +1 -1
  68. package/dist/test/beastTest.spec.d.ts +0 -2
  69. package/dist/test/beastTest.spec.d.ts.map +1 -1
  70. package/dist/test/beastTest.spec.js +1 -5
  71. package/dist/test/beastTest.spec.js.map +1 -1
  72. package/dist/test/client.annotateMarker.spec.js.map +1 -1
  73. package/dist/test/client.applyMsg.spec.js +15 -12
  74. package/dist/test/client.applyMsg.spec.js.map +1 -1
  75. package/dist/test/client.attributionFarm.spec.js.map +1 -1
  76. package/dist/test/client.getPosition.spec.js +3 -2
  77. package/dist/test/client.getPosition.spec.js.map +1 -1
  78. package/dist/test/client.localReference.spec.js +6 -6
  79. package/dist/test/client.localReference.spec.js.map +1 -1
  80. package/dist/test/client.localReferenceFarm.spec.js.map +1 -1
  81. package/dist/test/client.rollback.spec.js.map +1 -1
  82. package/dist/test/dirname.cjs +0 -1
  83. package/dist/test/dirname.cjs.map +1 -1
  84. package/dist/test/index.d.ts +1 -1
  85. package/dist/test/index.d.ts.map +1 -1
  86. package/dist/test/index.js +2 -4
  87. package/dist/test/index.js.map +1 -1
  88. package/dist/test/mergeTree.annotate.spec.js +3 -0
  89. package/dist/test/mergeTree.annotate.spec.js.map +1 -1
  90. package/dist/test/mergeTree.insertingWalk.spec.js +1 -1
  91. package/dist/test/mergeTree.insertingWalk.spec.js.map +1 -1
  92. package/dist/test/mergeTree.markRangeRemoved.spec.js +2 -0
  93. package/dist/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
  94. package/dist/test/mergeTree.walk.spec.js.map +1 -1
  95. package/dist/test/mergeTreeOperationRunner.d.ts.map +1 -1
  96. package/dist/test/mergeTreeOperationRunner.js +2 -3
  97. package/dist/test/mergeTreeOperationRunner.js.map +1 -1
  98. package/dist/test/obliterate.spec.js.map +1 -1
  99. package/dist/test/propertyManager.spec.js.map +1 -1
  100. package/dist/test/reconnectHelper.d.ts +2 -1
  101. package/dist/test/reconnectHelper.d.ts.map +1 -1
  102. package/dist/test/reconnectHelper.js.map +1 -1
  103. package/dist/test/resetPendingSegmentsToOp.spec.js.map +1 -1
  104. package/dist/test/revertibleFarm.spec.js.map +1 -1
  105. package/dist/test/segmentGroupCollection.spec.js +15 -3
  106. package/dist/test/segmentGroupCollection.spec.js.map +1 -1
  107. package/dist/test/snapshot.utils.d.ts +2 -2
  108. package/dist/test/snapshot.utils.d.ts.map +1 -1
  109. package/dist/test/snapshot.utils.js.map +1 -1
  110. package/dist/test/sortedSegmentSet.spec.js +4 -3
  111. package/dist/test/sortedSegmentSet.spec.js.map +1 -1
  112. package/dist/test/testClient.d.ts +8 -6
  113. package/dist/test/testClient.d.ts.map +1 -1
  114. package/dist/test/testClient.js +29 -27
  115. package/dist/test/testClient.js.map +1 -1
  116. package/dist/test/testClientLogger.d.ts.map +1 -1
  117. package/dist/test/testClientLogger.js +6 -4
  118. package/dist/test/testClientLogger.js.map +1 -1
  119. package/dist/test/testUtils.d.ts +2 -2
  120. package/dist/test/testUtils.d.ts.map +1 -1
  121. package/dist/test/testUtils.js +32 -8
  122. package/dist/test/testUtils.js.map +1 -1
  123. package/dist/test/text.d.ts +2 -2
  124. package/dist/test/text.d.ts.map +1 -1
  125. package/dist/test/text.js +12 -6
  126. package/dist/test/text.js.map +1 -1
  127. package/dist/test/tracking.spec.js.map +1 -1
  128. package/dist/test/wordUnitTests.spec.js +1 -1
  129. package/dist/test/wordUnitTests.spec.js.map +1 -1
  130. package/dist/zamboni.d.ts.map +1 -1
  131. package/dist/zamboni.js +8 -7
  132. package/dist/zamboni.js.map +1 -1
  133. package/lib/MergeTreeTextHelper.d.ts.map +1 -1
  134. package/lib/MergeTreeTextHelper.js +0 -2
  135. package/lib/MergeTreeTextHelper.js.map +1 -1
  136. package/lib/attributionPolicy.d.ts.map +1 -1
  137. package/lib/attributionPolicy.js +6 -16
  138. package/lib/attributionPolicy.js.map +1 -1
  139. package/lib/client.d.ts +3 -4
  140. package/lib/client.d.ts.map +1 -1
  141. package/lib/client.js +40 -29
  142. package/lib/client.js.map +1 -1
  143. package/lib/endOfTreeSegment.d.ts +2 -1
  144. package/lib/endOfTreeSegment.d.ts.map +1 -1
  145. package/lib/endOfTreeSegment.js.map +1 -1
  146. package/lib/index.d.ts +2 -1
  147. package/lib/index.d.ts.map +1 -1
  148. package/lib/index.js +1 -1
  149. package/lib/index.js.map +1 -1
  150. package/lib/mergeTree.d.ts +8 -7
  151. package/lib/mergeTree.d.ts.map +1 -1
  152. package/lib/mergeTree.js +177 -205
  153. package/lib/mergeTree.js.map +1 -1
  154. package/lib/mergeTreeNodeWalk.d.ts.map +1 -1
  155. package/lib/mergeTreeNodeWalk.js +3 -2
  156. package/lib/mergeTreeNodeWalk.js.map +1 -1
  157. package/lib/mergeTreeNodes.d.ts +76 -162
  158. package/lib/mergeTreeNodes.d.ts.map +1 -1
  159. package/lib/mergeTreeNodes.js +95 -108
  160. package/lib/mergeTreeNodes.js.map +1 -1
  161. package/lib/mergeTreeTracking.d.ts.map +1 -1
  162. package/lib/mergeTreeTracking.js +0 -2
  163. package/lib/mergeTreeTracking.js.map +1 -1
  164. package/lib/partialLengths.d.ts +2 -2
  165. package/lib/partialLengths.d.ts.map +1 -1
  166. package/lib/partialLengths.js +25 -23
  167. package/lib/partialLengths.js.map +1 -1
  168. package/lib/perspective.d.ts +3 -2
  169. package/lib/perspective.d.ts.map +1 -1
  170. package/lib/perspective.js +11 -4
  171. package/lib/perspective.js.map +1 -1
  172. package/lib/referencePositions.d.ts.map +1 -1
  173. package/lib/referencePositions.js +4 -1
  174. package/lib/referencePositions.js.map +1 -1
  175. package/lib/revertibles.d.ts.map +1 -1
  176. package/lib/revertibles.js +8 -9
  177. package/lib/revertibles.js.map +1 -1
  178. package/lib/segmentGroupCollection.d.ts +4 -4
  179. package/lib/segmentGroupCollection.d.ts.map +1 -1
  180. package/lib/segmentGroupCollection.js +0 -6
  181. package/lib/segmentGroupCollection.js.map +1 -1
  182. package/lib/segmentInfos.d.ts +257 -0
  183. package/lib/segmentInfos.d.ts.map +1 -0
  184. package/lib/segmentInfos.js +145 -0
  185. package/lib/segmentInfos.js.map +1 -0
  186. package/lib/snapshotLoader.d.ts.map +1 -1
  187. package/lib/snapshotLoader.js +38 -44
  188. package/lib/snapshotLoader.js.map +1 -1
  189. package/lib/snapshotV1.d.ts.map +1 -1
  190. package/lib/snapshotV1.js +9 -12
  191. package/lib/snapshotV1.js.map +1 -1
  192. package/lib/snapshotlegacy.d.ts +2 -2
  193. package/lib/snapshotlegacy.d.ts.map +1 -1
  194. package/lib/snapshotlegacy.js +5 -3
  195. package/lib/snapshotlegacy.js.map +1 -1
  196. package/lib/sortedSegmentSet.d.ts.map +1 -1
  197. package/lib/sortedSegmentSet.js +5 -8
  198. package/lib/sortedSegmentSet.js.map +1 -1
  199. package/lib/test/beastTest.spec.d.ts +0 -2
  200. package/lib/test/beastTest.spec.d.ts.map +1 -1
  201. package/lib/test/beastTest.spec.js +0 -3
  202. package/lib/test/beastTest.spec.js.map +1 -1
  203. package/lib/test/client.annotateMarker.spec.js.map +1 -1
  204. package/lib/test/client.applyMsg.spec.js +15 -12
  205. package/lib/test/client.applyMsg.spec.js.map +1 -1
  206. package/lib/test/client.attributionFarm.spec.js.map +1 -1
  207. package/lib/test/client.getPosition.spec.js +3 -2
  208. package/lib/test/client.getPosition.spec.js.map +1 -1
  209. package/lib/test/client.localReference.spec.js +1 -1
  210. package/lib/test/client.localReference.spec.js.map +1 -1
  211. package/lib/test/client.localReferenceFarm.spec.js.map +1 -1
  212. package/lib/test/client.rollback.spec.js +1 -1
  213. package/lib/test/client.rollback.spec.js.map +1 -1
  214. package/lib/test/dirname.cjs +0 -1
  215. package/lib/test/dirname.cjs.map +1 -1
  216. package/lib/test/index.d.ts +1 -1
  217. package/lib/test/index.d.ts.map +1 -1
  218. package/lib/test/index.js +1 -1
  219. package/lib/test/index.js.map +1 -1
  220. package/lib/test/mergeTree.annotate.spec.js +3 -0
  221. package/lib/test/mergeTree.annotate.spec.js.map +1 -1
  222. package/lib/test/mergeTree.insertingWalk.spec.js +2 -2
  223. package/lib/test/mergeTree.insertingWalk.spec.js.map +1 -1
  224. package/lib/test/mergeTree.markRangeRemoved.spec.js +2 -0
  225. package/lib/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
  226. package/lib/test/mergeTree.walk.spec.js.map +1 -1
  227. package/lib/test/mergeTreeOperationRunner.d.ts.map +1 -1
  228. package/lib/test/mergeTreeOperationRunner.js +1 -2
  229. package/lib/test/mergeTreeOperationRunner.js.map +1 -1
  230. package/lib/test/obliterate.spec.js.map +1 -1
  231. package/lib/test/propertyManager.spec.js.map +1 -1
  232. package/lib/test/reconnectHelper.d.ts +2 -1
  233. package/lib/test/reconnectHelper.d.ts.map +1 -1
  234. package/lib/test/reconnectHelper.js.map +1 -1
  235. package/lib/test/resetPendingSegmentsToOp.spec.js.map +1 -1
  236. package/lib/test/revertibleFarm.spec.js.map +1 -1
  237. package/lib/test/segmentGroupCollection.spec.js +15 -3
  238. package/lib/test/segmentGroupCollection.spec.js.map +1 -1
  239. package/lib/test/snapshot.utils.d.ts +2 -2
  240. package/lib/test/snapshot.utils.d.ts.map +1 -1
  241. package/lib/test/snapshot.utils.js.map +1 -1
  242. package/lib/test/sortedSegmentSet.spec.js +4 -3
  243. package/lib/test/sortedSegmentSet.spec.js.map +1 -1
  244. package/lib/test/testClient.d.ts +8 -6
  245. package/lib/test/testClient.d.ts.map +1 -1
  246. package/lib/test/testClient.js +30 -28
  247. package/lib/test/testClient.js.map +1 -1
  248. package/lib/test/testClientLogger.d.ts.map +1 -1
  249. package/lib/test/testClientLogger.js +5 -3
  250. package/lib/test/testClientLogger.js.map +1 -1
  251. package/lib/test/testUtils.d.ts +2 -2
  252. package/lib/test/testUtils.d.ts.map +1 -1
  253. package/lib/test/testUtils.js +9 -8
  254. package/lib/test/testUtils.js.map +1 -1
  255. package/lib/test/text.d.ts +2 -2
  256. package/lib/test/text.d.ts.map +1 -1
  257. package/lib/test/text.js +12 -6
  258. package/lib/test/text.js.map +1 -1
  259. package/lib/test/tracking.spec.js.map +1 -1
  260. package/lib/test/wordUnitTests.spec.js +1 -1
  261. package/lib/test/wordUnitTests.spec.js.map +1 -1
  262. package/lib/zamboni.d.ts.map +1 -1
  263. package/lib/zamboni.js +7 -6
  264. package/lib/zamboni.js.map +1 -1
  265. package/package.json +17 -17
  266. package/src/MergeTreeTextHelper.ts +2 -4
  267. package/src/attributionPolicy.ts +5 -13
  268. package/src/client.ts +55 -44
  269. package/src/endOfTreeSegment.ts +3 -3
  270. package/src/index.ts +4 -6
  271. package/src/mergeTree.ts +245 -282
  272. package/src/mergeTreeNodeWalk.ts +3 -2
  273. package/src/mergeTreeNodes.ts +190 -322
  274. package/src/mergeTreeTracking.ts +0 -3
  275. package/src/partialLengths.ts +42 -27
  276. package/src/perspective.ts +27 -4
  277. package/src/referencePositions.ts +4 -1
  278. package/src/revertibles.ts +19 -13
  279. package/src/segmentGroupCollection.ts +7 -18
  280. package/src/segmentInfos.ts +377 -0
  281. package/src/snapshotLoader.ts +60 -57
  282. package/src/snapshotV1.ts +14 -16
  283. package/src/snapshotlegacy.ts +12 -17
  284. package/src/sortedSegmentSet.ts +6 -8
  285. package/src/zamboni.ts +10 -12
package/lib/mergeTree.js CHANGED
@@ -14,40 +14,19 @@ import {
14
14
  LocalReferenceCollection, SlidingPreference, anyLocalReferencePosition, createDetachedLocalReferencePosition, filterLocalReferencePositions, } from "./localReference.js";
15
15
  import { MergeTreeMaintenanceType, } from "./mergeTreeDeltaCallback.js";
16
16
  import { NodeAction, backwardExcursion, depthFirstNodeWalk, forwardExcursion, walkAllChildSegments, } from "./mergeTreeNodeWalk.js";
17
- import {
18
- // eslint-disable-next-line import/no-deprecated
19
- CollaborationWindow, Marker, MaxNodesInBlock, MergeBlock, reservedMarkerIdKey, seqLTE, toMoveInfo, toRemovalInfo, } from "./mergeTreeNodes.js";
17
+ import { CollaborationWindow, Marker, MaxNodesInBlock, MergeBlock, assertSegmentLeaf, assignChild, isSegmentLeaf, reservedMarkerIdKey, seqLTE, } from "./mergeTreeNodes.js";
20
18
  import { createAnnotateRangeOp, createInsertSegmentOp, createRemoveRangeOp, } from "./opBuilder.js";
21
19
  import { MergeTreeDeltaType, ReferenceType, } from "./ops.js";
22
20
  import { PartialSequenceLengths } from "./partialLengths.js";
23
21
  import { PerspectiveImpl, isSegmentPresent } from "./perspective.js";
24
22
  import { createMap, extend, extendIfUndefined } from "./properties.js";
25
23
  import { DetachedReferencePosition, refGetTileLabels, refHasTileLabel, refTypeIncludesFlag, } from "./referencePositions.js";
26
- // eslint-disable-next-line import/no-deprecated
27
24
  import { SegmentGroupCollection } from "./segmentGroupCollection.js";
28
- // eslint-disable-next-line import/no-deprecated
25
+ import { assertMoved, assertRemoved, isMergeNodeInfo, isMoved, isRemoved, overwriteInfo, removeRemovalInfo, toMoveInfo, toRemovalInfo, } from "./segmentInfos.js";
29
26
  import { copyPropertiesAndManager, PropertiesManager, PropertiesRollback, } from "./segmentPropertiesManager.js";
30
27
  import { Side } from "./sequencePlace.js";
31
28
  import { SortedSegmentSet } from "./sortedSegmentSet.js";
32
29
  import { zamboniSegments } from "./zamboni.js";
33
- // eslint-disable-next-line import/no-deprecated
34
- function markSegmentMoved(seg, moveInfo) {
35
- seg.moveDst = moveInfo.moveDst;
36
- seg.movedClientIds = [...moveInfo.movedClientIds];
37
- seg.movedSeqs = [moveInfo.movedSeq];
38
- seg.movedSeq = moveInfo.movedSeq;
39
- seg.localMovedSeq = moveInfo.localMovedSeq;
40
- seg.wasMovedOnInsert = moveInfo.wasMovedOnInsert;
41
- }
42
- // eslint-disable-next-line import/no-deprecated
43
- function isMoved(segment) {
44
- return toMoveInfo(segment) !== undefined;
45
- }
46
- // eslint-disable-next-line import/no-deprecated
47
- function isRemoved(segment) {
48
- return toRemovalInfo(segment) !== undefined;
49
- }
50
- // eslint-disable-next-line import/no-deprecated
51
30
  function isRemovedAndAcked(segment) {
52
31
  const removalInfo = toRemovalInfo(segment);
53
32
  return removalInfo !== undefined && removalInfo.removedSeq !== UnassignedSequenceNumber;
@@ -91,29 +70,25 @@ function ackSegment(segment, segmentGroup, opArgs) {
91
70
  return true;
92
71
  }
93
72
  case MergeTreeDeltaType.REMOVE: {
94
- // eslint-disable-next-line import/no-deprecated
95
- const removalInfo = toRemovalInfo(segment);
96
- assert(removalInfo !== undefined, 0x046 /* "On remove ack, missing removal info!" */);
73
+ assertRemoved(segment);
97
74
  segment.localRemovedSeq = undefined;
98
- if (removalInfo.removedSeq === UnassignedSequenceNumber) {
99
- removalInfo.removedSeq = sequenceNumber;
75
+ if (segment.removedSeq === UnassignedSequenceNumber) {
76
+ segment.removedSeq = sequenceNumber;
100
77
  return true;
101
78
  }
102
79
  return false;
103
80
  }
104
81
  case MergeTreeDeltaType.OBLITERATE:
105
82
  case MergeTreeDeltaType.OBLITERATE_SIDED: {
106
- // eslint-disable-next-line import/no-deprecated
107
- const moveInfo = toMoveInfo(segment);
108
- assert(moveInfo !== undefined, 0x86e /* On obliterate ack, missing move info! */);
83
+ assertMoved(segment);
109
84
  const obliterateInfo = segmentGroup.obliterateInfo;
110
85
  assert(obliterateInfo !== undefined, 0xa40 /* must have obliterate info */);
111
86
  segment.localMovedSeq = obliterateInfo.localSeq = undefined;
112
- const seqIdx = moveInfo.movedSeqs.indexOf(UnassignedSequenceNumber);
87
+ const seqIdx = segment.movedSeqs.indexOf(UnassignedSequenceNumber);
113
88
  assert(seqIdx !== -1, 0x86f /* expected movedSeqs to contain unacked seq */);
114
- moveInfo.movedSeqs[seqIdx] = sequenceNumber;
115
- if (moveInfo.movedSeq === UnassignedSequenceNumber) {
116
- moveInfo.movedSeq = sequenceNumber;
89
+ segment.movedSeqs[seqIdx] = sequenceNumber;
90
+ if (segment.movedSeq === UnassignedSequenceNumber) {
91
+ segment.movedSeq = sequenceNumber;
117
92
  return true;
118
93
  }
119
94
  return false;
@@ -150,7 +125,6 @@ export function findRootMergeBlock(segmentOrNode) {
150
125
  * entries for all segments visited during excursion.
151
126
  * This can reduce the number of times the tree needs to be scanned if a range containing many
152
127
  * SlideOnRemove references is removed.
153
- * @internal
154
128
  */
155
129
  function getSlideToSegment(segment, slidingPreference = SlidingPreference.FORWARD, cache, useNewSlidingBehavior = false) {
156
130
  if (!segment ||
@@ -170,7 +144,8 @@ function getSlideToSegment(segment, slidingPreference = SlidingPreference.FORWAR
170
144
  return false;
171
145
  }
172
146
  if (cache !== undefined &&
173
- (seg.removedSeq === segment.removedSeq || seg.movedSeq === segment.movedSeq)) {
147
+ (toRemovalInfo(seg)?.removedSeq === toRemovalInfo(segment)?.removedSeq ||
148
+ toMoveInfo(seg)?.movedSeq === toMoveInfo(segment)?.movedSeq)) {
174
149
  cache.set(seg, result);
175
150
  }
176
151
  return true;
@@ -217,7 +192,7 @@ function getSlideToSegment(segment, slidingPreference = SlidingPreference.FORWAR
217
192
  * @internal
218
193
  */
219
194
  export function getSlideToSegoff(segoff, slidingPreference = SlidingPreference.FORWARD, useNewSlidingBehavior = false) {
220
- if (segoff.segment === undefined) {
195
+ if (!isSegmentLeaf(segoff.segment)) {
221
196
  return segoff;
222
197
  }
223
198
  const [segment, _] = getSlideToSegment(segoff.segment, slidingPreference, undefined, useNewSlidingBehavior);
@@ -244,7 +219,6 @@ class Obliterates {
244
219
  * See https://github.com/microsoft/FluidFramework/blob/main/packages/dds/merge-tree/docs/Obliterate.md#remote-perspective
245
220
  * for additional context
246
221
  */
247
- // eslint-disable-next-line import/no-deprecated
248
222
  this.seqOrdered = new DoublyLinkedList();
249
223
  /**
250
224
  * This contains a sorted lists of all obliterate starts
@@ -262,7 +236,6 @@ class Obliterates {
262
236
  this.mergeTree.removeLocalReferencePosition(ob.data.end);
263
237
  }
264
238
  }
265
- // eslint-disable-next-line import/no-deprecated
266
239
  addOrUpdate(obliterateInfo) {
267
240
  const { seq, start } = obliterateInfo;
268
241
  if (seq !== UnassignedSequenceNumber) {
@@ -273,14 +246,14 @@ class Obliterates {
273
246
  empty() {
274
247
  return this.startOrdered.size === 0;
275
248
  }
276
- // eslint-disable-next-line import/no-deprecated
277
249
  findOverlapping(seg) {
278
- // eslint-disable-next-line import/no-deprecated
279
250
  const overlapping = [];
280
251
  for (const start of this.startOrdered.items) {
281
- if (start.getSegment().ordinal <= seg.ordinal) {
252
+ const startSeg = start.getSegment();
253
+ if (isMergeNodeInfo(startSeg) && startSeg.ordinal <= seg.ordinal) {
282
254
  const ob = start.properties?.obliterate;
283
- if (ob.end.getSegment().ordinal >= seg.ordinal) {
255
+ const endSeg = ob.end.getSegment();
256
+ if (isMergeNodeInfo(endSeg) && endSeg.ordinal >= seg.ordinal) {
284
257
  overlapping.push(ob);
285
258
  }
286
259
  }
@@ -298,9 +271,7 @@ class Obliterates {
298
271
  export class MergeTree {
299
272
  constructor(options) {
300
273
  this.options = options;
301
- // eslint-disable-next-line import/no-deprecated
302
274
  this.collabWindow = new CollaborationWindow();
303
- // eslint-disable-next-line import/no-deprecated
304
275
  this.pendingSegments = new DoublyLinkedList();
305
276
  this.segmentsToScour = new Heap(LRUSegmentComparer);
306
277
  /**
@@ -318,6 +289,7 @@ export class MergeTree {
318
289
  return {};
319
290
  }
320
291
  const next = segment.splitAt(pos);
292
+ assertSegmentLeaf(next);
321
293
  if (segment?.segmentGroups) {
322
294
  next.segmentGroups ?? (next.segmentGroups = new SegmentGroupCollection(next));
323
295
  segment.segmentGroups.copyTo(next.segmentGroups);
@@ -380,7 +352,9 @@ export class MergeTree {
380
352
  }
381
353
  assert(refSeq !== undefined, 0x398 /* localSeq provided for local length without refSeq */);
382
354
  assert(segment.seq !== undefined, 0x399 /* segment with no seq in mergeTree */);
383
- const { seq, removedSeq, localRemovedSeq, movedSeq, localMovedSeq } = segment;
355
+ const { seq } = segment;
356
+ const { removedSeq, localRemovedSeq } = removalInfo ?? {};
357
+ const { movedSeq, localMovedSeq } = moveInfo ?? {};
384
358
  if (seq === UnassignedSequenceNumber) {
385
359
  assert(segment.localSeq !== undefined, 0x39a /* unacked segment with undefined localSeq */);
386
360
  // inserted locally, still un-acked
@@ -416,7 +390,7 @@ export class MergeTree {
416
390
  }
417
391
  addNode(block, node) {
418
392
  const index = block.childCount++;
419
- block.assignChild(node, index, false);
393
+ assignChild(block, node, index, false);
420
394
  return index;
421
395
  }
422
396
  reloadFromSegments(segments) {
@@ -510,12 +484,12 @@ export class MergeTree {
510
484
  assert(localSeq === undefined || clientId === this.collabWindow.clientId, 0x39b /* localSeq provided for non-local client */);
511
485
  let segment;
512
486
  let offset;
513
- const leaf = (leafSeg, segpos, _refSeq, _clientId, start) => {
487
+ const leaf = (leafSeg, _, start) => {
514
488
  segment = leafSeg;
515
489
  offset = start;
516
490
  return false;
517
491
  };
518
- this.nodeMap(refSeq, clientId, leaf, undefined, undefined, pos, pos + 1, localSeq);
492
+ this.nodeMap(refSeq, clientId, leaf, undefined, pos, pos + 1, localSeq);
519
493
  return { segment, offset };
520
494
  }
521
495
  /**
@@ -650,7 +624,6 @@ export class MergeTree {
650
624
  if (this.localPartialsComputed) {
651
625
  return;
652
626
  }
653
- // eslint-disable-next-line import/no-deprecated
654
627
  const rebaseCollabWindow = new CollaborationWindow();
655
628
  rebaseCollabWindow.loadFrom(this.collabWindow);
656
629
  if (refSeq < this.collabWindow.minSeq) {
@@ -734,24 +707,26 @@ export class MergeTree {
734
707
  */
735
708
  referencePositionToLocalPosition(refPos, refSeq = Number.MAX_SAFE_INTEGER, clientId = this.collabWindow.clientId, localSeq = this.collabWindow.localSeq) {
736
709
  const seg = refPos.getSegment();
737
- if (seg?.parent === undefined) {
710
+ if (!isSegmentLeaf(seg)) {
738
711
  // We have no idea where this reference is, because it refers to a segment which is not in the tree.
739
712
  return DetachedReferencePosition;
740
713
  }
741
714
  if (refPos.isLeaf()) {
742
- return this.getPosition(refPos, refSeq, clientId, localSeq);
715
+ return this.getPosition(seg, refSeq, clientId, localSeq);
743
716
  }
744
717
  if (refTypeIncludesFlag(refPos, ReferenceType.Transient) || seg.localRefs?.has(refPos)) {
745
718
  if (seg !== this.startOfTree &&
746
719
  seg !== this.endOfTree &&
747
720
  !isSegmentPresent(seg, { refSeq, localSeq })) {
748
721
  const forward = refPos.slidingPreference === SlidingPreference.FORWARD;
749
- const slideSeq = seg.movedSeq !== UnassignedSequenceNumber && seg.movedSeq !== undefined
750
- ? seg.movedSeq
751
- : seg.removedSeq !== UnassignedSequenceNumber && seg.removedSeq !== undefined
752
- ? seg.removedSeq
722
+ const moveInfo = toMoveInfo(seg);
723
+ const removeInfo = toRemovalInfo(seg);
724
+ const slideSeq = moveInfo !== undefined && moveInfo.movedSeq !== UnassignedSequenceNumber
725
+ ? moveInfo.movedSeq
726
+ : removeInfo !== undefined && removeInfo.removedSeq !== UnassignedSequenceNumber
727
+ ? removeInfo.removedSeq
753
728
  : refSeq;
754
- const slideLocalSeq = seg.localMovedSeq ?? seg.localRemovedSeq;
729
+ const slideLocalSeq = moveInfo?.localMovedSeq ?? removeInfo?.localRemovedSeq;
755
730
  const perspective = new PerspectiveImpl(this, {
756
731
  refSeq: slideSeq,
757
732
  localSeq: slideLocalSeq,
@@ -779,11 +754,10 @@ export class MergeTree {
779
754
  searchForMarker(startPos, clientId, markerLabel, forwards = true) {
780
755
  let foundMarker;
781
756
  const { segment } = this.getContainingSegment(startPos, UniversalSequenceNumber, clientId);
782
- const segWithParent = segment;
783
- if (segWithParent?.parent === undefined) {
757
+ if (!isSegmentLeaf(segment)) {
784
758
  return undefined;
785
759
  }
786
- depthFirstNodeWalk(segWithParent.parent, segWithParent, (node) => {
760
+ depthFirstNodeWalk(segment.parent, segment, (node) => {
787
761
  if (node.isLeaf()) {
788
762
  if (Marker.is(node) && refHasTileLabel(node, markerLabel)) {
789
763
  foundMarker = node;
@@ -805,8 +779,8 @@ export class MergeTree {
805
779
  updateRoot(splitNode) {
806
780
  if (splitNode !== undefined) {
807
781
  const newRoot = this.makeBlock(2);
808
- newRoot.assignChild(this.root, 0, false);
809
- newRoot.assignChild(splitNode, 1, false);
782
+ assignChild(newRoot, this.root, 0, false);
783
+ assignChild(newRoot, splitNode, 1, false);
810
784
  this.root = newRoot;
811
785
  this.nodeUpdateOrdinals(this.root);
812
786
  this.nodeUpdateLengthNewStructure(this.root);
@@ -862,9 +836,7 @@ export class MergeTree {
862
836
  zamboniSegments(this);
863
837
  }
864
838
  }
865
- addToPendingList(segment,
866
- // eslint-disable-next-line import/no-deprecated
867
- segmentGroup, localSeq, previousProps) {
839
+ addToPendingList(segment, segmentGroup, localSeq, previousProps) {
868
840
  let _segmentGroup = segmentGroup;
869
841
  if (_segmentGroup === undefined) {
870
842
  _segmentGroup = {
@@ -884,7 +856,6 @@ export class MergeTree {
884
856
  if (previousProps) {
885
857
  _segmentGroup.previousProps.push(previousProps);
886
858
  }
887
- // eslint-disable-next-line import/no-deprecated
888
859
  const segmentGroups = (segment.segmentGroups ?? (segment.segmentGroups = new SegmentGroupCollection(segment)));
889
860
  segmentGroups.enqueue(_segmentGroup);
890
861
  return _segmentGroup;
@@ -911,7 +882,7 @@ export class MergeTree {
911
882
  if (relativePos.id) {
912
883
  marker = this.getMarkerFromId(relativePos.id);
913
884
  }
914
- if (marker) {
885
+ if (isSegmentLeaf(marker)) {
915
886
  pos = this.getPosition(marker, refseq, clientId);
916
887
  if (relativePos.before) {
917
888
  if (relativePos.offset !== undefined) {
@@ -969,7 +940,7 @@ export class MergeTree {
969
940
  }
970
941
  const segmentInfo = this.getContainingSegment(remoteClientPosition, remoteClientRefSeq, remoteClientId);
971
942
  const { currentSeq, clientId } = this.collabWindow;
972
- if (segmentInfo?.segment) {
943
+ if (isSegmentLeaf(segmentInfo?.segment)) {
973
944
  const segmentPosition = this.getPosition(segmentInfo.segment, currentSeq, clientId);
974
945
  return segmentPosition + segmentInfo.offset;
975
946
  }
@@ -990,7 +961,6 @@ export class MergeTree {
990
961
  });
991
962
  return siblingExists;
992
963
  };
993
- // eslint-disable-next-line import/no-deprecated
994
964
  let segmentGroup;
995
965
  const saveIfLocal = (locSegment) => {
996
966
  // Save segment so we can assign sequence number when acked by server
@@ -1020,93 +990,95 @@ export class MergeTree {
1020
990
  }
1021
991
  return segmentChanges;
1022
992
  };
993
+ const insertInfo = {
994
+ clientId,
995
+ seq,
996
+ localSeq,
997
+ };
1023
998
  // TODO: build tree from segs and insert all at once
1024
999
  let insertPos = pos;
1025
- for (const newSegment of newSegments) {
1026
- if (newSegment.cachedLength > 0) {
1027
- newSegment.seq = seq;
1028
- newSegment.localSeq = localSeq;
1029
- newSegment.clientId = clientId;
1030
- if (Marker.is(newSegment)) {
1031
- const markerId = newSegment.getId();
1032
- if (markerId) {
1033
- this.idToMarker.set(markerId, newSegment);
1034
- }
1000
+ for (const newSegment of newSegments
1001
+ .filter((s) => s.cachedLength > 0)
1002
+ .map((s) => overwriteInfo(s, insertInfo))) {
1003
+ if (Marker.is(newSegment)) {
1004
+ const markerId = newSegment.getId();
1005
+ if (markerId) {
1006
+ this.idToMarker.set(markerId, newSegment);
1035
1007
  }
1036
- const splitNode = this.insertingWalk(this.root, insertPos, refSeq, clientId, seq, {
1037
- leaf: onLeaf,
1038
- candidateSegment: newSegment,
1039
- continuePredicate: continueFrom,
1008
+ }
1009
+ const splitNode = this.insertingWalk(this.root, insertPos, refSeq, clientId, seq, {
1010
+ leaf: onLeaf,
1011
+ candidateSegment: newSegment,
1012
+ continuePredicate: continueFrom,
1013
+ });
1014
+ if (!isSegmentLeaf(newSegment)) {
1015
+ // Indicates an attempt to insert past the end of the merge-tree's content.
1016
+ const errorConstructor = localSeq === undefined ? DataProcessingError : UsageError;
1017
+ throw new errorConstructor("MergeTree insert failed", {
1018
+ currentSeq: this.collabWindow.currentSeq,
1019
+ minSeq: this.collabWindow.minSeq,
1020
+ segSeq: insertInfo.seq,
1040
1021
  });
1041
- if (newSegment.parent === undefined) {
1042
- // Indicates an attempt to insert past the end of the merge-tree's content.
1043
- const errorConstructor = localSeq === undefined ? DataProcessingError : UsageError;
1044
- throw new errorConstructor("MergeTree insert failed", {
1045
- currentSeq: this.collabWindow.currentSeq,
1046
- minSeq: this.collabWindow.minSeq,
1047
- segSeq: newSegment.seq,
1048
- });
1049
- }
1050
- this.updateRoot(splitNode);
1051
- insertPos += newSegment.cachedLength;
1052
- if (!this.options?.mergeTreeEnableObliterate || this.obliterates.empty()) {
1053
- saveIfLocal(newSegment);
1054
- continue;
1055
- }
1056
- let oldest;
1057
- let normalizedOldestSeq = 0;
1058
- let newest;
1059
- let normalizedNewestSeq = 0;
1060
- const movedClientIds = [];
1061
- const movedSeqs = [];
1062
- for (const ob of this.obliterates.findOverlapping(newSegment)) {
1063
- // compute a normalized seq that takes into account local seqs
1064
- // but is still comparable to remote seqs to keep the checks below easy
1065
- // REMOTE SEQUENCE NUMBERS LOCAL SEQUENCE NUMBERS
1066
- // [0, 1, 2, 3, ..., 100, ..., 1000, ..., (MAX - MaxLocalSeq), L1, L2, L3, L4, ..., L100, ..., L1000, ...(MAX)]
1067
- const normalizedObSeq = ob.seq === UnassignedSequenceNumber
1068
- ? Number.MAX_SAFE_INTEGER - this.collabWindow.localSeq + ob.localSeq
1069
- : ob.seq;
1070
- if (normalizedObSeq > refSeq) {
1071
- if (oldest === undefined || normalizedOldestSeq > normalizedObSeq) {
1072
- normalizedOldestSeq = normalizedObSeq;
1073
- oldest = ob;
1074
- movedClientIds.unshift(ob.clientId);
1075
- movedSeqs.unshift(ob.seq);
1076
- }
1077
- else {
1078
- movedClientIds.push(ob.clientId);
1079
- movedSeqs.push(ob.seq);
1080
- }
1081
- if (newest === undefined || normalizedNewestSeq < normalizedObSeq) {
1082
- normalizedNewestSeq = normalizedObSeq;
1083
- newest = ob;
1084
- }
1022
+ }
1023
+ this.updateRoot(splitNode);
1024
+ insertPos += newSegment.cachedLength;
1025
+ if (!this.options?.mergeTreeEnableObliterate || this.obliterates.empty()) {
1026
+ saveIfLocal(newSegment);
1027
+ continue;
1028
+ }
1029
+ let oldest;
1030
+ let normalizedOldestSeq = 0;
1031
+ let newest;
1032
+ let normalizedNewestSeq = 0;
1033
+ const movedClientIds = [];
1034
+ const movedSeqs = [];
1035
+ for (const ob of this.obliterates.findOverlapping(newSegment)) {
1036
+ // compute a normalized seq that takes into account local seqs
1037
+ // but is still comparable to remote seqs to keep the checks below easy
1038
+ // REMOTE SEQUENCE NUMBERS LOCAL SEQUENCE NUMBERS
1039
+ // [0, 1, 2, 3, ..., 100, ..., 1000, ..., (MAX - MaxLocalSeq), L1, L2, L3, L4, ..., L100, ..., L1000, ...(MAX)]
1040
+ const normalizedObSeq = ob.seq === UnassignedSequenceNumber
1041
+ ? Number.MAX_SAFE_INTEGER - this.collabWindow.localSeq + ob.localSeq
1042
+ : ob.seq;
1043
+ if (normalizedObSeq > refSeq) {
1044
+ if (oldest === undefined || normalizedOldestSeq > normalizedObSeq) {
1045
+ normalizedOldestSeq = normalizedObSeq;
1046
+ oldest = ob;
1047
+ movedClientIds.unshift(ob.clientId);
1048
+ movedSeqs.unshift(ob.seq);
1085
1049
  }
1086
- }
1087
- if (oldest && newest?.clientId !== clientId) {
1088
- // eslint-disable-next-line import/no-deprecated
1089
- const moveInfo = {
1090
- movedClientIds,
1091
- movedSeq: oldest.seq,
1092
- movedSeqs,
1093
- localMovedSeq: oldest.localSeq,
1094
- wasMovedOnInsert: oldest.seq !== UnassignedSequenceNumber,
1095
- };
1096
- markSegmentMoved(newSegment, moveInfo);
1097
- if (moveInfo.localMovedSeq !== undefined) {
1098
- assert(oldest.segmentGroup !== undefined, 0x86c /* expected segment group to exist */);
1099
- this.addToPendingList(newSegment, oldest.segmentGroup);
1050
+ else {
1051
+ movedClientIds.push(ob.clientId);
1052
+ movedSeqs.push(ob.seq);
1100
1053
  }
1101
- if (newSegment.parent) {
1102
- this.blockUpdatePathLengths(newSegment.parent, seq, clientId);
1054
+ if (newest === undefined || normalizedNewestSeq < normalizedObSeq) {
1055
+ normalizedNewestSeq = normalizedObSeq;
1056
+ newest = ob;
1103
1057
  }
1104
1058
  }
1105
- else if (oldest && newest?.clientId === clientId) {
1106
- newSegment.prevObliterateByInserter = newest;
1059
+ }
1060
+ if (oldest && newest?.clientId !== clientId) {
1061
+ // eslint-disable-next-line import/no-deprecated
1062
+ const moveInfo = {
1063
+ movedClientIds,
1064
+ movedSeq: oldest.seq,
1065
+ movedSeqs,
1066
+ localMovedSeq: oldest.localSeq,
1067
+ wasMovedOnInsert: oldest.seq !== UnassignedSequenceNumber,
1068
+ };
1069
+ overwriteInfo(newSegment, moveInfo);
1070
+ if (moveInfo.localMovedSeq !== undefined) {
1071
+ assert(oldest.segmentGroup !== undefined, 0x86c /* expected segment group to exist */);
1072
+ this.addToPendingList(newSegment, oldest.segmentGroup);
1107
1073
  }
1108
- saveIfLocal(newSegment);
1074
+ if (newSegment.parent) {
1075
+ this.blockUpdatePathLengths(newSegment.parent, seq, clientId);
1076
+ }
1077
+ }
1078
+ else if (oldest && newest?.clientId === clientId) {
1079
+ newSegment.prevObliterateByInserter = newest;
1109
1080
  }
1081
+ saveIfLocal(newSegment);
1110
1082
  }
1111
1083
  }
1112
1084
  ensureIntervalBoundary(pos, refSeq, clientId) {
@@ -1127,10 +1099,8 @@ export class MergeTree {
1127
1099
  const newSeq = seq === UnassignedSequenceNumber ? Number.MAX_SAFE_INTEGER : seq;
1128
1100
  const segSeq = node.seq === UnassignedSequenceNumber ? Number.MAX_SAFE_INTEGER - 1 : (node.seq ?? 0);
1129
1101
  return (newSeq > segSeq ||
1130
- (node.movedSeq !== undefined &&
1131
- node.movedSeq !== UnassignedSequenceNumber &&
1132
- node.movedSeq > seq) ||
1133
- (node.removedSeq !== undefined &&
1102
+ (isMoved(node) && node.movedSeq !== UnassignedSequenceNumber && node.movedSeq > seq) ||
1103
+ (isRemoved(node) &&
1134
1104
  node.removedSeq !== UnassignedSequenceNumber &&
1135
1105
  node.removedSeq > seq));
1136
1106
  }
@@ -1162,7 +1132,7 @@ export class MergeTree {
1162
1132
  const segment = child;
1163
1133
  const segmentChanges = context.leaf(segment, _pos, context);
1164
1134
  if (segmentChanges.replaceCurrent) {
1165
- block.assignChild(segmentChanges.replaceCurrent, childIndex, false);
1135
+ assignChild(block, segmentChanges.replaceCurrent, childIndex, false);
1166
1136
  segmentChanges.replaceCurrent.ordinal = child.ordinal;
1167
1137
  }
1168
1138
  if (segmentChanges.next) {
@@ -1213,7 +1183,7 @@ export class MergeTree {
1213
1183
  block.children[i] = block.children[i - 1];
1214
1184
  block.children[i].index = i;
1215
1185
  }
1216
- block.assignChild(newNode, childIndex, false);
1186
+ assignChild(block, newNode, childIndex, false);
1217
1187
  block.childCount++;
1218
1188
  block.setOrdinal(newNode, childIndex);
1219
1189
  if (block.childCount < MaxNodesInBlock) {
@@ -1242,7 +1212,7 @@ export class MergeTree {
1242
1212
  // Update ordinals to reflect lowered child count
1243
1213
  this.nodeUpdateOrdinals(node);
1244
1214
  for (let i = 0; i < halfCount; i++) {
1245
- newNode.assignChild(node.children[halfCount + i], i, false);
1215
+ assignChild(newNode, node.children[halfCount + i], i, false);
1246
1216
  node.children[halfCount + i] = undefined;
1247
1217
  }
1248
1218
  this.nodeUpdateLengthNewStructure(node);
@@ -1269,9 +1239,7 @@ export class MergeTree {
1269
1239
  * @param opArgs - The op args for the annotate op. this is passed to the merge tree callback if there is one
1270
1240
  * @param rollback - Whether this is for a local rollback and what kind
1271
1241
  */
1272
- annotateRange(start, end, propsOrAdjust, refSeq, clientId, seq, opArgs,
1273
- // eslint-disable-next-line import/no-deprecated
1274
- rollback = PropertiesRollback.None) {
1242
+ annotateRange(start, end, propsOrAdjust, refSeq, clientId, seq, opArgs, rollback = PropertiesRollback.None) {
1275
1243
  if (propsOrAdjust.adjust !== undefined) {
1276
1244
  errorIfOptionNotTrue(this.options, "mergeTreeEnableAnnotateAdjust");
1277
1245
  }
@@ -1279,7 +1247,6 @@ export class MergeTree {
1279
1247
  this.ensureIntervalBoundary(end, refSeq, clientId);
1280
1248
  const deltaSegments = [];
1281
1249
  const localSeq = seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
1282
- // eslint-disable-next-line import/no-deprecated
1283
1250
  let segmentGroup;
1284
1251
  const opObj = propsOrAdjust.props ?? propsOrAdjust.adjust;
1285
1252
  const annotateSegment = (segment) => {
@@ -1303,7 +1270,7 @@ export class MergeTree {
1303
1270
  }
1304
1271
  return true;
1305
1272
  };
1306
- this.nodeMap(refSeq, clientId, annotateSegment, undefined, undefined, start, end);
1273
+ this.nodeMap(refSeq, clientId, annotateSegment, undefined, start, end);
1307
1274
  // OpArgs == undefined => test code
1308
1275
  if (deltaSegments.length > 0) {
1309
1276
  this.mergeTreeDeltaCallback?.(opArgs, {
@@ -1324,9 +1291,9 @@ export class MergeTree {
1324
1291
  this.ensureIntervalBoundary(endPos, refSeq, clientId);
1325
1292
  let _overwrite = false;
1326
1293
  const localOverlapWithRefs = [];
1294
+ // eslint-disable-next-line import/no-deprecated
1327
1295
  const movedSegments = [];
1328
1296
  const localSeq = seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
1329
- // eslint-disable-next-line import/no-deprecated
1330
1297
  const obliterate = {
1331
1298
  clientId,
1332
1299
  end: createDetachedLocalReferencePosition(undefined),
@@ -1338,7 +1305,7 @@ export class MergeTree {
1338
1305
  };
1339
1306
  const { segment: startSeg } = this.getContainingSegment(start.pos, refSeq, clientId);
1340
1307
  const { segment: endSeg } = this.getContainingSegment(end.pos, refSeq, clientId);
1341
- assert(startSeg !== undefined && endSeg !== undefined, 0xa3f /* segments cannot be undefined */);
1308
+ assert(isSegmentLeaf(startSeg) && isSegmentLeaf(endSeg), 0xa3f /* segments cannot be undefined */);
1342
1309
  obliterate.start = this.createLocalReferencePosition(startSeg, start.side === Side.Before ? 0 : Math.max(startSeg.cachedLength - 1, 0), ReferenceType.StayOnRemove, {
1343
1310
  obliterate,
1344
1311
  });
@@ -1359,7 +1326,7 @@ export class MergeTree {
1359
1326
  this.pendingSegments.push(obliterate.segmentGroup);
1360
1327
  }
1361
1328
  this.obliterates.addOrUpdate(obliterate);
1362
- const markMoved = (segment, pos, _start, _end) => {
1329
+ const markMoved = (segment, pos) => {
1363
1330
  if ((start.side === Side.After && startPos === pos + segment.cachedLength) || // exclusive start segment
1364
1331
  (end.side === Side.Before &&
1365
1332
  endPos === pos &&
@@ -1376,23 +1343,27 @@ export class MergeTree {
1376
1343
  // Other clients will also choose not to obliterate this segment because the most recent obliteration has the same clientId
1377
1344
  return true;
1378
1345
  }
1379
- if (clientId !== segment.clientId &&
1346
+ const wasMovedOnInsert = clientId !== segment.clientId &&
1380
1347
  segment.seq !== undefined &&
1381
1348
  seq !== UnassignedSequenceNumber &&
1382
- (refSeq < segment.seq || segment.seq === UnassignedSequenceNumber)) {
1383
- segment.wasMovedOnInsert = true;
1384
- }
1349
+ (refSeq < segment.seq || segment.seq === UnassignedSequenceNumber);
1385
1350
  if (existingMoveInfo === undefined) {
1386
- segment.movedClientIds = [clientId];
1387
- segment.movedSeq = seq;
1388
- segment.localMovedSeq = localSeq;
1389
- segment.movedSeqs = [seq];
1390
- if (!toRemovalInfo(segment)) {
1391
- movedSegments.push({ segment });
1351
+ // eslint-disable-next-line import/no-deprecated
1352
+ const movedSeg = overwriteInfo(segment, {
1353
+ movedClientIds: [clientId],
1354
+ movedSeq: seq,
1355
+ localMovedSeq: localSeq,
1356
+ movedSeqs: [seq],
1357
+ wasMovedOnInsert,
1358
+ });
1359
+ if (!toRemovalInfo(movedSeg)) {
1360
+ movedSegments.push(movedSeg);
1392
1361
  }
1393
1362
  }
1394
1363
  else {
1395
1364
  _overwrite = true;
1365
+ // never move wasMovedOnInsert from true to false
1366
+ existingMoveInfo.wasMovedOnInsert || (existingMoveInfo.wasMovedOnInsert = wasMovedOnInsert);
1396
1367
  if (existingMoveInfo.movedSeq === UnassignedSequenceNumber) {
1397
1368
  // we moved this locally, but someone else moved it first
1398
1369
  // so put them at the head of the list
@@ -1411,6 +1382,7 @@ export class MergeTree {
1411
1382
  existingMoveInfo.movedSeqs.push(seq);
1412
1383
  }
1413
1384
  }
1385
+ assertMoved(segment);
1414
1386
  // Save segment so can assign moved sequence number when acked by server
1415
1387
  if (this.collabWindow.collaborating) {
1416
1388
  if (segment.movedSeq === UnassignedSequenceNumber &&
@@ -1425,7 +1397,7 @@ export class MergeTree {
1425
1397
  }
1426
1398
  return true;
1427
1399
  };
1428
- const afterMarkMoved = (node, pos, _start, _end) => {
1400
+ const afterMarkMoved = (node) => {
1429
1401
  if (_overwrite) {
1430
1402
  this.nodeUpdateLengthNewStructure(node);
1431
1403
  }
@@ -1434,21 +1406,21 @@ export class MergeTree {
1434
1406
  }
1435
1407
  return true;
1436
1408
  };
1437
- this.nodeMap(refSeq, clientId, markMoved, undefined, afterMarkMoved, start.pos, end.pos + 1, // include the segment containing the end reference
1409
+ this.nodeMap(refSeq, clientId, markMoved, afterMarkMoved, start.pos, end.pos + 1, // include the segment containing the end reference
1438
1410
  undefined, seq === UnassignedSequenceNumber ? undefined : seq);
1439
1411
  this.slideAckedRemovedSegmentReferences(localOverlapWithRefs);
1440
1412
  // opArgs == undefined => test code
1441
1413
  if (start.pos !== end.pos || start.side !== end.side) {
1442
1414
  this.mergeTreeDeltaCallback?.(opArgs, {
1443
1415
  operation: MergeTreeDeltaType.OBLITERATE,
1444
- deltaSegments: movedSegments,
1416
+ deltaSegments: movedSegments.map((segment) => ({ segment })),
1445
1417
  });
1446
1418
  }
1447
1419
  // these events are newly removed
1448
1420
  // so we slide after eventing in case the consumer wants to make reference
1449
1421
  // changes at remove time, like add a ref to track undo redo.
1450
1422
  if (!this.collabWindow.collaborating || clientId !== this.collabWindow.clientId) {
1451
- this.slideAckedRemovedSegmentReferences(movedSegments.map(({ segment }) => segment));
1423
+ this.slideAckedRemovedSegmentReferences(movedSegments);
1452
1424
  }
1453
1425
  if (this.collabWindow.collaborating &&
1454
1426
  seq !== UnassignedSequenceNumber &&
@@ -1471,19 +1443,22 @@ export class MergeTree {
1471
1443
  let _overwrite = false;
1472
1444
  this.ensureIntervalBoundary(start, refSeq, clientId);
1473
1445
  this.ensureIntervalBoundary(end, refSeq, clientId);
1474
- // eslint-disable-next-line import/no-deprecated
1475
1446
  let segmentGroup;
1447
+ // eslint-disable-next-line import/no-deprecated
1476
1448
  const removedSegments = [];
1477
1449
  const localOverlapWithRefs = [];
1478
1450
  const localSeq = seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
1479
1451
  const markRemoved = (segment, pos, _start, _end) => {
1480
1452
  const existingRemovalInfo = toRemovalInfo(segment);
1481
1453
  if (existingRemovalInfo === undefined) {
1482
- segment.removedClientIds = [clientId];
1483
- segment.removedSeq = seq;
1484
- segment.localRemovedSeq = localSeq;
1485
- if (!toMoveInfo(segment)) {
1486
- removedSegments.push({ segment });
1454
+ // eslint-disable-next-line import/no-deprecated
1455
+ const removed = overwriteInfo(segment, {
1456
+ removedClientIds: [clientId],
1457
+ removedSeq: seq,
1458
+ localRemovedSeq: localSeq,
1459
+ });
1460
+ if (!toMoveInfo(removed)) {
1461
+ removedSegments.push(removed);
1487
1462
  }
1488
1463
  }
1489
1464
  else {
@@ -1504,6 +1479,7 @@ export class MergeTree {
1504
1479
  existingRemovalInfo.removedClientIds.push(clientId);
1505
1480
  }
1506
1481
  }
1482
+ assertRemoved(segment);
1507
1483
  // Save segment so we can assign removed sequence number when acked by server
1508
1484
  if (this.collabWindow.collaborating) {
1509
1485
  if (segment.removedSeq === UnassignedSequenceNumber &&
@@ -1518,7 +1494,7 @@ export class MergeTree {
1518
1494
  }
1519
1495
  return true;
1520
1496
  };
1521
- const afterMarkRemoved = (node, pos, _start, _end) => {
1497
+ const afterMarkRemoved = (node) => {
1522
1498
  if (_overwrite) {
1523
1499
  this.nodeUpdateLengthNewStructure(node);
1524
1500
  }
@@ -1527,7 +1503,7 @@ export class MergeTree {
1527
1503
  }
1528
1504
  return true;
1529
1505
  };
1530
- this.nodeMap(refSeq, clientId, markRemoved, undefined, afterMarkRemoved, start, end);
1506
+ this.nodeMap(refSeq, clientId, markRemoved, afterMarkRemoved, start, end);
1531
1507
  // these segments are already viewed as being removed locally and are not event-ed
1532
1508
  // so can slide non-StayOnRemove refs immediately
1533
1509
  this.slideAckedRemovedSegmentReferences(localOverlapWithRefs);
@@ -1535,14 +1511,14 @@ export class MergeTree {
1535
1511
  if (removedSegments.length > 0) {
1536
1512
  this.mergeTreeDeltaCallback?.(opArgs, {
1537
1513
  operation: MergeTreeDeltaType.REMOVE,
1538
- deltaSegments: removedSegments,
1514
+ deltaSegments: removedSegments.map((segment) => ({ segment })),
1539
1515
  });
1540
1516
  }
1541
1517
  // these events are newly removed
1542
1518
  // so we slide after eventing in case the consumer wants to make reference
1543
1519
  // changes at remove time, like add a ref to track undo redo.
1544
1520
  if (!this.collabWindow.collaborating || clientId !== this.collabWindow.clientId) {
1545
- this.slideAckedRemovedSegmentReferences(removedSegments.map(({ segment }) => segment));
1521
+ this.slideAckedRemovedSegmentReferences(removedSegments);
1546
1522
  }
1547
1523
  if (this.collabWindow.collaborating &&
1548
1524
  seq !== UnassignedSequenceNumber &&
@@ -1553,24 +1529,21 @@ export class MergeTree {
1553
1529
  /**
1554
1530
  * Revert an unacked local op
1555
1531
  */
1556
- // eslint-disable-next-line import/no-deprecated
1557
1532
  rollback(op, localOpMetadata) {
1558
1533
  if (op.type === MergeTreeDeltaType.REMOVE) {
1559
- const pendingSegmentGroup = this.pendingSegments.pop?.()?.data;
1534
+ const pendingSegmentGroup = this.pendingSegments.pop()?.data;
1560
1535
  if (pendingSegmentGroup === undefined || pendingSegmentGroup !== localOpMetadata) {
1561
1536
  throw new Error("Rollback op doesn't match last edit");
1562
1537
  }
1563
1538
  // Disabling because a for of loop causes the type of segment to be ISegmentLeaf, which does not have parent information stored
1564
1539
  // eslint-disable-next-line unicorn/no-array-for-each
1565
1540
  pendingSegmentGroup.segments.forEach((segment) => {
1566
- const segmentSegmentGroup = segment?.segmentGroups?.pop?.();
1541
+ const segmentSegmentGroup = segment?.segmentGroups?.pop();
1567
1542
  assert(segmentSegmentGroup === pendingSegmentGroup, 0x3ee /* Unexpected segmentGroup in segment */);
1568
- assert(segment.removedClientIds !== undefined &&
1569
- segment.removedClientIds[0] === this.collabWindow.clientId, 0x39d /* Rollback segment removedClientId does not match local client */);
1570
- segment.removedClientIds = undefined;
1571
- segment.removedSeq = undefined;
1572
- segment.localRemovedSeq = undefined;
1573
- for (let updateNode = segment.parent; updateNode !== undefined; updateNode = updateNode.parent) {
1543
+ assert(isRemoved(segment) && segment.removedClientIds[0] === this.collabWindow.clientId, 0x39d /* Rollback segment removedClientId does not match local client */);
1544
+ let updateNode = segment.parent;
1545
+ removeRemovalInfo(segment);
1546
+ for (updateNode; updateNode !== undefined; updateNode = updateNode.parent) {
1574
1547
  this.blockUpdateLength(updateNode, UnassignedSequenceNumber, this.collabWindow.clientId);
1575
1548
  }
1576
1549
  // Note: optional chaining short-circuits:
@@ -1583,7 +1556,7 @@ export class MergeTree {
1583
1556
  }
1584
1557
  else if (op.type === MergeTreeDeltaType.INSERT ||
1585
1558
  op.type === MergeTreeDeltaType.ANNOTATE) {
1586
- const pendingSegmentGroup = this.pendingSegments.pop?.()?.data;
1559
+ const pendingSegmentGroup = this.pendingSegments.pop()?.data;
1587
1560
  if (pendingSegmentGroup === undefined ||
1588
1561
  pendingSegmentGroup !== localOpMetadata ||
1589
1562
  (op.type === MergeTreeDeltaType.ANNOTATE && !pendingSegmentGroup.previousProps)) {
@@ -1591,7 +1564,7 @@ export class MergeTree {
1591
1564
  }
1592
1565
  let i = 0;
1593
1566
  for (const segment of pendingSegmentGroup.segments) {
1594
- const segmentSegmentGroup = segment?.segmentGroups?.pop?.();
1567
+ const segmentSegmentGroup = segment?.segmentGroups?.pop();
1595
1568
  assert(segmentSegmentGroup === pendingSegmentGroup, 0x3ef /* Unexpected segmentGroup in segment */);
1596
1569
  const start = this.findRollbackPosition(segment);
1597
1570
  if (op.type === MergeTreeDeltaType.INSERT) {
@@ -1623,7 +1596,7 @@ export class MergeTree {
1623
1596
  return false;
1624
1597
  }
1625
1598
  // If not removed, increase position
1626
- if (seg.removedSeq === undefined) {
1599
+ if (!isRemoved(seg)) {
1627
1600
  segmentPosition += seg.cachedLength;
1628
1601
  }
1629
1602
  return true;
@@ -1657,6 +1630,7 @@ export class MergeTree {
1657
1630
  segment = this.endOfTree;
1658
1631
  }
1659
1632
  else {
1633
+ assertSegmentLeaf(_segment);
1660
1634
  segment = _segment;
1661
1635
  }
1662
1636
  // eslint-disable-next-line import/no-deprecated
@@ -1721,7 +1695,7 @@ export class MergeTree {
1721
1695
  for (let i = 0; i < newOrder.length; i++) {
1722
1696
  const seg = newOrder[i];
1723
1697
  const { parent, index, ordinal } = currentOrder[i];
1724
- parent?.assignChild(seg, index, false);
1698
+ assignChild(parent, seg, index, false);
1725
1699
  seg.ordinal = ordinal;
1726
1700
  }
1727
1701
  for (const [segment, groups] of perSegmentTrackingGroups.entries()) {
@@ -1888,7 +1862,7 @@ export class MergeTree {
1888
1862
  this.ensureIntervalBoundary(end, refSeq, clientId);
1889
1863
  }
1890
1864
  }
1891
- this.nodeMap(refSeq, clientId, handler, accum, undefined, start, end, undefined, visibilitySeq);
1865
+ this.nodeMap(refSeq, clientId, (seg, pos, _start, _end) => handler(seg, pos, refSeq, clientId, _start, _end, accum), undefined, start, end, undefined, visibilitySeq);
1892
1866
  }
1893
1867
  /**
1894
1868
  * Map over all visible segments in a given range
@@ -1913,7 +1887,7 @@ export class MergeTree {
1913
1887
  * but it will not count as a segment within the range. That is, it will be
1914
1888
  * ignored for the purposes of tracking when traversal should end.
1915
1889
  */
1916
- nodeMap(refSeq, clientId, leaf, accum, post, start = 0, end, localSeq, visibilitySeq = refSeq) {
1890
+ nodeMap(refSeq, clientId, leaf, post, start = 0, end, localSeq, visibilitySeq = refSeq) {
1917
1891
  const endPos = end ?? this.nodeLength(this.root, refSeq, clientId, localSeq) ?? 0;
1918
1892
  if (endPos === start) {
1919
1893
  return;
@@ -1940,14 +1914,12 @@ export class MergeTree {
1940
1914
  return NodeAction.Skip;
1941
1915
  }
1942
1916
  if (node.isLeaf()) {
1943
- if (leaf(node, pos, refSeq, clientId, start - pos, endPos - pos, accum) === false) {
1917
+ if (leaf(node, pos, start - pos, endPos - pos) === false) {
1944
1918
  return NodeAction.Exit;
1945
1919
  }
1946
1920
  pos = nextPos;
1947
1921
  }
1948
- }, undefined, post === undefined
1949
- ? undefined
1950
- : (block) => post(block, pos, refSeq, clientId, start - pos, endPos - pos, accum));
1922
+ }, undefined, post);
1951
1923
  }
1952
1924
  }
1953
1925
  MergeTree.options = {