@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/lib/mergeTree.js CHANGED
@@ -9,50 +9,26 @@ import { DataProcessingError, UsageError } from "@fluidframework/telemetry-utils
9
9
  import { DoublyLinkedList } from "./collections/index.js";
10
10
  import { NonCollabClient, TreeMaintenanceSequenceNumber, UnassignedSequenceNumber, UniversalSequenceNumber, } from "./constants.js";
11
11
  import { EndOfTreeSegment, StartOfTreeSegment } from "./endOfTreeSegment.js";
12
- import {
13
- // eslint-disable-next-line import/no-deprecated
14
- LocalReferenceCollection, SlidingPreference, anyLocalReferencePosition, createDetachedLocalReferencePosition, filterLocalReferencePositions, } from "./localReference.js";
12
+ import { LocalReferenceCollection, SlidingPreference, anyLocalReferencePosition, createDetachedLocalReferencePosition, filterLocalReferencePositions, } from "./localReference.js";
15
13
  import { MergeTreeMaintenanceType, } from "./mergeTreeDeltaCallback.js";
16
14
  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";
15
+ import { CollaborationWindow, Marker, MaxNodesInBlock, MergeBlock, assertSegmentLeaf, assignChild, isSegmentLeaf, reservedMarkerIdKey, seqLTE, } from "./mergeTreeNodes.js";
20
16
  import { createAnnotateRangeOp, createInsertSegmentOp, createRemoveRangeOp, } from "./opBuilder.js";
21
17
  import { MergeTreeDeltaType, ReferenceType, } from "./ops.js";
22
18
  import { PartialSequenceLengths } from "./partialLengths.js";
23
19
  import { PerspectiveImpl, isSegmentPresent } from "./perspective.js";
24
20
  import { createMap, extend, extendIfUndefined } from "./properties.js";
25
21
  import { DetachedReferencePosition, refGetTileLabels, refHasTileLabel, refTypeIncludesFlag, } from "./referencePositions.js";
26
- // eslint-disable-next-line import/no-deprecated
27
22
  import { SegmentGroupCollection } from "./segmentGroupCollection.js";
28
- // eslint-disable-next-line import/no-deprecated
23
+ import { assertMoved, assertRemoved, isMergeNodeInfo, isMoved, isRemoved, overwriteInfo, removeRemovalInfo, toMoveInfo, toRemovalInfo, } from "./segmentInfos.js";
29
24
  import { copyPropertiesAndManager, PropertiesManager, PropertiesRollback, } from "./segmentPropertiesManager.js";
30
25
  import { Side } from "./sequencePlace.js";
31
26
  import { SortedSegmentSet } from "./sortedSegmentSet.js";
32
27
  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
28
  function isRemovedAndAcked(segment) {
52
29
  const removalInfo = toRemovalInfo(segment);
53
30
  return removalInfo !== undefined && removalInfo.removedSeq !== UnassignedSequenceNumber;
54
31
  }
55
- // eslint-disable-next-line import/no-deprecated
56
32
  function isMovedAndAcked(segment) {
57
33
  const moveInfo = toMoveInfo(segment);
58
34
  return moveInfo !== undefined && moveInfo.movedSeq !== UnassignedSequenceNumber;
@@ -91,29 +67,25 @@ function ackSegment(segment, segmentGroup, opArgs) {
91
67
  return true;
92
68
  }
93
69
  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!" */);
70
+ assertRemoved(segment);
97
71
  segment.localRemovedSeq = undefined;
98
- if (removalInfo.removedSeq === UnassignedSequenceNumber) {
99
- removalInfo.removedSeq = sequenceNumber;
72
+ if (segment.removedSeq === UnassignedSequenceNumber) {
73
+ segment.removedSeq = sequenceNumber;
100
74
  return true;
101
75
  }
102
76
  return false;
103
77
  }
104
78
  case MergeTreeDeltaType.OBLITERATE:
105
79
  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! */);
80
+ assertMoved(segment);
109
81
  const obliterateInfo = segmentGroup.obliterateInfo;
110
82
  assert(obliterateInfo !== undefined, 0xa40 /* must have obliterate info */);
111
83
  segment.localMovedSeq = obliterateInfo.localSeq = undefined;
112
- const seqIdx = moveInfo.movedSeqs.indexOf(UnassignedSequenceNumber);
84
+ const seqIdx = segment.movedSeqs.indexOf(UnassignedSequenceNumber);
113
85
  assert(seqIdx !== -1, 0x86f /* expected movedSeqs to contain unacked seq */);
114
- moveInfo.movedSeqs[seqIdx] = sequenceNumber;
115
- if (moveInfo.movedSeq === UnassignedSequenceNumber) {
116
- moveInfo.movedSeq = sequenceNumber;
86
+ segment.movedSeqs[seqIdx] = sequenceNumber;
87
+ if (segment.movedSeq === UnassignedSequenceNumber) {
88
+ segment.movedSeq = sequenceNumber;
117
89
  return true;
118
90
  }
119
91
  return false;
@@ -150,7 +122,6 @@ export function findRootMergeBlock(segmentOrNode) {
150
122
  * entries for all segments visited during excursion.
151
123
  * This can reduce the number of times the tree needs to be scanned if a range containing many
152
124
  * SlideOnRemove references is removed.
153
- * @internal
154
125
  */
155
126
  function getSlideToSegment(segment, slidingPreference = SlidingPreference.FORWARD, cache, useNewSlidingBehavior = false) {
156
127
  if (!segment ||
@@ -170,7 +141,8 @@ function getSlideToSegment(segment, slidingPreference = SlidingPreference.FORWAR
170
141
  return false;
171
142
  }
172
143
  if (cache !== undefined &&
173
- (seg.removedSeq === segment.removedSeq || seg.movedSeq === segment.movedSeq)) {
144
+ (toRemovalInfo(seg)?.removedSeq === toRemovalInfo(segment)?.removedSeq ||
145
+ toMoveInfo(seg)?.movedSeq === toMoveInfo(segment)?.movedSeq)) {
174
146
  cache.set(seg, result);
175
147
  }
176
148
  return true;
@@ -217,7 +189,7 @@ function getSlideToSegment(segment, slidingPreference = SlidingPreference.FORWAR
217
189
  * @internal
218
190
  */
219
191
  export function getSlideToSegoff(segoff, slidingPreference = SlidingPreference.FORWARD, useNewSlidingBehavior = false) {
220
- if (segoff.segment === undefined) {
192
+ if (!isSegmentLeaf(segoff.segment)) {
221
193
  return segoff;
222
194
  }
223
195
  const [segment, _] = getSlideToSegment(segoff.segment, slidingPreference, undefined, useNewSlidingBehavior);
@@ -244,7 +216,6 @@ class Obliterates {
244
216
  * See https://github.com/microsoft/FluidFramework/blob/main/packages/dds/merge-tree/docs/Obliterate.md#remote-perspective
245
217
  * for additional context
246
218
  */
247
- // eslint-disable-next-line import/no-deprecated
248
219
  this.seqOrdered = new DoublyLinkedList();
249
220
  /**
250
221
  * This contains a sorted lists of all obliterate starts
@@ -262,7 +233,6 @@ class Obliterates {
262
233
  this.mergeTree.removeLocalReferencePosition(ob.data.end);
263
234
  }
264
235
  }
265
- // eslint-disable-next-line import/no-deprecated
266
236
  addOrUpdate(obliterateInfo) {
267
237
  const { seq, start } = obliterateInfo;
268
238
  if (seq !== UnassignedSequenceNumber) {
@@ -273,14 +243,14 @@ class Obliterates {
273
243
  empty() {
274
244
  return this.startOrdered.size === 0;
275
245
  }
276
- // eslint-disable-next-line import/no-deprecated
277
246
  findOverlapping(seg) {
278
- // eslint-disable-next-line import/no-deprecated
279
247
  const overlapping = [];
280
248
  for (const start of this.startOrdered.items) {
281
- if (start.getSegment().ordinal <= seg.ordinal) {
249
+ const startSeg = start.getSegment();
250
+ if (isMergeNodeInfo(startSeg) && startSeg.ordinal <= seg.ordinal) {
282
251
  const ob = start.properties?.obliterate;
283
- if (ob.end.getSegment().ordinal >= seg.ordinal) {
252
+ const endSeg = ob.end.getSegment();
253
+ if (isMergeNodeInfo(endSeg) && endSeg.ordinal >= seg.ordinal) {
284
254
  overlapping.push(ob);
285
255
  }
286
256
  }
@@ -298,9 +268,7 @@ class Obliterates {
298
268
  export class MergeTree {
299
269
  constructor(options) {
300
270
  this.options = options;
301
- // eslint-disable-next-line import/no-deprecated
302
271
  this.collabWindow = new CollaborationWindow();
303
- // eslint-disable-next-line import/no-deprecated
304
272
  this.pendingSegments = new DoublyLinkedList();
305
273
  this.segmentsToScour = new Heap(LRUSegmentComparer);
306
274
  /**
@@ -318,6 +286,7 @@ export class MergeTree {
318
286
  return {};
319
287
  }
320
288
  const next = segment.splitAt(pos);
289
+ assertSegmentLeaf(next);
321
290
  if (segment?.segmentGroups) {
322
291
  next.segmentGroups ?? (next.segmentGroups = new SegmentGroupCollection(next));
323
292
  segment.segmentGroups.copyTo(next.segmentGroups);
@@ -380,7 +349,9 @@ export class MergeTree {
380
349
  }
381
350
  assert(refSeq !== undefined, 0x398 /* localSeq provided for local length without refSeq */);
382
351
  assert(segment.seq !== undefined, 0x399 /* segment with no seq in mergeTree */);
383
- const { seq, removedSeq, localRemovedSeq, movedSeq, localMovedSeq } = segment;
352
+ const { seq } = segment;
353
+ const { removedSeq, localRemovedSeq } = removalInfo ?? {};
354
+ const { movedSeq, localMovedSeq } = moveInfo ?? {};
384
355
  if (seq === UnassignedSequenceNumber) {
385
356
  assert(segment.localSeq !== undefined, 0x39a /* unacked segment with undefined localSeq */);
386
357
  // inserted locally, still un-acked
@@ -416,7 +387,7 @@ export class MergeTree {
416
387
  }
417
388
  addNode(block, node) {
418
389
  const index = block.childCount++;
419
- block.assignChild(node, index, false);
390
+ assignChild(block, node, index, false);
420
391
  return index;
421
392
  }
422
393
  reloadFromSegments(segments) {
@@ -510,12 +481,12 @@ export class MergeTree {
510
481
  assert(localSeq === undefined || clientId === this.collabWindow.clientId, 0x39b /* localSeq provided for non-local client */);
511
482
  let segment;
512
483
  let offset;
513
- const leaf = (leafSeg, segpos, _refSeq, _clientId, start) => {
484
+ const leaf = (leafSeg, _, start) => {
514
485
  segment = leafSeg;
515
486
  offset = start;
516
487
  return false;
517
488
  };
518
- this.nodeMap(refSeq, clientId, leaf, undefined, undefined, pos, pos + 1, localSeq);
489
+ this.nodeMap(refSeq, clientId, leaf, undefined, pos, pos + 1, localSeq);
519
490
  return { segment, offset };
520
491
  }
521
492
  /**
@@ -540,9 +511,7 @@ export class MergeTree {
540
511
  */
541
512
  slideAckedRemovedSegmentReferences(segments) {
542
513
  // References are slid in groups to preserve their order.
543
- // eslint-disable-next-line import/no-deprecated
544
514
  let currentForwardSlideGroup = [];
545
- // eslint-disable-next-line import/no-deprecated
546
515
  let currentBackwardSlideGroup = [];
547
516
  let currentForwardMaybeEndpoint;
548
517
  let currentForwardSlideDestination;
@@ -550,9 +519,7 @@ export class MergeTree {
550
519
  let currentBackwardMaybeEndpoint;
551
520
  let currentBackwardSlideDestination;
552
521
  let currentBackwardSlideIsForward;
553
- const slideGroup = (currentSlideDestination, currentSlideIsForward,
554
- // eslint-disable-next-line import/no-deprecated
555
- currentSlideGroup, pred, maybeEndpoint) => {
522
+ const slideGroup = (currentSlideDestination, currentSlideIsForward, currentSlideGroup, pred, maybeEndpoint) => {
556
523
  if (currentSlideIsForward === undefined) {
557
524
  return;
558
525
  }
@@ -560,7 +527,6 @@ export class MergeTree {
560
527
  const endpointRefsToAdd = currentSlideGroup.map((collection) => filterLocalReferencePositions(collection, (ref) => pred(ref) && !!ref.canSlideToEndpoint));
561
528
  if (maybeEndpoint) {
562
529
  const endpoint = maybeEndpoint === "start" ? this.startOfTree : this.endOfTree;
563
- // eslint-disable-next-line import/no-deprecated
564
530
  const localRefs = LocalReferenceCollection.setOrGet(endpoint);
565
531
  if (currentSlideIsForward) {
566
532
  localRefs.addBeforeTombstones(...endpointRefsToAdd);
@@ -581,7 +547,6 @@ export class MergeTree {
581
547
  }
582
548
  }
583
549
  else {
584
- // eslint-disable-next-line import/no-deprecated
585
550
  const localRefs = LocalReferenceCollection.setOrGet(currentSlideDestination);
586
551
  if (currentSlideIsForward) {
587
552
  localRefs.addBeforeTombstones(...nonEndpointRefsToAdd);
@@ -591,9 +556,7 @@ export class MergeTree {
591
556
  }
592
557
  }
593
558
  };
594
- const trySlideSegment = (segment, currentSlideDestination, currentSlideIsForward,
595
- // eslint-disable-next-line import/no-deprecated
596
- currentSlideGroup, pred, slidingPreference, currentMaybeEndpoint, reassign) => {
559
+ const trySlideSegment = (segment, currentSlideDestination, currentSlideIsForward, currentSlideGroup, pred, slidingPreference, currentMaybeEndpoint, reassign) => {
597
560
  // avoid sliding logic if this segment doesn't have any references
598
561
  // with the given sliding preference
599
562
  if (!segment.localRefs || !anyLocalReferencePosition(segment.localRefs, pred)) {
@@ -650,7 +613,6 @@ export class MergeTree {
650
613
  if (this.localPartialsComputed) {
651
614
  return;
652
615
  }
653
- // eslint-disable-next-line import/no-deprecated
654
616
  const rebaseCollabWindow = new CollaborationWindow();
655
617
  rebaseCollabWindow.loadFrom(this.collabWindow);
656
618
  if (refSeq < this.collabWindow.minSeq) {
@@ -734,24 +696,26 @@ export class MergeTree {
734
696
  */
735
697
  referencePositionToLocalPosition(refPos, refSeq = Number.MAX_SAFE_INTEGER, clientId = this.collabWindow.clientId, localSeq = this.collabWindow.localSeq) {
736
698
  const seg = refPos.getSegment();
737
- if (seg?.parent === undefined) {
699
+ if (!isSegmentLeaf(seg)) {
738
700
  // We have no idea where this reference is, because it refers to a segment which is not in the tree.
739
701
  return DetachedReferencePosition;
740
702
  }
741
703
  if (refPos.isLeaf()) {
742
- return this.getPosition(refPos, refSeq, clientId, localSeq);
704
+ return this.getPosition(seg, refSeq, clientId, localSeq);
743
705
  }
744
706
  if (refTypeIncludesFlag(refPos, ReferenceType.Transient) || seg.localRefs?.has(refPos)) {
745
707
  if (seg !== this.startOfTree &&
746
708
  seg !== this.endOfTree &&
747
709
  !isSegmentPresent(seg, { refSeq, localSeq })) {
748
710
  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
711
+ const moveInfo = toMoveInfo(seg);
712
+ const removeInfo = toRemovalInfo(seg);
713
+ const slideSeq = moveInfo !== undefined && moveInfo.movedSeq !== UnassignedSequenceNumber
714
+ ? moveInfo.movedSeq
715
+ : removeInfo !== undefined && removeInfo.removedSeq !== UnassignedSequenceNumber
716
+ ? removeInfo.removedSeq
753
717
  : refSeq;
754
- const slideLocalSeq = seg.localMovedSeq ?? seg.localRemovedSeq;
718
+ const slideLocalSeq = moveInfo?.localMovedSeq ?? removeInfo?.localRemovedSeq;
755
719
  const perspective = new PerspectiveImpl(this, {
756
720
  refSeq: slideSeq,
757
721
  localSeq: slideLocalSeq,
@@ -779,11 +743,10 @@ export class MergeTree {
779
743
  searchForMarker(startPos, clientId, markerLabel, forwards = true) {
780
744
  let foundMarker;
781
745
  const { segment } = this.getContainingSegment(startPos, UniversalSequenceNumber, clientId);
782
- const segWithParent = segment;
783
- if (segWithParent?.parent === undefined) {
746
+ if (!isSegmentLeaf(segment)) {
784
747
  return undefined;
785
748
  }
786
- depthFirstNodeWalk(segWithParent.parent, segWithParent, (node) => {
749
+ depthFirstNodeWalk(segment.parent, segment, (node) => {
787
750
  if (node.isLeaf()) {
788
751
  if (Marker.is(node) && refHasTileLabel(node, markerLabel)) {
789
752
  foundMarker = node;
@@ -805,8 +768,8 @@ export class MergeTree {
805
768
  updateRoot(splitNode) {
806
769
  if (splitNode !== undefined) {
807
770
  const newRoot = this.makeBlock(2);
808
- newRoot.assignChild(this.root, 0, false);
809
- newRoot.assignChild(splitNode, 1, false);
771
+ assignChild(newRoot, this.root, 0, false);
772
+ assignChild(newRoot, splitNode, 1, false);
810
773
  this.root = newRoot;
811
774
  this.nodeUpdateOrdinals(this.root);
812
775
  this.nodeUpdateLengthNewStructure(this.root);
@@ -862,9 +825,7 @@ export class MergeTree {
862
825
  zamboniSegments(this);
863
826
  }
864
827
  }
865
- addToPendingList(segment,
866
- // eslint-disable-next-line import/no-deprecated
867
- segmentGroup, localSeq, previousProps) {
828
+ addToPendingList(segment, segmentGroup, localSeq, previousProps) {
868
829
  let _segmentGroup = segmentGroup;
869
830
  if (_segmentGroup === undefined) {
870
831
  _segmentGroup = {
@@ -884,7 +845,6 @@ export class MergeTree {
884
845
  if (previousProps) {
885
846
  _segmentGroup.previousProps.push(previousProps);
886
847
  }
887
- // eslint-disable-next-line import/no-deprecated
888
848
  const segmentGroups = (segment.segmentGroups ?? (segment.segmentGroups = new SegmentGroupCollection(segment)));
889
849
  segmentGroups.enqueue(_segmentGroup);
890
850
  return _segmentGroup;
@@ -911,7 +871,7 @@ export class MergeTree {
911
871
  if (relativePos.id) {
912
872
  marker = this.getMarkerFromId(relativePos.id);
913
873
  }
914
- if (marker) {
874
+ if (isSegmentLeaf(marker)) {
915
875
  pos = this.getPosition(marker, refseq, clientId);
916
876
  if (relativePos.before) {
917
877
  if (relativePos.offset !== undefined) {
@@ -969,7 +929,7 @@ export class MergeTree {
969
929
  }
970
930
  const segmentInfo = this.getContainingSegment(remoteClientPosition, remoteClientRefSeq, remoteClientId);
971
931
  const { currentSeq, clientId } = this.collabWindow;
972
- if (segmentInfo?.segment) {
932
+ if (isSegmentLeaf(segmentInfo?.segment)) {
973
933
  const segmentPosition = this.getPosition(segmentInfo.segment, currentSeq, clientId);
974
934
  return segmentPosition + segmentInfo.offset;
975
935
  }
@@ -990,7 +950,6 @@ export class MergeTree {
990
950
  });
991
951
  return siblingExists;
992
952
  };
993
- // eslint-disable-next-line import/no-deprecated
994
953
  let segmentGroup;
995
954
  const saveIfLocal = (locSegment) => {
996
955
  // Save segment so we can assign sequence number when acked by server
@@ -1020,93 +979,94 @@ export class MergeTree {
1020
979
  }
1021
980
  return segmentChanges;
1022
981
  };
982
+ const insertInfo = {
983
+ clientId,
984
+ seq,
985
+ localSeq,
986
+ };
1023
987
  // TODO: build tree from segs and insert all at once
1024
988
  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
- }
989
+ for (const newSegment of newSegments
990
+ .filter((s) => s.cachedLength > 0)
991
+ .map((s) => overwriteInfo(s, insertInfo))) {
992
+ if (Marker.is(newSegment)) {
993
+ const markerId = newSegment.getId();
994
+ if (markerId) {
995
+ this.idToMarker.set(markerId, newSegment);
1035
996
  }
1036
- const splitNode = this.insertingWalk(this.root, insertPos, refSeq, clientId, seq, {
1037
- leaf: onLeaf,
1038
- candidateSegment: newSegment,
1039
- continuePredicate: continueFrom,
997
+ }
998
+ const splitNode = this.insertingWalk(this.root, insertPos, refSeq, clientId, seq, {
999
+ leaf: onLeaf,
1000
+ candidateSegment: newSegment,
1001
+ continuePredicate: continueFrom,
1002
+ });
1003
+ if (!isSegmentLeaf(newSegment)) {
1004
+ // Indicates an attempt to insert past the end of the merge-tree's content.
1005
+ const errorConstructor = localSeq === undefined ? DataProcessingError : UsageError;
1006
+ throw new errorConstructor("MergeTree insert failed", {
1007
+ currentSeq: this.collabWindow.currentSeq,
1008
+ minSeq: this.collabWindow.minSeq,
1009
+ segSeq: insertInfo.seq,
1040
1010
  });
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
- }
1011
+ }
1012
+ this.updateRoot(splitNode);
1013
+ insertPos += newSegment.cachedLength;
1014
+ if (!this.options?.mergeTreeEnableObliterate || this.obliterates.empty()) {
1015
+ saveIfLocal(newSegment);
1016
+ continue;
1017
+ }
1018
+ let oldest;
1019
+ let normalizedOldestSeq = 0;
1020
+ let newest;
1021
+ let normalizedNewestSeq = 0;
1022
+ const movedClientIds = [];
1023
+ const movedSeqs = [];
1024
+ for (const ob of this.obliterates.findOverlapping(newSegment)) {
1025
+ // compute a normalized seq that takes into account local seqs
1026
+ // but is still comparable to remote seqs to keep the checks below easy
1027
+ // REMOTE SEQUENCE NUMBERS LOCAL SEQUENCE NUMBERS
1028
+ // [0, 1, 2, 3, ..., 100, ..., 1000, ..., (MAX - MaxLocalSeq), L1, L2, L3, L4, ..., L100, ..., L1000, ...(MAX)]
1029
+ const normalizedObSeq = ob.seq === UnassignedSequenceNumber
1030
+ ? Number.MAX_SAFE_INTEGER - this.collabWindow.localSeq + ob.localSeq
1031
+ : ob.seq;
1032
+ if (normalizedObSeq > refSeq) {
1033
+ if (oldest === undefined || normalizedOldestSeq > normalizedObSeq) {
1034
+ normalizedOldestSeq = normalizedObSeq;
1035
+ oldest = ob;
1036
+ movedClientIds.unshift(ob.clientId);
1037
+ movedSeqs.unshift(ob.seq);
1085
1038
  }
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);
1039
+ else {
1040
+ movedClientIds.push(ob.clientId);
1041
+ movedSeqs.push(ob.seq);
1100
1042
  }
1101
- if (newSegment.parent) {
1102
- this.blockUpdatePathLengths(newSegment.parent, seq, clientId);
1043
+ if (newest === undefined || normalizedNewestSeq < normalizedObSeq) {
1044
+ normalizedNewestSeq = normalizedObSeq;
1045
+ newest = ob;
1103
1046
  }
1104
1047
  }
1105
- else if (oldest && newest?.clientId === clientId) {
1106
- newSegment.prevObliterateByInserter = newest;
1048
+ }
1049
+ if (oldest && newest?.clientId !== clientId) {
1050
+ const moveInfo = {
1051
+ movedClientIds,
1052
+ movedSeq: oldest.seq,
1053
+ movedSeqs,
1054
+ localMovedSeq: oldest.localSeq,
1055
+ wasMovedOnInsert: oldest.seq !== UnassignedSequenceNumber,
1056
+ };
1057
+ overwriteInfo(newSegment, moveInfo);
1058
+ if (moveInfo.localMovedSeq !== undefined) {
1059
+ assert(oldest.segmentGroup !== undefined, 0x86c /* expected segment group to exist */);
1060
+ this.addToPendingList(newSegment, oldest.segmentGroup);
1061
+ }
1062
+ if (newSegment.parent) {
1063
+ this.blockUpdatePathLengths(newSegment.parent, seq, clientId);
1107
1064
  }
1108
- saveIfLocal(newSegment);
1109
1065
  }
1066
+ else if (oldest && newest?.clientId === clientId) {
1067
+ newSegment.prevObliterateByInserter = newest;
1068
+ }
1069
+ saveIfLocal(newSegment);
1110
1070
  }
1111
1071
  }
1112
1072
  ensureIntervalBoundary(pos, refSeq, clientId) {
@@ -1127,10 +1087,8 @@ export class MergeTree {
1127
1087
  const newSeq = seq === UnassignedSequenceNumber ? Number.MAX_SAFE_INTEGER : seq;
1128
1088
  const segSeq = node.seq === UnassignedSequenceNumber ? Number.MAX_SAFE_INTEGER - 1 : (node.seq ?? 0);
1129
1089
  return (newSeq > segSeq ||
1130
- (node.movedSeq !== undefined &&
1131
- node.movedSeq !== UnassignedSequenceNumber &&
1132
- node.movedSeq > seq) ||
1133
- (node.removedSeq !== undefined &&
1090
+ (isMoved(node) && node.movedSeq !== UnassignedSequenceNumber && node.movedSeq > seq) ||
1091
+ (isRemoved(node) &&
1134
1092
  node.removedSeq !== UnassignedSequenceNumber &&
1135
1093
  node.removedSeq > seq));
1136
1094
  }
@@ -1162,7 +1120,7 @@ export class MergeTree {
1162
1120
  const segment = child;
1163
1121
  const segmentChanges = context.leaf(segment, _pos, context);
1164
1122
  if (segmentChanges.replaceCurrent) {
1165
- block.assignChild(segmentChanges.replaceCurrent, childIndex, false);
1123
+ assignChild(block, segmentChanges.replaceCurrent, childIndex, false);
1166
1124
  segmentChanges.replaceCurrent.ordinal = child.ordinal;
1167
1125
  }
1168
1126
  if (segmentChanges.next) {
@@ -1213,7 +1171,7 @@ export class MergeTree {
1213
1171
  block.children[i] = block.children[i - 1];
1214
1172
  block.children[i].index = i;
1215
1173
  }
1216
- block.assignChild(newNode, childIndex, false);
1174
+ assignChild(block, newNode, childIndex, false);
1217
1175
  block.childCount++;
1218
1176
  block.setOrdinal(newNode, childIndex);
1219
1177
  if (block.childCount < MaxNodesInBlock) {
@@ -1242,7 +1200,7 @@ export class MergeTree {
1242
1200
  // Update ordinals to reflect lowered child count
1243
1201
  this.nodeUpdateOrdinals(node);
1244
1202
  for (let i = 0; i < halfCount; i++) {
1245
- newNode.assignChild(node.children[halfCount + i], i, false);
1203
+ assignChild(newNode, node.children[halfCount + i], i, false);
1246
1204
  node.children[halfCount + i] = undefined;
1247
1205
  }
1248
1206
  this.nodeUpdateLengthNewStructure(node);
@@ -1269,9 +1227,7 @@ export class MergeTree {
1269
1227
  * @param opArgs - The op args for the annotate op. this is passed to the merge tree callback if there is one
1270
1228
  * @param rollback - Whether this is for a local rollback and what kind
1271
1229
  */
1272
- annotateRange(start, end, propsOrAdjust, refSeq, clientId, seq, opArgs,
1273
- // eslint-disable-next-line import/no-deprecated
1274
- rollback = PropertiesRollback.None) {
1230
+ annotateRange(start, end, propsOrAdjust, refSeq, clientId, seq, opArgs, rollback = PropertiesRollback.None) {
1275
1231
  if (propsOrAdjust.adjust !== undefined) {
1276
1232
  errorIfOptionNotTrue(this.options, "mergeTreeEnableAnnotateAdjust");
1277
1233
  }
@@ -1279,7 +1235,6 @@ export class MergeTree {
1279
1235
  this.ensureIntervalBoundary(end, refSeq, clientId);
1280
1236
  const deltaSegments = [];
1281
1237
  const localSeq = seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
1282
- // eslint-disable-next-line import/no-deprecated
1283
1238
  let segmentGroup;
1284
1239
  const opObj = propsOrAdjust.props ?? propsOrAdjust.adjust;
1285
1240
  const annotateSegment = (segment) => {
@@ -1303,7 +1258,7 @@ export class MergeTree {
1303
1258
  }
1304
1259
  return true;
1305
1260
  };
1306
- this.nodeMap(refSeq, clientId, annotateSegment, undefined, undefined, start, end);
1261
+ this.nodeMap(refSeq, clientId, annotateSegment, undefined, start, end);
1307
1262
  // OpArgs == undefined => test code
1308
1263
  if (deltaSegments.length > 0) {
1309
1264
  this.mergeTreeDeltaCallback?.(opArgs, {
@@ -1326,7 +1281,6 @@ export class MergeTree {
1326
1281
  const localOverlapWithRefs = [];
1327
1282
  const movedSegments = [];
1328
1283
  const localSeq = seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
1329
- // eslint-disable-next-line import/no-deprecated
1330
1284
  const obliterate = {
1331
1285
  clientId,
1332
1286
  end: createDetachedLocalReferencePosition(undefined),
@@ -1338,7 +1292,7 @@ export class MergeTree {
1338
1292
  };
1339
1293
  const { segment: startSeg } = this.getContainingSegment(start.pos, refSeq, clientId);
1340
1294
  const { segment: endSeg } = this.getContainingSegment(end.pos, refSeq, clientId);
1341
- assert(startSeg !== undefined && endSeg !== undefined, 0xa3f /* segments cannot be undefined */);
1295
+ assert(isSegmentLeaf(startSeg) && isSegmentLeaf(endSeg), 0xa3f /* segments cannot be undefined */);
1342
1296
  obliterate.start = this.createLocalReferencePosition(startSeg, start.side === Side.Before ? 0 : Math.max(startSeg.cachedLength - 1, 0), ReferenceType.StayOnRemove, {
1343
1297
  obliterate,
1344
1298
  });
@@ -1359,7 +1313,7 @@ export class MergeTree {
1359
1313
  this.pendingSegments.push(obliterate.segmentGroup);
1360
1314
  }
1361
1315
  this.obliterates.addOrUpdate(obliterate);
1362
- const markMoved = (segment, pos, _start, _end) => {
1316
+ const markMoved = (segment, pos) => {
1363
1317
  if ((start.side === Side.After && startPos === pos + segment.cachedLength) || // exclusive start segment
1364
1318
  (end.side === Side.Before &&
1365
1319
  endPos === pos &&
@@ -1376,23 +1330,26 @@ export class MergeTree {
1376
1330
  // Other clients will also choose not to obliterate this segment because the most recent obliteration has the same clientId
1377
1331
  return true;
1378
1332
  }
1379
- if (clientId !== segment.clientId &&
1333
+ const wasMovedOnInsert = clientId !== segment.clientId &&
1380
1334
  segment.seq !== undefined &&
1381
1335
  seq !== UnassignedSequenceNumber &&
1382
- (refSeq < segment.seq || segment.seq === UnassignedSequenceNumber)) {
1383
- segment.wasMovedOnInsert = true;
1384
- }
1336
+ (refSeq < segment.seq || segment.seq === UnassignedSequenceNumber);
1385
1337
  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 });
1338
+ const movedSeg = overwriteInfo(segment, {
1339
+ movedClientIds: [clientId],
1340
+ movedSeq: seq,
1341
+ localMovedSeq: localSeq,
1342
+ movedSeqs: [seq],
1343
+ wasMovedOnInsert,
1344
+ });
1345
+ if (!toRemovalInfo(movedSeg)) {
1346
+ movedSegments.push(movedSeg);
1392
1347
  }
1393
1348
  }
1394
1349
  else {
1395
1350
  _overwrite = true;
1351
+ // never move wasMovedOnInsert from true to false
1352
+ existingMoveInfo.wasMovedOnInsert || (existingMoveInfo.wasMovedOnInsert = wasMovedOnInsert);
1396
1353
  if (existingMoveInfo.movedSeq === UnassignedSequenceNumber) {
1397
1354
  // we moved this locally, but someone else moved it first
1398
1355
  // so put them at the head of the list
@@ -1411,6 +1368,7 @@ export class MergeTree {
1411
1368
  existingMoveInfo.movedSeqs.push(seq);
1412
1369
  }
1413
1370
  }
1371
+ assertMoved(segment);
1414
1372
  // Save segment so can assign moved sequence number when acked by server
1415
1373
  if (this.collabWindow.collaborating) {
1416
1374
  if (segment.movedSeq === UnassignedSequenceNumber &&
@@ -1425,7 +1383,7 @@ export class MergeTree {
1425
1383
  }
1426
1384
  return true;
1427
1385
  };
1428
- const afterMarkMoved = (node, pos, _start, _end) => {
1386
+ const afterMarkMoved = (node) => {
1429
1387
  if (_overwrite) {
1430
1388
  this.nodeUpdateLengthNewStructure(node);
1431
1389
  }
@@ -1434,21 +1392,21 @@ export class MergeTree {
1434
1392
  }
1435
1393
  return true;
1436
1394
  };
1437
- this.nodeMap(refSeq, clientId, markMoved, undefined, afterMarkMoved, start.pos, end.pos + 1, // include the segment containing the end reference
1395
+ this.nodeMap(refSeq, clientId, markMoved, afterMarkMoved, start.pos, end.pos + 1, // include the segment containing the end reference
1438
1396
  undefined, seq === UnassignedSequenceNumber ? undefined : seq);
1439
1397
  this.slideAckedRemovedSegmentReferences(localOverlapWithRefs);
1440
1398
  // opArgs == undefined => test code
1441
1399
  if (start.pos !== end.pos || start.side !== end.side) {
1442
1400
  this.mergeTreeDeltaCallback?.(opArgs, {
1443
1401
  operation: MergeTreeDeltaType.OBLITERATE,
1444
- deltaSegments: movedSegments,
1402
+ deltaSegments: movedSegments.map((segment) => ({ segment })),
1445
1403
  });
1446
1404
  }
1447
1405
  // these events are newly removed
1448
1406
  // so we slide after eventing in case the consumer wants to make reference
1449
1407
  // changes at remove time, like add a ref to track undo redo.
1450
1408
  if (!this.collabWindow.collaborating || clientId !== this.collabWindow.clientId) {
1451
- this.slideAckedRemovedSegmentReferences(movedSegments.map(({ segment }) => segment));
1409
+ this.slideAckedRemovedSegmentReferences(movedSegments);
1452
1410
  }
1453
1411
  if (this.collabWindow.collaborating &&
1454
1412
  seq !== UnassignedSequenceNumber &&
@@ -1471,7 +1429,6 @@ export class MergeTree {
1471
1429
  let _overwrite = false;
1472
1430
  this.ensureIntervalBoundary(start, refSeq, clientId);
1473
1431
  this.ensureIntervalBoundary(end, refSeq, clientId);
1474
- // eslint-disable-next-line import/no-deprecated
1475
1432
  let segmentGroup;
1476
1433
  const removedSegments = [];
1477
1434
  const localOverlapWithRefs = [];
@@ -1479,11 +1436,13 @@ export class MergeTree {
1479
1436
  const markRemoved = (segment, pos, _start, _end) => {
1480
1437
  const existingRemovalInfo = toRemovalInfo(segment);
1481
1438
  if (existingRemovalInfo === undefined) {
1482
- segment.removedClientIds = [clientId];
1483
- segment.removedSeq = seq;
1484
- segment.localRemovedSeq = localSeq;
1485
- if (!toMoveInfo(segment)) {
1486
- removedSegments.push({ segment });
1439
+ const removed = overwriteInfo(segment, {
1440
+ removedClientIds: [clientId],
1441
+ removedSeq: seq,
1442
+ localRemovedSeq: localSeq,
1443
+ });
1444
+ if (!toMoveInfo(removed)) {
1445
+ removedSegments.push(removed);
1487
1446
  }
1488
1447
  }
1489
1448
  else {
@@ -1504,6 +1463,7 @@ export class MergeTree {
1504
1463
  existingRemovalInfo.removedClientIds.push(clientId);
1505
1464
  }
1506
1465
  }
1466
+ assertRemoved(segment);
1507
1467
  // Save segment so we can assign removed sequence number when acked by server
1508
1468
  if (this.collabWindow.collaborating) {
1509
1469
  if (segment.removedSeq === UnassignedSequenceNumber &&
@@ -1518,7 +1478,7 @@ export class MergeTree {
1518
1478
  }
1519
1479
  return true;
1520
1480
  };
1521
- const afterMarkRemoved = (node, pos, _start, _end) => {
1481
+ const afterMarkRemoved = (node) => {
1522
1482
  if (_overwrite) {
1523
1483
  this.nodeUpdateLengthNewStructure(node);
1524
1484
  }
@@ -1527,7 +1487,7 @@ export class MergeTree {
1527
1487
  }
1528
1488
  return true;
1529
1489
  };
1530
- this.nodeMap(refSeq, clientId, markRemoved, undefined, afterMarkRemoved, start, end);
1490
+ this.nodeMap(refSeq, clientId, markRemoved, afterMarkRemoved, start, end);
1531
1491
  // these segments are already viewed as being removed locally and are not event-ed
1532
1492
  // so can slide non-StayOnRemove refs immediately
1533
1493
  this.slideAckedRemovedSegmentReferences(localOverlapWithRefs);
@@ -1535,14 +1495,14 @@ export class MergeTree {
1535
1495
  if (removedSegments.length > 0) {
1536
1496
  this.mergeTreeDeltaCallback?.(opArgs, {
1537
1497
  operation: MergeTreeDeltaType.REMOVE,
1538
- deltaSegments: removedSegments,
1498
+ deltaSegments: removedSegments.map((segment) => ({ segment })),
1539
1499
  });
1540
1500
  }
1541
1501
  // these events are newly removed
1542
1502
  // so we slide after eventing in case the consumer wants to make reference
1543
1503
  // changes at remove time, like add a ref to track undo redo.
1544
1504
  if (!this.collabWindow.collaborating || clientId !== this.collabWindow.clientId) {
1545
- this.slideAckedRemovedSegmentReferences(removedSegments.map(({ segment }) => segment));
1505
+ this.slideAckedRemovedSegmentReferences(removedSegments);
1546
1506
  }
1547
1507
  if (this.collabWindow.collaborating &&
1548
1508
  seq !== UnassignedSequenceNumber &&
@@ -1553,24 +1513,21 @@ export class MergeTree {
1553
1513
  /**
1554
1514
  * Revert an unacked local op
1555
1515
  */
1556
- // eslint-disable-next-line import/no-deprecated
1557
1516
  rollback(op, localOpMetadata) {
1558
1517
  if (op.type === MergeTreeDeltaType.REMOVE) {
1559
- const pendingSegmentGroup = this.pendingSegments.pop?.()?.data;
1518
+ const pendingSegmentGroup = this.pendingSegments.pop()?.data;
1560
1519
  if (pendingSegmentGroup === undefined || pendingSegmentGroup !== localOpMetadata) {
1561
1520
  throw new Error("Rollback op doesn't match last edit");
1562
1521
  }
1563
1522
  // Disabling because a for of loop causes the type of segment to be ISegmentLeaf, which does not have parent information stored
1564
1523
  // eslint-disable-next-line unicorn/no-array-for-each
1565
1524
  pendingSegmentGroup.segments.forEach((segment) => {
1566
- const segmentSegmentGroup = segment?.segmentGroups?.pop?.();
1525
+ const segmentSegmentGroup = segment?.segmentGroups?.pop();
1567
1526
  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) {
1527
+ assert(isRemoved(segment) && segment.removedClientIds[0] === this.collabWindow.clientId, 0x39d /* Rollback segment removedClientId does not match local client */);
1528
+ let updateNode = segment.parent;
1529
+ removeRemovalInfo(segment);
1530
+ for (updateNode; updateNode !== undefined; updateNode = updateNode.parent) {
1574
1531
  this.blockUpdateLength(updateNode, UnassignedSequenceNumber, this.collabWindow.clientId);
1575
1532
  }
1576
1533
  // Note: optional chaining short-circuits:
@@ -1583,7 +1540,7 @@ export class MergeTree {
1583
1540
  }
1584
1541
  else if (op.type === MergeTreeDeltaType.INSERT ||
1585
1542
  op.type === MergeTreeDeltaType.ANNOTATE) {
1586
- const pendingSegmentGroup = this.pendingSegments.pop?.()?.data;
1543
+ const pendingSegmentGroup = this.pendingSegments.pop()?.data;
1587
1544
  if (pendingSegmentGroup === undefined ||
1588
1545
  pendingSegmentGroup !== localOpMetadata ||
1589
1546
  (op.type === MergeTreeDeltaType.ANNOTATE && !pendingSegmentGroup.previousProps)) {
@@ -1591,7 +1548,7 @@ export class MergeTree {
1591
1548
  }
1592
1549
  let i = 0;
1593
1550
  for (const segment of pendingSegmentGroup.segments) {
1594
- const segmentSegmentGroup = segment?.segmentGroups?.pop?.();
1551
+ const segmentSegmentGroup = segment?.segmentGroups?.pop();
1595
1552
  assert(segmentSegmentGroup === pendingSegmentGroup, 0x3ef /* Unexpected segmentGroup in segment */);
1596
1553
  const start = this.findRollbackPosition(segment);
1597
1554
  if (op.type === MergeTreeDeltaType.INSERT) {
@@ -1623,7 +1580,7 @@ export class MergeTree {
1623
1580
  return false;
1624
1581
  }
1625
1582
  // If not removed, increase position
1626
- if (seg.removedSeq === undefined) {
1583
+ if (!isRemoved(seg)) {
1627
1584
  segmentPosition += seg.cachedLength;
1628
1585
  }
1629
1586
  return true;
@@ -1657,9 +1614,9 @@ export class MergeTree {
1657
1614
  segment = this.endOfTree;
1658
1615
  }
1659
1616
  else {
1617
+ assertSegmentLeaf(_segment);
1660
1618
  segment = _segment;
1661
1619
  }
1662
- // eslint-disable-next-line import/no-deprecated
1663
1620
  const localRefs = LocalReferenceCollection.setOrGet(segment);
1664
1621
  const segRef = localRefs.createLocalRef(offset, refType, properties, slidingPreference, canSlideToEndpoint);
1665
1622
  return segRef;
@@ -1721,7 +1678,7 @@ export class MergeTree {
1721
1678
  for (let i = 0; i < newOrder.length; i++) {
1722
1679
  const seg = newOrder[i];
1723
1680
  const { parent, index, ordinal } = currentOrder[i];
1724
- parent?.assignChild(seg, index, false);
1681
+ assignChild(parent, seg, index, false);
1725
1682
  seg.ordinal = ordinal;
1726
1683
  }
1727
1684
  for (const [segment, groups] of perSegmentTrackingGroups.entries()) {
@@ -1888,7 +1845,7 @@ export class MergeTree {
1888
1845
  this.ensureIntervalBoundary(end, refSeq, clientId);
1889
1846
  }
1890
1847
  }
1891
- this.nodeMap(refSeq, clientId, handler, accum, undefined, start, end, undefined, visibilitySeq);
1848
+ this.nodeMap(refSeq, clientId, (seg, pos, _start, _end) => handler(seg, pos, refSeq, clientId, _start, _end, accum), undefined, start, end, undefined, visibilitySeq);
1892
1849
  }
1893
1850
  /**
1894
1851
  * Map over all visible segments in a given range
@@ -1913,7 +1870,7 @@ export class MergeTree {
1913
1870
  * but it will not count as a segment within the range. That is, it will be
1914
1871
  * ignored for the purposes of tracking when traversal should end.
1915
1872
  */
1916
- nodeMap(refSeq, clientId, leaf, accum, post, start = 0, end, localSeq, visibilitySeq = refSeq) {
1873
+ nodeMap(refSeq, clientId, leaf, post, start = 0, end, localSeq, visibilitySeq = refSeq) {
1917
1874
  const endPos = end ?? this.nodeLength(this.root, refSeq, clientId, localSeq) ?? 0;
1918
1875
  if (endPos === start) {
1919
1876
  return;
@@ -1940,14 +1897,12 @@ export class MergeTree {
1940
1897
  return NodeAction.Skip;
1941
1898
  }
1942
1899
  if (node.isLeaf()) {
1943
- if (leaf(node, pos, refSeq, clientId, start - pos, endPos - pos, accum) === false) {
1900
+ if (leaf(node, pos, start - pos, endPos - pos) === false) {
1944
1901
  return NodeAction.Exit;
1945
1902
  }
1946
1903
  pos = nextPos;
1947
1904
  }
1948
- }, undefined, post === undefined
1949
- ? undefined
1950
- : (block) => post(block, pos, refSeq, clientId, start - pos, endPos - pos, accum));
1905
+ }, undefined, post);
1951
1906
  }
1952
1907
  }
1953
1908
  MergeTree.options = {