@fluidframework/merge-tree 2.0.0-rc.1.0.3 → 2.0.0-rc.2.0.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 (770) hide show
  1. package/{.eslintrc.js → .eslintrc.cjs} +4 -1
  2. package/{.mocharc.js → .mocharc.cjs} +1 -1
  3. package/CHANGELOG.md +4 -0
  4. package/api-extractor-cjs.json +8 -0
  5. package/api-extractor-lint.json +1 -1
  6. package/api-extractor.json +1 -9
  7. package/api-report/merge-tree.api.md +6 -12
  8. package/dist/MergeTreeTextHelper.d.ts +2 -2
  9. package/dist/MergeTreeTextHelper.d.ts.map +1 -1
  10. package/dist/MergeTreeTextHelper.js +3 -3
  11. package/dist/MergeTreeTextHelper.js.map +1 -1
  12. package/dist/attributionCollection.d.ts +1 -1
  13. package/dist/attributionCollection.d.ts.map +1 -1
  14. package/dist/attributionCollection.js.map +1 -1
  15. package/dist/attributionPolicy.d.ts +1 -1
  16. package/dist/attributionPolicy.d.ts.map +1 -1
  17. package/dist/attributionPolicy.js +15 -15
  18. package/dist/attributionPolicy.js.map +1 -1
  19. package/dist/client.d.ts +31 -12
  20. package/dist/client.d.ts.map +1 -1
  21. package/dist/client.js +103 -92
  22. package/dist/client.js.map +1 -1
  23. package/dist/collections/index.d.ts +2 -2
  24. package/dist/collections/index.d.ts.map +1 -1
  25. package/dist/collections/index.js +6 -6
  26. package/dist/collections/index.js.map +1 -1
  27. package/dist/endOfTreeSegment.d.ts +3 -3
  28. package/dist/endOfTreeSegment.d.ts.map +1 -1
  29. package/dist/endOfTreeSegment.js +8 -8
  30. package/dist/endOfTreeSegment.js.map +1 -1
  31. package/dist/index.d.ts +20 -20
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +71 -71
  34. package/dist/index.js.map +1 -1
  35. package/dist/localReference.d.ts +9 -39
  36. package/dist/localReference.d.ts.map +1 -1
  37. package/dist/localReference.js +29 -24
  38. package/dist/localReference.js.map +1 -1
  39. package/dist/merge-tree-alpha.d.ts +28 -450
  40. package/dist/merge-tree-beta.d.ts +0 -438
  41. package/dist/merge-tree-public.d.ts +0 -438
  42. package/dist/merge-tree-untrimmed.d.ts +28 -787
  43. package/dist/mergeTree.d.ts +11 -19
  44. package/dist/mergeTree.d.ts.map +1 -1
  45. package/dist/mergeTree.js +201 -189
  46. package/dist/mergeTree.js.map +1 -1
  47. package/dist/mergeTreeDeltaCallback.d.ts +3 -7
  48. package/dist/mergeTreeDeltaCallback.d.ts.map +1 -1
  49. package/dist/mergeTreeDeltaCallback.js.map +1 -1
  50. package/dist/mergeTreeNodeWalk.d.ts +1 -1
  51. package/dist/mergeTreeNodeWalk.d.ts.map +1 -1
  52. package/dist/mergeTreeNodeWalk.js.map +1 -1
  53. package/dist/mergeTreeNodes.d.ts +17 -14
  54. package/dist/mergeTreeNodes.d.ts.map +1 -1
  55. package/dist/mergeTreeNodes.js +32 -32
  56. package/dist/mergeTreeNodes.js.map +1 -1
  57. package/dist/mergeTreeTracking.d.ts +2 -2
  58. package/dist/mergeTreeTracking.d.ts.map +1 -1
  59. package/dist/mergeTreeTracking.js +2 -2
  60. package/dist/mergeTreeTracking.js.map +1 -1
  61. package/dist/opBuilder.d.ts +3 -3
  62. package/dist/opBuilder.d.ts.map +1 -1
  63. package/dist/opBuilder.js +7 -7
  64. package/dist/opBuilder.js.map +1 -1
  65. package/dist/package.json +3 -0
  66. package/dist/partialLengths.d.ts +5 -5
  67. package/dist/partialLengths.d.ts.map +1 -1
  68. package/dist/partialLengths.js +29 -29
  69. package/dist/partialLengths.js.map +1 -1
  70. package/dist/referencePositions.d.ts +4 -4
  71. package/dist/referencePositions.d.ts.map +1 -1
  72. package/dist/referencePositions.js +2 -2
  73. package/dist/referencePositions.js.map +1 -1
  74. package/dist/revertibles.d.ts +7 -7
  75. package/dist/revertibles.d.ts.map +1 -1
  76. package/dist/revertibles.js +39 -39
  77. package/dist/revertibles.js.map +1 -1
  78. package/dist/segmentGroupCollection.d.ts +1 -1
  79. package/dist/segmentGroupCollection.d.ts.map +1 -1
  80. package/dist/segmentGroupCollection.js +3 -3
  81. package/dist/segmentGroupCollection.js.map +1 -1
  82. package/dist/segmentPropertiesManager.d.ts +2 -2
  83. package/dist/segmentPropertiesManager.d.ts.map +1 -1
  84. package/dist/segmentPropertiesManager.js +8 -8
  85. package/dist/segmentPropertiesManager.js.map +1 -1
  86. package/dist/snapshotChunks.d.ts +3 -3
  87. package/dist/snapshotChunks.d.ts.map +1 -1
  88. package/dist/snapshotChunks.js +5 -5
  89. package/dist/snapshotChunks.js.map +1 -1
  90. package/dist/snapshotLoader.d.ts +3 -3
  91. package/dist/snapshotLoader.d.ts.map +1 -1
  92. package/dist/snapshotLoader.js +19 -19
  93. package/dist/snapshotLoader.js.map +1 -1
  94. package/dist/snapshotV1.d.ts +3 -3
  95. package/dist/snapshotV1.d.ts.map +1 -1
  96. package/dist/snapshotV1.js +35 -18
  97. package/dist/snapshotV1.js.map +1 -1
  98. package/dist/snapshotlegacy.d.ts +2 -2
  99. package/dist/snapshotlegacy.d.ts.map +1 -1
  100. package/dist/snapshotlegacy.js +22 -10
  101. package/dist/snapshotlegacy.js.map +1 -1
  102. package/dist/sortedSegmentSet.d.ts +3 -3
  103. package/dist/sortedSegmentSet.d.ts.map +1 -1
  104. package/dist/sortedSegmentSet.js +7 -5
  105. package/dist/sortedSegmentSet.js.map +1 -1
  106. package/dist/test/Insertion.perf.spec.js +15 -15
  107. package/dist/test/Insertion.perf.spec.js.map +1 -1
  108. package/dist/test/PartialLengths.perf.spec.js +13 -13
  109. package/dist/test/PartialLengths.perf.spec.js.map +1 -1
  110. package/dist/test/Removal.perf.spec.js +25 -25
  111. package/dist/test/Removal.perf.spec.js.map +1 -1
  112. package/dist/test/Snapshot.perf.spec.js +3 -3
  113. package/dist/test/Snapshot.perf.spec.js.map +1 -1
  114. package/dist/test/attributionCollection.perf.spec.js +9 -9
  115. package/dist/test/attributionCollection.perf.spec.js.map +1 -1
  116. package/dist/test/attributionCollection.spec.js +46 -46
  117. package/dist/test/attributionCollection.spec.js.map +1 -1
  118. package/dist/test/attributionPolicy.spec.js +13 -13
  119. package/dist/test/attributionPolicy.spec.js.map +1 -1
  120. package/dist/test/{beastTest.d.ts → beastTest.spec.d.ts} +3 -3
  121. package/dist/test/beastTest.spec.d.ts.map +1 -0
  122. package/dist/test/{beastTest.js → beastTest.spec.js} +120 -119
  123. package/dist/test/beastTest.spec.js.map +1 -0
  124. package/dist/test/client.annotateMarker.spec.js +13 -13
  125. package/dist/test/client.annotateMarker.spec.js.map +1 -1
  126. package/dist/test/{client.apis.d.ts → client.apis.spec.d.ts} +1 -1
  127. package/dist/test/client.apis.spec.d.ts.map +1 -0
  128. package/dist/test/{client.apis.js → client.apis.spec.js} +8 -8
  129. package/dist/test/client.apis.spec.js.map +1 -0
  130. package/dist/test/client.applyMsg.spec.js +106 -43
  131. package/dist/test/client.applyMsg.spec.js.map +1 -1
  132. package/dist/test/client.applyStashedOpFarm.spec.d.ts +1 -1
  133. package/dist/test/client.applyStashedOpFarm.spec.d.ts.map +1 -1
  134. package/dist/test/client.applyStashedOpFarm.spec.js +33 -21
  135. package/dist/test/client.applyStashedOpFarm.spec.js.map +1 -1
  136. package/dist/test/client.attributionFarm.spec.d.ts +1 -1
  137. package/dist/test/client.attributionFarm.spec.d.ts.map +1 -1
  138. package/dist/test/client.attributionFarm.spec.js +13 -13
  139. package/dist/test/client.attributionFarm.spec.js.map +1 -1
  140. package/dist/test/client.conflictFarm.spec.d.ts +1 -1
  141. package/dist/test/client.conflictFarm.spec.d.ts.map +1 -1
  142. package/dist/test/client.conflictFarm.spec.js +9 -9
  143. package/dist/test/client.conflictFarm.spec.js.map +1 -1
  144. package/dist/test/client.getPosition.spec.js +4 -4
  145. package/dist/test/client.getPosition.spec.js.map +1 -1
  146. package/dist/test/client.localReference.spec.js +140 -109
  147. package/dist/test/client.localReference.spec.js.map +1 -1
  148. package/dist/test/client.localReferenceFarm.spec.js +18 -18
  149. package/dist/test/client.localReferenceFarm.spec.js.map +1 -1
  150. package/dist/test/client.rebasePosition.spec.js +2 -2
  151. package/dist/test/client.rebasePosition.spec.js.map +1 -1
  152. package/dist/test/client.reconnectFarm.spec.d.ts +1 -1
  153. package/dist/test/client.reconnectFarm.spec.d.ts.map +1 -1
  154. package/dist/test/client.reconnectFarm.spec.js +10 -10
  155. package/dist/test/client.reconnectFarm.spec.js.map +1 -1
  156. package/dist/test/client.replay.spec.js +11 -11
  157. package/dist/test/client.replay.spec.js.map +1 -1
  158. package/dist/test/client.rollback.spec.js +83 -83
  159. package/dist/test/client.rollback.spec.js.map +1 -1
  160. package/dist/test/client.rollbackFarm.spec.js +9 -9
  161. package/dist/test/client.rollbackFarm.spec.js.map +1 -1
  162. package/dist/test/client.searchForMarker.spec.js +137 -137
  163. package/dist/test/client.searchForMarker.spec.js.map +1 -1
  164. package/dist/test/client.walkSegments.spec.js +2 -2
  165. package/dist/test/client.walkSegments.spec.js.map +1 -1
  166. package/dist/test/collections.list.spec.js +4 -4
  167. package/dist/test/collections.list.spec.js.map +1 -1
  168. package/dist/test/createInsertOnlyAttributionPolicy.spec.js +4 -4
  169. package/dist/test/createInsertOnlyAttributionPolicy.spec.js.map +1 -1
  170. package/dist/test/dirname.cjs +16 -0
  171. package/dist/test/dirname.cjs.map +1 -0
  172. package/dist/test/dirname.d.cts +6 -0
  173. package/dist/test/dirname.d.cts.map +1 -0
  174. package/dist/test/index.d.ts +8 -8
  175. package/dist/test/index.d.ts.map +1 -1
  176. package/dist/test/index.js +82 -81
  177. package/dist/test/index.js.map +1 -1
  178. package/dist/test/mergeTree.annotate.deltaCallback.spec.js +39 -39
  179. package/dist/test/mergeTree.annotate.deltaCallback.spec.js.map +1 -1
  180. package/dist/test/mergeTree.annotate.spec.js +39 -39
  181. package/dist/test/mergeTree.annotate.spec.js.map +1 -1
  182. package/dist/test/mergeTree.insert.deltaCallback.spec.js +35 -35
  183. package/dist/test/mergeTree.insert.deltaCallback.spec.js.map +1 -1
  184. package/dist/test/mergeTree.insertingWalk.spec.js +77 -77
  185. package/dist/test/mergeTree.insertingWalk.spec.js.map +1 -1
  186. package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +42 -42
  187. package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -1
  188. package/dist/test/mergeTree.markRangeRemoved.spec.js +15 -15
  189. package/dist/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
  190. package/dist/test/mergeTree.walk.spec.js +14 -14
  191. package/dist/test/mergeTree.walk.spec.js.map +1 -1
  192. package/dist/test/mergeTree.zamboni.spec.js +9 -9
  193. package/dist/test/mergeTree.zamboni.spec.js.map +1 -1
  194. package/dist/test/mergeTreeOperationRunner.d.ts +4 -4
  195. package/dist/test/mergeTreeOperationRunner.d.ts.map +1 -1
  196. package/dist/test/mergeTreeOperationRunner.js +16 -15
  197. package/dist/test/mergeTreeOperationRunner.js.map +1 -1
  198. package/dist/test/mergeTreeOperationRunner.spec.js +5 -5
  199. package/dist/test/mergeTreeOperationRunner.spec.js.map +1 -1
  200. package/dist/test/obliterate.concurrent.spec.js +85 -88
  201. package/dist/test/obliterate.concurrent.spec.js.map +1 -1
  202. package/dist/test/obliterate.deltaCallback.spec.d.ts +6 -0
  203. package/dist/test/obliterate.deltaCallback.spec.d.ts.map +1 -0
  204. package/dist/test/obliterate.deltaCallback.spec.js +146 -0
  205. package/dist/test/obliterate.deltaCallback.spec.js.map +1 -0
  206. package/dist/test/obliterate.partialLength.spec.js +39 -44
  207. package/dist/test/obliterate.partialLength.spec.js.map +1 -1
  208. package/dist/test/obliterate.reconnect.spec.js +15 -18
  209. package/dist/test/obliterate.reconnect.spec.js.map +1 -1
  210. package/dist/test/obliterate.spec.js +16 -16
  211. package/dist/test/obliterate.spec.js.map +1 -1
  212. package/dist/test/ordinal.spec.js +5 -5
  213. package/dist/test/ordinal.spec.js.map +1 -1
  214. package/dist/test/partialLength.spec.js +58 -64
  215. package/dist/test/partialLength.spec.js.map +1 -1
  216. package/dist/test/properties.spec.js +15 -15
  217. package/dist/test/properties.spec.js.map +1 -1
  218. package/dist/test/reconnectHelper.d.ts +8 -8
  219. package/dist/test/reconnectHelper.d.ts.map +1 -1
  220. package/dist/test/reconnectHelper.js +3 -3
  221. package/dist/test/reconnectHelper.js.map +1 -1
  222. package/dist/test/resetPendingSegmentsToOp.spec.js +18 -18
  223. package/dist/test/resetPendingSegmentsToOp.spec.js.map +1 -1
  224. package/dist/test/revertibleFarm.spec.js +21 -21
  225. package/dist/test/revertibleFarm.spec.js.map +1 -1
  226. package/dist/test/revertibles.spec.js +67 -67
  227. package/dist/test/revertibles.spec.js.map +1 -1
  228. package/dist/test/segmentGroupCollection.spec.js +3 -3
  229. package/dist/test/segmentGroupCollection.spec.js.map +1 -1
  230. package/dist/test/snapshot.spec.js +16 -16
  231. package/dist/test/snapshot.spec.js.map +1 -1
  232. package/dist/test/snapshot.utils.d.ts +4 -4
  233. package/dist/test/snapshot.utils.d.ts.map +1 -1
  234. package/dist/test/snapshot.utils.js +11 -11
  235. package/dist/test/snapshot.utils.js.map +1 -1
  236. package/dist/test/snapshotlegacy.spec.js +22 -22
  237. package/dist/test/snapshotlegacy.spec.js.map +1 -1
  238. package/dist/test/sortedSegmentSet.spec.js +9 -9
  239. package/dist/test/sortedSegmentSet.spec.js.map +1 -1
  240. package/dist/test/testClient.d.ts +13 -16
  241. package/dist/test/testClient.d.ts.map +1 -1
  242. package/dist/test/testClient.js +57 -59
  243. package/dist/test/testClient.js.map +1 -1
  244. package/dist/test/testClientLogger.d.ts +3 -3
  245. package/dist/test/testClientLogger.d.ts.map +1 -1
  246. package/dist/test/testClientLogger.js +19 -19
  247. package/dist/test/testClientLogger.js.map +1 -1
  248. package/dist/test/testServer.d.ts +3 -3
  249. package/dist/test/testServer.d.ts.map +1 -1
  250. package/dist/test/testServer.js +8 -8
  251. package/dist/test/testServer.js.map +1 -1
  252. package/dist/test/testUtils.d.ts +14 -6
  253. package/dist/test/testUtils.d.ts.map +1 -1
  254. package/dist/test/testUtils.js +36 -17
  255. package/dist/test/testUtils.js.map +1 -1
  256. package/dist/test/text.d.ts +2 -2
  257. package/dist/test/text.d.ts.map +1 -1
  258. package/dist/test/text.js +10 -10
  259. package/dist/test/text.js.map +1 -1
  260. package/dist/test/tracking.spec.js +12 -12
  261. package/dist/test/tracking.spec.js.map +1 -1
  262. package/dist/test/{wordUnitTests.d.ts → wordUnitTests.spec.d.ts} +1 -1
  263. package/dist/test/wordUnitTests.spec.d.ts.map +1 -0
  264. package/dist/test/{wordUnitTests.js → wordUnitTests.spec.js} +16 -15
  265. package/dist/test/wordUnitTests.spec.js.map +1 -0
  266. package/dist/textSegment.d.ts +3 -3
  267. package/dist/textSegment.d.ts.map +1 -1
  268. package/dist/textSegment.js +2 -2
  269. package/dist/textSegment.js.map +1 -1
  270. package/dist/tsdoc-metadata.json +1 -1
  271. package/dist/zamboni.d.ts +2 -2
  272. package/dist/zamboni.d.ts.map +1 -1
  273. package/dist/zamboni.js +19 -19
  274. package/dist/zamboni.js.map +1 -1
  275. package/lib/{MergeTreeTextHelper.d.mts → MergeTreeTextHelper.d.ts} +3 -3
  276. package/lib/MergeTreeTextHelper.d.ts.map +1 -0
  277. package/lib/{MergeTreeTextHelper.mjs → MergeTreeTextHelper.js} +3 -2
  278. package/lib/MergeTreeTextHelper.js.map +1 -0
  279. package/lib/{attributionCollection.d.mts → attributionCollection.d.ts} +2 -2
  280. package/lib/attributionCollection.d.ts.map +1 -0
  281. package/lib/{attributionCollection.mjs → attributionCollection.js} +1 -1
  282. package/lib/attributionCollection.js.map +1 -0
  283. package/lib/{attributionPolicy.d.mts → attributionPolicy.d.ts} +2 -2
  284. package/lib/attributionPolicy.d.ts.map +1 -0
  285. package/lib/{attributionPolicy.mjs → attributionPolicy.js} +4 -4
  286. package/lib/attributionPolicy.js.map +1 -0
  287. package/lib/{client.d.mts → client.d.ts} +32 -13
  288. package/lib/client.d.ts.map +1 -0
  289. package/lib/{client.mjs → client.js} +42 -31
  290. package/lib/client.js.map +1 -0
  291. package/lib/collections/{index.d.mts → index.d.ts} +3 -3
  292. package/lib/collections/index.d.ts.map +1 -0
  293. package/lib/collections/index.js +7 -0
  294. package/lib/collections/index.js.map +1 -0
  295. package/lib/collections/{list.d.mts → list.d.ts} +1 -1
  296. package/lib/collections/list.d.ts.map +1 -0
  297. package/lib/collections/{list.mjs → list.js} +1 -1
  298. package/lib/collections/list.js.map +1 -0
  299. package/lib/collections/{rbTree.d.mts → rbTree.d.ts} +1 -1
  300. package/lib/collections/rbTree.d.ts.map +1 -0
  301. package/lib/collections/{rbTree.mjs → rbTree.js} +1 -1
  302. package/lib/collections/rbTree.js.map +1 -0
  303. package/lib/{constants.d.mts → constants.d.ts} +1 -1
  304. package/lib/constants.d.ts.map +1 -0
  305. package/lib/{constants.mjs → constants.js} +1 -1
  306. package/lib/constants.js.map +1 -0
  307. package/lib/{endOfTreeSegment.d.mts → endOfTreeSegment.d.ts} +4 -4
  308. package/lib/endOfTreeSegment.d.ts.map +1 -0
  309. package/lib/{endOfTreeSegment.mjs → endOfTreeSegment.js} +3 -3
  310. package/lib/endOfTreeSegment.js.map +1 -0
  311. package/lib/{index.d.mts → index.d.ts} +21 -21
  312. package/lib/index.d.ts.map +1 -0
  313. package/lib/{index.mjs → index.js} +20 -20
  314. package/lib/index.js.map +1 -0
  315. package/lib/{localReference.d.mts → localReference.d.ts} +10 -40
  316. package/lib/localReference.d.ts.map +1 -0
  317. package/lib/{localReference.mjs → localReference.js} +12 -6
  318. package/lib/localReference.js.map +1 -0
  319. package/lib/{merge-tree-alpha.d.mts → merge-tree-alpha.d.ts} +28 -450
  320. package/lib/merge-tree-beta.d.ts +230 -0
  321. package/lib/merge-tree-public.d.ts +230 -0
  322. package/lib/{merge-tree-untrimmed.d.mts → merge-tree-untrimmed.d.ts} +28 -787
  323. package/lib/{mergeTree.d.mts → mergeTree.d.ts} +12 -20
  324. package/lib/mergeTree.d.ts.map +1 -0
  325. package/lib/{mergeTree.mjs → mergeTree.js} +47 -32
  326. package/lib/mergeTree.js.map +1 -0
  327. package/lib/{mergeTreeDeltaCallback.d.mts → mergeTreeDeltaCallback.d.ts} +8 -8
  328. package/lib/mergeTreeDeltaCallback.d.ts.map +1 -0
  329. package/lib/{mergeTreeDeltaCallback.mjs → mergeTreeDeltaCallback.js} +1 -1
  330. package/lib/mergeTreeDeltaCallback.js.map +1 -0
  331. package/lib/{mergeTreeNodeWalk.d.mts → mergeTreeNodeWalk.d.ts} +2 -2
  332. package/lib/mergeTreeNodeWalk.d.ts.map +1 -0
  333. package/lib/{mergeTreeNodeWalk.mjs → mergeTreeNodeWalk.js} +1 -1
  334. package/lib/mergeTreeNodeWalk.js.map +1 -0
  335. package/lib/{mergeTreeNodes.d.mts → mergeTreeNodes.d.ts} +18 -15
  336. package/lib/mergeTreeNodes.d.ts.map +1 -0
  337. package/lib/{mergeTreeNodes.mjs → mergeTreeNodes.js} +12 -10
  338. package/lib/mergeTreeNodes.js.map +1 -0
  339. package/lib/{mergeTreeTracking.d.mts → mergeTreeTracking.d.ts} +3 -3
  340. package/lib/mergeTreeTracking.d.ts.map +1 -0
  341. package/lib/{mergeTreeTracking.mjs → mergeTreeTracking.js} +3 -2
  342. package/lib/mergeTreeTracking.js.map +1 -0
  343. package/lib/{opBuilder.d.mts → opBuilder.d.ts} +4 -4
  344. package/lib/{opBuilder.d.mts.map → opBuilder.d.ts.map} +1 -1
  345. package/lib/{opBuilder.mjs → opBuilder.js} +2 -2
  346. package/lib/opBuilder.js.map +1 -0
  347. package/lib/{ops.d.mts → ops.d.ts} +1 -1
  348. package/lib/ops.d.ts.map +1 -0
  349. package/lib/{ops.mjs → ops.js} +1 -1
  350. package/lib/ops.js.map +1 -0
  351. package/lib/{ordinal.d.mts → ordinal.d.ts} +1 -1
  352. package/lib/ordinal.d.ts.map +1 -0
  353. package/lib/{ordinal.mjs → ordinal.js} +2 -1
  354. package/lib/ordinal.js.map +1 -0
  355. package/lib/{partialLengths.d.mts → partialLengths.d.ts} +6 -6
  356. package/lib/partialLengths.d.ts.map +1 -0
  357. package/lib/{partialLengths.mjs → partialLengths.js} +11 -10
  358. package/lib/partialLengths.js.map +1 -0
  359. package/lib/{properties.d.mts → properties.d.ts} +1 -1
  360. package/lib/properties.d.ts.map +1 -0
  361. package/lib/{properties.mjs → properties.js} +1 -1
  362. package/lib/properties.js.map +1 -0
  363. package/lib/{referencePositions.d.mts → referencePositions.d.ts} +5 -5
  364. package/lib/referencePositions.d.ts.map +1 -0
  365. package/lib/{referencePositions.mjs → referencePositions.js} +2 -2
  366. package/lib/referencePositions.js.map +1 -0
  367. package/lib/{revertibles.d.mts → revertibles.d.ts} +8 -8
  368. package/lib/revertibles.d.ts.map +1 -0
  369. package/lib/{revertibles.mjs → revertibles.js} +13 -13
  370. package/lib/revertibles.js.map +1 -0
  371. package/lib/{segmentGroupCollection.d.mts → segmentGroupCollection.d.ts} +2 -2
  372. package/lib/segmentGroupCollection.d.ts.map +1 -0
  373. package/lib/{segmentGroupCollection.mjs → segmentGroupCollection.js} +2 -2
  374. package/lib/segmentGroupCollection.js.map +1 -0
  375. package/lib/{segmentPropertiesManager.d.mts → segmentPropertiesManager.d.ts} +3 -3
  376. package/lib/segmentPropertiesManager.d.ts.map +1 -0
  377. package/lib/{segmentPropertiesManager.mjs → segmentPropertiesManager.js} +5 -3
  378. package/lib/segmentPropertiesManager.js.map +1 -0
  379. package/lib/{snapshotChunks.d.mts → snapshotChunks.d.ts} +4 -4
  380. package/lib/snapshotChunks.d.ts.map +1 -0
  381. package/lib/{snapshotChunks.mjs → snapshotChunks.js} +2 -2
  382. package/lib/snapshotChunks.js.map +1 -0
  383. package/lib/{snapshotLoader.d.mts → snapshotLoader.d.ts} +4 -4
  384. package/lib/snapshotLoader.d.ts.map +1 -0
  385. package/lib/{snapshotLoader.mjs → snapshotLoader.js} +10 -9
  386. package/lib/snapshotLoader.js.map +1 -0
  387. package/lib/{snapshotV1.d.mts → snapshotV1.d.ts} +4 -4
  388. package/lib/snapshotV1.d.ts.map +1 -0
  389. package/lib/{snapshotV1.mjs → snapshotV1.js} +24 -7
  390. package/lib/snapshotV1.js.map +1 -0
  391. package/lib/{snapshotlegacy.d.mts → snapshotlegacy.d.ts} +3 -3
  392. package/lib/snapshotlegacy.d.ts.map +1 -0
  393. package/lib/{snapshotlegacy.mjs → snapshotlegacy.js} +17 -4
  394. package/lib/snapshotlegacy.js.map +1 -0
  395. package/lib/{sortedSegmentSet.d.mts → sortedSegmentSet.d.ts} +4 -4
  396. package/lib/sortedSegmentSet.d.ts.map +1 -0
  397. package/lib/{sortedSegmentSet.mjs → sortedSegmentSet.js} +8 -5
  398. package/lib/sortedSegmentSet.js.map +1 -0
  399. package/lib/{sortedSet.d.mts → sortedSet.d.ts} +1 -1
  400. package/lib/sortedSet.d.ts.map +1 -0
  401. package/lib/{sortedSet.mjs → sortedSet.js} +1 -1
  402. package/lib/sortedSet.js.map +1 -0
  403. package/lib/test/Insertion.perf.spec.d.ts +6 -0
  404. package/lib/test/Insertion.perf.spec.d.ts.map +1 -0
  405. package/lib/test/Insertion.perf.spec.js +111 -0
  406. package/lib/test/Insertion.perf.spec.js.map +1 -0
  407. package/lib/test/PartialLengths.perf.spec.d.ts +6 -0
  408. package/lib/test/PartialLengths.perf.spec.d.ts.map +1 -0
  409. package/lib/test/PartialLengths.perf.spec.js +65 -0
  410. package/lib/test/PartialLengths.perf.spec.js.map +1 -0
  411. package/lib/test/Removal.perf.spec.d.ts +6 -0
  412. package/lib/test/Removal.perf.spec.d.ts.map +1 -0
  413. package/lib/test/Removal.perf.spec.js +164 -0
  414. package/lib/test/Removal.perf.spec.js.map +1 -0
  415. package/lib/test/Snapshot.perf.spec.d.ts +6 -0
  416. package/lib/test/Snapshot.perf.spec.d.ts.map +1 -0
  417. package/lib/test/Snapshot.perf.spec.js +31 -0
  418. package/lib/test/Snapshot.perf.spec.js.map +1 -0
  419. package/lib/test/attributionCollection.perf.spec.d.ts +6 -0
  420. package/lib/test/attributionCollection.perf.spec.d.ts.map +1 -0
  421. package/lib/test/attributionCollection.perf.spec.js +229 -0
  422. package/lib/test/attributionCollection.perf.spec.js.map +1 -0
  423. package/lib/test/attributionCollection.spec.d.ts +6 -0
  424. package/lib/test/attributionCollection.spec.d.ts.map +1 -0
  425. package/lib/test/attributionCollection.spec.js +484 -0
  426. package/lib/test/attributionCollection.spec.js.map +1 -0
  427. package/lib/test/attributionPolicy.spec.d.ts +6 -0
  428. package/lib/test/attributionPolicy.spec.d.ts.map +1 -0
  429. package/lib/test/attributionPolicy.spec.js +187 -0
  430. package/lib/test/attributionPolicy.spec.js.map +1 -0
  431. package/lib/test/beastTest.spec.d.ts +54 -0
  432. package/lib/test/beastTest.spec.d.ts.map +1 -0
  433. package/lib/test/beastTest.spec.js +1318 -0
  434. package/lib/test/beastTest.spec.js.map +1 -0
  435. package/lib/test/client.annotateMarker.spec.d.ts +6 -0
  436. package/lib/test/client.annotateMarker.spec.d.ts.map +1 -0
  437. package/lib/test/client.annotateMarker.spec.js +43 -0
  438. package/lib/test/client.annotateMarker.spec.js.map +1 -0
  439. package/lib/test/client.apis.spec.d.ts +7 -0
  440. package/lib/test/client.apis.spec.d.ts.map +1 -0
  441. package/lib/test/client.apis.spec.js +67 -0
  442. package/lib/test/client.apis.spec.js.map +1 -0
  443. package/lib/test/client.applyMsg.spec.d.ts +6 -0
  444. package/lib/test/client.applyMsg.spec.d.ts.map +1 -0
  445. package/lib/test/client.applyMsg.spec.js +561 -0
  446. package/lib/test/client.applyMsg.spec.js.map +1 -0
  447. package/lib/test/client.applyStashedOpFarm.spec.d.ts +12 -0
  448. package/lib/test/client.applyStashedOpFarm.spec.d.ts.map +1 -0
  449. package/lib/test/client.applyStashedOpFarm.spec.js +153 -0
  450. package/lib/test/client.applyStashedOpFarm.spec.js.map +1 -0
  451. package/lib/test/client.attributionFarm.spec.d.ts +7 -0
  452. package/lib/test/client.attributionFarm.spec.d.ts.map +1 -0
  453. package/lib/test/client.attributionFarm.spec.js +92 -0
  454. package/lib/test/client.attributionFarm.spec.js.map +1 -0
  455. package/lib/test/client.conflictFarm.spec.d.ts +15 -0
  456. package/lib/test/client.conflictFarm.spec.d.ts.map +1 -0
  457. package/lib/test/client.conflictFarm.spec.js +85 -0
  458. package/lib/test/client.conflictFarm.spec.js.map +1 -0
  459. package/lib/test/client.getPosition.spec.d.ts +6 -0
  460. package/lib/test/client.getPosition.spec.d.ts.map +1 -0
  461. package/lib/test/client.getPosition.spec.js +52 -0
  462. package/lib/test/client.getPosition.spec.js.map +1 -0
  463. package/lib/test/client.localReference.spec.d.ts +6 -0
  464. package/lib/test/client.localReference.spec.d.ts.map +1 -0
  465. package/lib/test/client.localReference.spec.js +468 -0
  466. package/lib/test/client.localReference.spec.js.map +1 -0
  467. package/lib/test/client.localReferenceFarm.spec.d.ts +6 -0
  468. package/lib/test/client.localReferenceFarm.spec.d.ts.map +1 -0
  469. package/lib/test/client.localReferenceFarm.spec.js +86 -0
  470. package/lib/test/client.localReferenceFarm.spec.js.map +1 -0
  471. package/lib/test/client.rebasePosition.spec.d.ts +6 -0
  472. package/lib/test/client.rebasePosition.spec.d.ts.map +1 -0
  473. package/lib/test/client.rebasePosition.spec.js +100 -0
  474. package/lib/test/client.rebasePosition.spec.js.map +1 -0
  475. package/lib/test/client.reconnectFarm.spec.d.ts +12 -0
  476. package/lib/test/client.reconnectFarm.spec.d.ts.map +1 -0
  477. package/lib/test/client.reconnectFarm.spec.js +88 -0
  478. package/lib/test/client.reconnectFarm.spec.js.map +1 -0
  479. package/lib/test/client.replay.spec.d.ts +6 -0
  480. package/lib/test/client.replay.spec.d.ts.map +1 -0
  481. package/lib/test/client.replay.spec.js +57 -0
  482. package/lib/test/client.replay.spec.js.map +1 -0
  483. package/lib/test/client.rollback.spec.d.ts +6 -0
  484. package/lib/test/client.rollback.spec.d.ts.map +1 -0
  485. package/lib/test/client.rollback.spec.js +451 -0
  486. package/lib/test/client.rollback.spec.js.map +1 -0
  487. package/lib/test/client.rollbackFarm.spec.d.ts +6 -0
  488. package/lib/test/client.rollbackFarm.spec.d.ts.map +1 -0
  489. package/lib/test/client.rollbackFarm.spec.js +46 -0
  490. package/lib/test/client.rollbackFarm.spec.js.map +1 -0
  491. package/lib/test/client.searchForMarker.spec.d.ts +6 -0
  492. package/lib/test/client.searchForMarker.spec.d.ts.map +1 -0
  493. package/lib/test/client.searchForMarker.spec.js +495 -0
  494. package/lib/test/client.searchForMarker.spec.js.map +1 -0
  495. package/lib/test/client.walkSegments.spec.d.ts +6 -0
  496. package/lib/test/client.walkSegments.spec.d.ts.map +1 -0
  497. package/lib/test/client.walkSegments.spec.js +52 -0
  498. package/lib/test/client.walkSegments.spec.js.map +1 -0
  499. package/lib/test/collections.list.spec.d.ts +6 -0
  500. package/lib/test/collections.list.spec.d.ts.map +1 -0
  501. package/lib/test/collections.list.spec.js +82 -0
  502. package/lib/test/collections.list.spec.js.map +1 -0
  503. package/lib/test/createInsertOnlyAttributionPolicy.spec.d.ts +6 -0
  504. package/lib/test/createInsertOnlyAttributionPolicy.spec.d.ts.map +1 -0
  505. package/lib/test/createInsertOnlyAttributionPolicy.spec.js +33 -0
  506. package/lib/test/createInsertOnlyAttributionPolicy.spec.js.map +1 -0
  507. package/lib/test/dirname.cjs +16 -0
  508. package/lib/test/dirname.cjs.map +1 -0
  509. package/lib/test/dirname.d.cts +6 -0
  510. package/lib/test/dirname.d.cts.map +1 -0
  511. package/lib/test/index.d.ts +13 -0
  512. package/lib/test/index.d.ts.map +1 -0
  513. package/lib/test/index.js +13 -0
  514. package/lib/test/index.js.map +1 -0
  515. package/lib/test/mergeTree.annotate.deltaCallback.spec.d.ts +6 -0
  516. package/lib/test/mergeTree.annotate.deltaCallback.spec.d.ts.map +1 -0
  517. package/lib/test/mergeTree.annotate.deltaCallback.spec.js +140 -0
  518. package/lib/test/mergeTree.annotate.deltaCallback.spec.js.map +1 -0
  519. package/lib/test/mergeTree.annotate.spec.d.ts +6 -0
  520. package/lib/test/mergeTree.annotate.spec.d.ts.map +1 -0
  521. package/lib/test/mergeTree.annotate.spec.js +446 -0
  522. package/lib/test/mergeTree.annotate.spec.js.map +1 -0
  523. package/lib/test/mergeTree.insert.deltaCallback.spec.d.ts +6 -0
  524. package/lib/test/mergeTree.insert.deltaCallback.spec.d.ts.map +1 -0
  525. package/lib/test/mergeTree.insert.deltaCallback.spec.js +124 -0
  526. package/lib/test/mergeTree.insert.deltaCallback.spec.js.map +1 -0
  527. package/lib/test/mergeTree.insertingWalk.spec.d.ts +6 -0
  528. package/lib/test/mergeTree.insertingWalk.spec.d.ts.map +1 -0
  529. package/lib/test/mergeTree.insertingWalk.spec.js +277 -0
  530. package/lib/test/mergeTree.insertingWalk.spec.js.map +1 -0
  531. package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.d.ts +6 -0
  532. package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.d.ts.map +1 -0
  533. package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +176 -0
  534. package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -0
  535. package/lib/test/mergeTree.markRangeRemoved.spec.d.ts +6 -0
  536. package/lib/test/mergeTree.markRangeRemoved.spec.d.ts.map +1 -0
  537. package/lib/test/mergeTree.markRangeRemoved.spec.js +128 -0
  538. package/lib/test/mergeTree.markRangeRemoved.spec.js.map +1 -0
  539. package/lib/test/mergeTree.walk.spec.d.ts +6 -0
  540. package/lib/test/mergeTree.walk.spec.d.ts.map +1 -0
  541. package/lib/test/mergeTree.walk.spec.js +61 -0
  542. package/lib/test/mergeTree.walk.spec.js.map +1 -0
  543. package/lib/test/mergeTree.zamboni.spec.d.ts +6 -0
  544. package/lib/test/mergeTree.zamboni.spec.d.ts.map +1 -0
  545. package/lib/test/mergeTree.zamboni.spec.js +50 -0
  546. package/lib/test/mergeTree.zamboni.spec.js.map +1 -0
  547. package/lib/test/mergeTreeOperationRunner.d.ts +63 -0
  548. package/lib/test/mergeTreeOperationRunner.d.ts.map +1 -0
  549. package/lib/test/mergeTreeOperationRunner.js +207 -0
  550. package/lib/test/mergeTreeOperationRunner.js.map +1 -0
  551. package/lib/test/mergeTreeOperationRunner.spec.d.ts +6 -0
  552. package/lib/test/mergeTreeOperationRunner.spec.d.ts.map +1 -0
  553. package/lib/test/mergeTreeOperationRunner.spec.js +154 -0
  554. package/lib/test/mergeTreeOperationRunner.spec.js.map +1 -0
  555. package/lib/test/obliterate.concurrent.spec.d.ts +6 -0
  556. package/lib/test/obliterate.concurrent.spec.d.ts.map +1 -0
  557. package/lib/test/obliterate.concurrent.spec.js +1441 -0
  558. package/lib/test/obliterate.concurrent.spec.js.map +1 -0
  559. package/lib/test/obliterate.deltaCallback.spec.d.ts +6 -0
  560. package/lib/test/obliterate.deltaCallback.spec.d.ts.map +1 -0
  561. package/lib/test/obliterate.deltaCallback.spec.js +144 -0
  562. package/lib/test/obliterate.deltaCallback.spec.js.map +1 -0
  563. package/lib/test/obliterate.partialLength.spec.d.ts +6 -0
  564. package/lib/test/obliterate.partialLength.spec.d.ts.map +1 -0
  565. package/lib/test/obliterate.partialLength.spec.js +272 -0
  566. package/lib/test/obliterate.partialLength.spec.js.map +1 -0
  567. package/lib/test/obliterate.reconnect.spec.d.ts +6 -0
  568. package/lib/test/obliterate.reconnect.spec.d.ts.map +1 -0
  569. package/lib/test/obliterate.reconnect.spec.js +159 -0
  570. package/lib/test/obliterate.reconnect.spec.js.map +1 -0
  571. package/lib/test/obliterate.spec.d.ts +6 -0
  572. package/lib/test/obliterate.spec.d.ts.map +1 -0
  573. package/lib/test/obliterate.spec.js +160 -0
  574. package/lib/test/obliterate.spec.js.map +1 -0
  575. package/lib/test/ordinal.spec.d.ts +2 -0
  576. package/lib/test/ordinal.spec.d.ts.map +1 -0
  577. package/lib/test/ordinal.spec.js +38 -0
  578. package/lib/test/ordinal.spec.js.map +1 -0
  579. package/lib/test/partialLength.spec.d.ts +6 -0
  580. package/lib/test/partialLength.spec.d.ts.map +1 -0
  581. package/lib/test/partialLength.spec.js +274 -0
  582. package/lib/test/partialLength.spec.js.map +1 -0
  583. package/lib/test/properties.spec.d.ts +6 -0
  584. package/lib/test/properties.spec.d.ts.map +1 -0
  585. package/lib/test/properties.spec.js +53 -0
  586. package/lib/test/properties.spec.js.map +1 -0
  587. package/lib/test/reconnectHelper.d.ts +48 -0
  588. package/lib/test/reconnectHelper.d.ts.map +1 -0
  589. package/lib/test/reconnectHelper.js +82 -0
  590. package/lib/test/reconnectHelper.js.map +1 -0
  591. package/lib/test/resetPendingSegmentsToOp.spec.d.ts +6 -0
  592. package/lib/test/resetPendingSegmentsToOp.spec.d.ts.map +1 -0
  593. package/lib/test/resetPendingSegmentsToOp.spec.js +235 -0
  594. package/lib/test/resetPendingSegmentsToOp.spec.js.map +1 -0
  595. package/lib/test/revertibleFarm.spec.d.ts +6 -0
  596. package/lib/test/revertibleFarm.spec.d.ts.map +1 -0
  597. package/lib/test/revertibleFarm.spec.js +119 -0
  598. package/lib/test/revertibleFarm.spec.js.map +1 -0
  599. package/lib/test/revertibles.spec.d.ts +17 -0
  600. package/lib/test/revertibles.spec.d.ts.map +1 -0
  601. package/lib/test/revertibles.spec.js +381 -0
  602. package/lib/test/revertibles.spec.js.map +1 -0
  603. package/lib/test/segmentGroupCollection.spec.d.ts +6 -0
  604. package/lib/test/segmentGroupCollection.spec.d.ts.map +1 -0
  605. package/lib/test/segmentGroupCollection.spec.js +58 -0
  606. package/lib/test/segmentGroupCollection.spec.js.map +1 -0
  607. package/lib/test/snapshot.spec.d.ts +6 -0
  608. package/lib/test/snapshot.spec.d.ts.map +1 -0
  609. package/lib/test/snapshot.spec.js +176 -0
  610. package/lib/test/snapshot.spec.js.map +1 -0
  611. package/lib/test/snapshot.utils.d.ts +33 -0
  612. package/lib/test/snapshot.utils.d.ts.map +1 -0
  613. package/lib/test/snapshot.utils.js +104 -0
  614. package/lib/test/snapshot.utils.js.map +1 -0
  615. package/lib/test/snapshotlegacy.spec.d.ts +6 -0
  616. package/lib/test/snapshotlegacy.spec.d.ts.map +1 -0
  617. package/lib/test/snapshotlegacy.spec.js +137 -0
  618. package/lib/test/snapshotlegacy.spec.js.map +1 -0
  619. package/lib/test/sortedSegmentSet.spec.d.ts +6 -0
  620. package/lib/test/sortedSegmentSet.spec.d.ts.map +1 -0
  621. package/lib/test/sortedSegmentSet.spec.js +93 -0
  622. package/lib/test/sortedSegmentSet.spec.js.map +1 -0
  623. package/lib/test/testClient.d.ts +116 -0
  624. package/lib/test/testClient.d.ts.map +1 -0
  625. package/lib/test/testClient.js +430 -0
  626. package/lib/test/testClient.js.map +1 -0
  627. package/lib/test/testClientLogger.d.ts +44 -0
  628. package/lib/test/testClientLogger.d.ts.map +1 -0
  629. package/lib/test/testClientLogger.js +282 -0
  630. package/lib/test/testClientLogger.js.map +1 -0
  631. package/lib/test/testSerializer.d.ts +18 -0
  632. package/lib/test/testSerializer.d.ts.map +1 -0
  633. package/lib/test/testSerializer.js +29 -0
  634. package/lib/test/testSerializer.js.map +1 -0
  635. package/lib/test/testServer.d.ts +36 -0
  636. package/lib/test/testServer.d.ts.map +1 -0
  637. package/lib/test/testServer.js +133 -0
  638. package/lib/test/testServer.js.map +1 -0
  639. package/lib/test/testUtils.d.ts +77 -0
  640. package/lib/test/testUtils.d.ts.map +1 -0
  641. package/lib/test/testUtils.js +151 -0
  642. package/lib/test/testUtils.js.map +1 -0
  643. package/lib/test/text.d.ts +9 -0
  644. package/lib/test/text.d.ts.map +1 -0
  645. package/lib/test/text.js +71 -0
  646. package/lib/test/text.js.map +1 -0
  647. package/lib/test/tracking.spec.d.ts +6 -0
  648. package/lib/test/tracking.spec.d.ts.map +1 -0
  649. package/lib/test/tracking.spec.js +118 -0
  650. package/lib/test/tracking.spec.js.map +1 -0
  651. package/lib/test/types/validateMergeTreePrevious.generated.d.ts +2 -0
  652. package/lib/test/types/validateMergeTreePrevious.generated.d.ts.map +1 -0
  653. package/lib/test/types/validateMergeTreePrevious.generated.js +228 -0
  654. package/lib/test/types/validateMergeTreePrevious.generated.js.map +1 -0
  655. package/lib/test/wordUnitTests.spec.d.ts +6 -0
  656. package/lib/test/wordUnitTests.spec.d.ts.map +1 -0
  657. package/lib/test/wordUnitTests.spec.js +166 -0
  658. package/lib/test/wordUnitTests.spec.js.map +1 -0
  659. package/lib/{textSegment.d.mts → textSegment.d.ts} +4 -4
  660. package/lib/textSegment.d.ts.map +1 -0
  661. package/lib/{textSegment.mjs → textSegment.js} +2 -2
  662. package/lib/textSegment.js.map +1 -0
  663. package/lib/{zamboni.d.mts → zamboni.d.ts} +3 -3
  664. package/lib/zamboni.d.ts.map +1 -0
  665. package/lib/{zamboni.mjs → zamboni.js} +7 -6
  666. package/lib/zamboni.js.map +1 -0
  667. package/package.json +50 -57
  668. package/src/MergeTreeTextHelper.ts +4 -4
  669. package/src/attributionCollection.ts +1 -1
  670. package/src/attributionPolicy.ts +5 -5
  671. package/src/client.ts +50 -41
  672. package/src/collections/index.ts +2 -2
  673. package/src/endOfTreeSegment.ts +5 -5
  674. package/src/index.ts +20 -20
  675. package/src/localReference.ts +13 -7
  676. package/src/mergeTree.ts +53 -44
  677. package/src/mergeTreeDeltaCallback.ts +3 -8
  678. package/src/mergeTreeNodeWalk.ts +1 -1
  679. package/src/mergeTreeNodes.ts +21 -19
  680. package/src/mergeTreeTracking.ts +3 -3
  681. package/src/opBuilder.ts +3 -3
  682. package/src/partialLengths.ts +10 -10
  683. package/src/referencePositions.ts +4 -4
  684. package/src/revertibles.ts +14 -18
  685. package/src/segmentGroupCollection.ts +2 -2
  686. package/src/segmentPropertiesManager.ts +3 -3
  687. package/src/snapshotChunks.ts +4 -4
  688. package/src/snapshotLoader.ts +14 -11
  689. package/src/snapshotV1.ts +29 -9
  690. package/src/snapshotlegacy.ts +19 -5
  691. package/src/sortedSegmentSet.ts +8 -6
  692. package/src/textSegment.ts +3 -3
  693. package/src/zamboni.ts +7 -7
  694. package/tsconfig.cjs.json +7 -0
  695. package/tsconfig.json +2 -5
  696. package/api-extractor-esm.json +0 -17
  697. package/dist/test/beastTest.d.ts.map +0 -1
  698. package/dist/test/beastTest.js.map +0 -1
  699. package/dist/test/client.apis.d.ts.map +0 -1
  700. package/dist/test/client.apis.js.map +0 -1
  701. package/dist/test/wordUnitTests.d.ts.map +0 -1
  702. package/dist/test/wordUnitTests.js.map +0 -1
  703. package/lib/MergeTreeTextHelper.d.mts.map +0 -1
  704. package/lib/MergeTreeTextHelper.mjs.map +0 -1
  705. package/lib/attributionCollection.d.mts.map +0 -1
  706. package/lib/attributionCollection.mjs.map +0 -1
  707. package/lib/attributionPolicy.d.mts.map +0 -1
  708. package/lib/attributionPolicy.mjs.map +0 -1
  709. package/lib/client.d.mts.map +0 -1
  710. package/lib/client.mjs.map +0 -1
  711. package/lib/collections/index.d.mts.map +0 -1
  712. package/lib/collections/index.mjs +0 -7
  713. package/lib/collections/index.mjs.map +0 -1
  714. package/lib/collections/list.d.mts.map +0 -1
  715. package/lib/collections/list.mjs.map +0 -1
  716. package/lib/collections/rbTree.d.mts.map +0 -1
  717. package/lib/collections/rbTree.mjs.map +0 -1
  718. package/lib/constants.d.mts.map +0 -1
  719. package/lib/constants.mjs.map +0 -1
  720. package/lib/endOfTreeSegment.d.mts.map +0 -1
  721. package/lib/endOfTreeSegment.mjs.map +0 -1
  722. package/lib/index.d.mts.map +0 -1
  723. package/lib/index.mjs.map +0 -1
  724. package/lib/localReference.d.mts.map +0 -1
  725. package/lib/localReference.mjs.map +0 -1
  726. package/lib/merge-tree-beta.d.mts +0 -668
  727. package/lib/merge-tree-public.d.mts +0 -668
  728. package/lib/mergeTree.d.mts.map +0 -1
  729. package/lib/mergeTree.mjs.map +0 -1
  730. package/lib/mergeTreeDeltaCallback.d.mts.map +0 -1
  731. package/lib/mergeTreeDeltaCallback.mjs.map +0 -1
  732. package/lib/mergeTreeNodeWalk.d.mts.map +0 -1
  733. package/lib/mergeTreeNodeWalk.mjs.map +0 -1
  734. package/lib/mergeTreeNodes.d.mts.map +0 -1
  735. package/lib/mergeTreeNodes.mjs.map +0 -1
  736. package/lib/mergeTreeTracking.d.mts.map +0 -1
  737. package/lib/mergeTreeTracking.mjs.map +0 -1
  738. package/lib/opBuilder.mjs.map +0 -1
  739. package/lib/ops.d.mts.map +0 -1
  740. package/lib/ops.mjs.map +0 -1
  741. package/lib/ordinal.d.mts.map +0 -1
  742. package/lib/ordinal.mjs.map +0 -1
  743. package/lib/partialLengths.d.mts.map +0 -1
  744. package/lib/partialLengths.mjs.map +0 -1
  745. package/lib/properties.d.mts.map +0 -1
  746. package/lib/properties.mjs.map +0 -1
  747. package/lib/referencePositions.d.mts.map +0 -1
  748. package/lib/referencePositions.mjs.map +0 -1
  749. package/lib/revertibles.d.mts.map +0 -1
  750. package/lib/revertibles.mjs.map +0 -1
  751. package/lib/segmentGroupCollection.d.mts.map +0 -1
  752. package/lib/segmentGroupCollection.mjs.map +0 -1
  753. package/lib/segmentPropertiesManager.d.mts.map +0 -1
  754. package/lib/segmentPropertiesManager.mjs.map +0 -1
  755. package/lib/snapshotChunks.d.mts.map +0 -1
  756. package/lib/snapshotChunks.mjs.map +0 -1
  757. package/lib/snapshotLoader.d.mts.map +0 -1
  758. package/lib/snapshotLoader.mjs.map +0 -1
  759. package/lib/snapshotV1.d.mts.map +0 -1
  760. package/lib/snapshotV1.mjs.map +0 -1
  761. package/lib/snapshotlegacy.d.mts.map +0 -1
  762. package/lib/snapshotlegacy.mjs.map +0 -1
  763. package/lib/sortedSegmentSet.d.mts.map +0 -1
  764. package/lib/sortedSegmentSet.mjs.map +0 -1
  765. package/lib/sortedSet.d.mts.map +0 -1
  766. package/lib/sortedSet.mjs.map +0 -1
  767. package/lib/textSegment.d.mts.map +0 -1
  768. package/lib/textSegment.mjs.map +0 -1
  769. package/lib/zamboni.d.mts.map +0 -1
  770. package/lib/zamboni.mjs.map +0 -1
@@ -0,0 +1,1441 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { strict as assert } from "assert";
6
+ import { LoggingError } from "@fluidframework/telemetry-utils";
7
+ import { MergeTree } from "../mergeTree.js";
8
+ import { ReconnectTestHelper } from "./reconnectHelper.js";
9
+ import { useStrictPartialLengthChecks } from "./testUtils.js";
10
+ /**
11
+ * Some tests contain ASCII diagrams of the trees to make it easier to reason about
12
+ * structure. The format of these diagrams is this:
13
+ * - segments are separated by `-`.
14
+ * - removed ranges are surrounded by `[` ... `]`
15
+ * - obliterated ranges are surrounded by `(` ... `)`
16
+ *
17
+ * In cases where these ranges are ambiguous, there are additional diagrams
18
+ * containing `v` and `-`, with the `v` denoting the start and end of the range
19
+ *
20
+ * E.g.
21
+ *
22
+ * ```
23
+ * v---v
24
+ * [ABC]
25
+ * ```
26
+ *
27
+ * This diagram describes a single segment, `ABC`, that has been removed.
28
+ *
29
+ *
30
+ * ```
31
+ * v-----v
32
+ * v---v
33
+ * [[ABC]]
34
+ * ```
35
+ *
36
+ * This diagram describes a single segment, `ABC`, that has been concurrently
37
+ * removed by two clients.
38
+ */
39
+ for (const incremental of [true, false]) {
40
+ describe(`obliterate partial lengths incremental = ${incremental}`, () => {
41
+ useStrictPartialLengthChecks();
42
+ beforeEach(() => {
43
+ MergeTree.options.incrementalUpdate = incremental;
44
+ });
45
+ afterEach(() => {
46
+ MergeTree.options.incrementalUpdate = true;
47
+ });
48
+ it("length of children does not differ from parent when overlapping remove+obliterate", () => {
49
+ const helper = new ReconnectTestHelper();
50
+ // ABCDEFGH
51
+ // I-[J]-(KLM-[ABC]-D-123456-E-[FG]-H)
52
+ helper.insertText("A", 0, "ABCDEFGH");
53
+ helper.processAllOps();
54
+ helper.removeRange("C", 0, 3);
55
+ helper.insertText("C", 1, "123456");
56
+ helper.removeRange("A", 5, 7);
57
+ helper.insertText("A", 0, "IJKLM");
58
+ helper.obliterateRange("A", 2, 11);
59
+ helper.removeRange("A", 1, 2);
60
+ helper.processAllOps();
61
+ assert.equal(helper.clients.A.getText(), "I");
62
+ helper.logger.validate();
63
+ });
64
+ it("deletes concurrent insert that occurs after obliterate", () => {
65
+ const helper = new ReconnectTestHelper();
66
+ helper.insertText("B", 0, "ABCD");
67
+ helper.processAllOps();
68
+ helper.obliterateRange("B", 0, 4);
69
+ helper.insertText("C", 2, "X");
70
+ helper.processAllOps();
71
+ assert.equal(helper.clients.A.getText(), "");
72
+ assert.equal(helper.clients.C.getText(), "");
73
+ helper.logger.validate();
74
+ });
75
+ it("deletes concurrent insert that occurs before obliterate", () => {
76
+ const helper = new ReconnectTestHelper();
77
+ helper.insertText("B", 0, "ABCD");
78
+ helper.processAllOps();
79
+ helper.insertText("C", 2, "X");
80
+ helper.obliterateRange("B", 0, 4);
81
+ helper.processAllOps();
82
+ assert.equal(helper.clients.A.getText(), "");
83
+ assert.equal(helper.clients.C.getText(), "");
84
+ helper.logger.validate();
85
+ });
86
+ it("does not delete unacked segment at start of string", () => {
87
+ const helper = new ReconnectTestHelper();
88
+ helper.insertText("C", 0, "ABC");
89
+ helper.obliterateRange("C", 2, 3);
90
+ helper.insertText("B", 0, "X");
91
+ helper.processAllOps();
92
+ assert.equal(helper.clients.A.getText(), "XAB");
93
+ assert.equal(helper.clients.B.getText(), "XAB");
94
+ assert.equal(helper.clients.C.getText(), "XAB");
95
+ helper.logger.validate();
96
+ });
97
+ it("throws when local obliterate has range end outside length of local string", () => {
98
+ const helper = new ReconnectTestHelper();
99
+ helper.insertText("B", 0, "A");
100
+ helper.insertText("C", 0, "B");
101
+ try {
102
+ helper.obliterateRange("C", 0, 2);
103
+ assert.fail("should not be possible to obliterate outside local range");
104
+ }
105
+ catch (e) {
106
+ assert(e instanceof LoggingError);
107
+ assert.equal(e.message, "RangeOutOfBounds");
108
+ }
109
+ });
110
+ it("does not delete when obliterate immediately after insert", () => {
111
+ const helper = new ReconnectTestHelper();
112
+ helper.insertText("C", 0, "A");
113
+ helper.obliterateRange("C", 0, 1);
114
+ helper.insertText("B", 0, "W");
115
+ helper.insertText("C", 0, "D");
116
+ helper.obliterateRange("C", 0, 1);
117
+ helper.processAllOps();
118
+ assert.equal(helper.clients.A.getText(), "W");
119
+ assert.equal(helper.clients.B.getText(), "W");
120
+ assert.equal(helper.clients.C.getText(), "W");
121
+ helper.logger.validate();
122
+ });
123
+ it("does not delete remote insert when between local insert+obliterate", () => {
124
+ const helper = new ReconnectTestHelper();
125
+ helper.insertText("C", 0, "A");
126
+ helper.insertText("B", 0, "X");
127
+ helper.obliterateRange("C", 0, 1);
128
+ helper.insertText("C", 0, "B");
129
+ helper.obliterateRange("C", 0, 1);
130
+ helper.processAllOps();
131
+ assert.equal(helper.clients.A.getText(), "X");
132
+ assert.equal(helper.clients.B.getText(), "X");
133
+ assert.equal(helper.clients.C.getText(), "X");
134
+ helper.logger.validate();
135
+ });
136
+ it("does not delete remote insert when between local insert+obliterate", () => {
137
+ const helper = new ReconnectTestHelper();
138
+ helper.insertText("C", 0, "A");
139
+ helper.obliterateRange("C", 0, 1);
140
+ helper.insertText("B", 0, "B");
141
+ helper.insertText("C", 0, "X");
142
+ helper.obliterateRange("B", 0, 1);
143
+ helper.processAllOps();
144
+ assert.equal(helper.clients.A.getText(), "X");
145
+ assert.equal(helper.clients.B.getText(), "X");
146
+ assert.equal(helper.clients.C.getText(), "X");
147
+ helper.logger.validate();
148
+ });
149
+ it("does not delete remote insert when in middle of segment", () => {
150
+ const helper = new ReconnectTestHelper();
151
+ helper.insertText("C", 0, "ABC");
152
+ helper.obliterateRange("C", 2, 3);
153
+ helper.obliterateRange("C", 0, 1);
154
+ helper.insertText("B", 0, "X");
155
+ helper.processAllOps();
156
+ assert.equal(helper.clients.A.getText(), "XB");
157
+ assert.equal(helper.clients.B.getText(), "XB");
158
+ assert.equal(helper.clients.C.getText(), "XB");
159
+ helper.logger.validate();
160
+ });
161
+ it("deletes segment inserted into locally obliterated segment", () => {
162
+ const helper = new ReconnectTestHelper();
163
+ helper.insertText("C", 0, "A");
164
+ helper.insertText("B", 0, "X");
165
+ helper.insertText("C", 0, "B");
166
+ helper.obliterateRange("C", 0, 2);
167
+ helper.processAllOps();
168
+ assert.equal(helper.clients.A.getText(), "");
169
+ assert.equal(helper.clients.B.getText(), "");
170
+ assert.equal(helper.clients.C.getText(), "");
171
+ helper.logger.validate();
172
+ });
173
+ it("updates lengths after obliterated insertion", () => {
174
+ const helper = new ReconnectTestHelper();
175
+ helper.insertText("C", 0, "A");
176
+ helper.insertText("B", 0, "X");
177
+ helper.insertText("C", 0, "N");
178
+ helper.obliterateRange("C", 0, 2);
179
+ helper.insertText("B", 1, "B");
180
+ helper.processAllOps();
181
+ assert.equal(helper.clients.A.getText(), "");
182
+ assert.equal(helper.clients.B.getText(), "");
183
+ assert.equal(helper.clients.C.getText(), "");
184
+ assert.equal(helper.clients.A.getLength(), 0);
185
+ assert.equal(helper.clients.B.getLength(), 0);
186
+ assert.equal(helper.clients.C.getLength(), 0);
187
+ helper.logger.validate();
188
+ });
189
+ it("updates lengths when insertion causes tree to split", () => {
190
+ const helper = new ReconnectTestHelper();
191
+ helper.insertText("A", 0, "0");
192
+ helper.insertText("C", 0, "123");
193
+ helper.insertText("B", 0, "BB");
194
+ helper.insertText("C", 0, "GGG");
195
+ helper.obliterateRange("C", 2, 5);
196
+ helper.insertText("B", 1, "A");
197
+ helper.processAllOps();
198
+ assert.equal(helper.clients.A.getText().length, helper.clients.A.getLength());
199
+ assert.equal(helper.clients.B.getText().length, helper.clients.B.getLength());
200
+ assert.equal(helper.clients.C.getText().length, helper.clients.C.getLength());
201
+ assert.equal(helper.clients.A.getText(), "GG30");
202
+ helper.logger.validate();
203
+ });
204
+ it("length of node split by insertion does not count remotely obliterated segments", () => {
205
+ const helper = new ReconnectTestHelper();
206
+ helper.insertText("A", 0, "1");
207
+ helper.insertText("A", 0, "2");
208
+ helper.insertText("C", 0, "XXXX");
209
+ helper.insertText("B", 0, "ABC");
210
+ helper.insertText("C", 0, "GGG");
211
+ helper.obliterateRange("C", 2, 6);
212
+ helper.insertText("C", 1, "D");
213
+ helper.processAllOps();
214
+ assert.equal(helper.clients.A.getText(), "GDGX21");
215
+ assert.equal(helper.clients.C.getText(), "GDGX21");
216
+ helper.logger.validate();
217
+ });
218
+ it("length of node split by obliterate does not count remotely obliterated segments", () => {
219
+ const helper = new ReconnectTestHelper();
220
+ helper.insertText("A", 0, "1");
221
+ helper.insertText("A", 0, "2");
222
+ helper.insertText("C", 0, "XXXX");
223
+ helper.insertText("B", 0, "A");
224
+ helper.insertText("C", 0, "GGG");
225
+ helper.obliterateRange("C", 2, 6);
226
+ helper.insertText("C", 1, "C");
227
+ helper.insertText("B", 1, "D");
228
+ helper.processAllOps();
229
+ assert.equal(helper.clients.A.getText(), "GCGX21");
230
+ assert.equal(helper.clients.B.getText(), "GCGX21");
231
+ helper.logger.validate();
232
+ });
233
+ it("counts remotely but not concurrently inserted segments for length when tree is split", () => {
234
+ const helper = new ReconnectTestHelper();
235
+ // a-b-c-d-e-123
236
+ // (a-b)-c-d-e-1-[2]-3
237
+ helper.insertText("B", 0, "123");
238
+ helper.insertText("C", 0, "e");
239
+ helper.insertText("C", 0, "d");
240
+ helper.insertText("C", 0, "c");
241
+ helper.insertText("C", 0, "b");
242
+ helper.insertText("C", 0, "a");
243
+ helper.processAllOps();
244
+ helper.obliterateRange("B", 0, 2);
245
+ helper.removeRange("B", 4, 5);
246
+ helper.processAllOps();
247
+ assert.equal(helper.clients.A.getText(), "cde13");
248
+ assert.equal(helper.clients.C.getText(), "cde13");
249
+ helper.logger.validate();
250
+ });
251
+ it("does obliterate X for all clients", () => {
252
+ const helper = new ReconnectTestHelper();
253
+ helper.insertText("B", 0, "DE");
254
+ helper.obliterateRange("B", 0, 1);
255
+ helper.insertText("A", 0, "X");
256
+ helper.insertText("B", 0, "ABC");
257
+ helper.obliterateRange("B", 2, 4);
258
+ helper.processAllOps();
259
+ assert.equal(helper.clients.A.getText(), "AB");
260
+ assert.equal(helper.clients.C.getText(), "AB");
261
+ helper.logger.validate();
262
+ });
263
+ it("does not include remote but unacked segments in partial len calculation", () => {
264
+ const helper = new ReconnectTestHelper();
265
+ // 89-4567-123-X
266
+ // 8-(9-4-w-567-1)-23-Y-X
267
+ helper.insertText("A", 0, "X");
268
+ helper.insertText("C", 0, "123");
269
+ helper.insertText("C", 0, "4567");
270
+ helper.insertText("B", 0, "89");
271
+ helper.processAllOps();
272
+ helper.obliterateRange("C", 1, 7);
273
+ helper.insertText("A", 3, "w");
274
+ helper.insertText("C", 3, "Y");
275
+ helper.processAllOps();
276
+ assert.equal(helper.clients.A.getText(), "823YX");
277
+ assert.equal(helper.clients.B.getText(), "823YX");
278
+ helper.logger.validate();
279
+ });
280
+ it("correctly accounts for overlapping obliterate", () => {
281
+ const helper = new ReconnectTestHelper();
282
+ helper.insertText("B", 0, "AB");
283
+ helper.processAllOps();
284
+ helper.obliterateRange("C", 0, 1);
285
+ helper.obliterateRange("B", 0, 1);
286
+ helper.processAllOps();
287
+ assert.equal(helper.clients.A.getText(), "B");
288
+ assert.equal(helper.clients.B.getText(), "B");
289
+ assert.equal(helper.clients.C.getText(), "B");
290
+ helper.logger.validate();
291
+ });
292
+ it("correctly accounts for overlapping obliterate and remove", () => {
293
+ const helper = new ReconnectTestHelper();
294
+ helper.insertText("B", 0, "AB");
295
+ helper.processAllOps();
296
+ helper.removeRange("C", 0, 1);
297
+ helper.obliterateRange("B", 0, 1);
298
+ helper.processAllOps();
299
+ assert.equal(helper.clients.A.getText(), "B");
300
+ assert.equal(helper.clients.B.getText(), "B");
301
+ assert.equal(helper.clients.C.getText(), "B");
302
+ helper.logger.validate();
303
+ });
304
+ it("clones movedClientIds array during insert", () => {
305
+ const helper = new ReconnectTestHelper();
306
+ // the bug found here:
307
+ // the X was skipped over by client `A` because it had already been
308
+ // deleted, so its length at refSeq was 0
309
+ //
310
+ // this was due to the movedClientIds array not being properly cloned
311
+ // when marking obliterated during insert
312
+ helper.insertText("C", 0, "ABCD");
313
+ helper.processAllOps();
314
+ helper.insertText("B", 2, "X");
315
+ helper.obliterateRange("A", 1, 3);
316
+ helper.obliterateRange("B", 1, 4);
317
+ helper.processAllOps();
318
+ assert.equal(helper.clients.A.getText(), "AD");
319
+ assert.equal(helper.clients.B.getText(), "AD");
320
+ assert.equal(helper.clients.C.getText(), "AD");
321
+ helper.logger.validate();
322
+ });
323
+ it("client partial lens consider overlapping obliterates", () => {
324
+ const helper = new ReconnectTestHelper();
325
+ helper.insertText("A", 0, "123");
326
+ helper.insertText("A", 0, "ABCDEF");
327
+ helper.processAllOps();
328
+ helper.obliterateRange("B", 2, 3);
329
+ helper.obliterateRange("C", 1, 4);
330
+ helper.obliterateRange("C", 4, 5);
331
+ helper.processAllOps();
332
+ assert.equal(helper.clients.A.getText(), "AEF13");
333
+ assert.equal(helper.clients.B.getText(), "AEF13");
334
+ assert.equal(helper.clients.C.getText(), "AEF13");
335
+ helper.logger.validate();
336
+ });
337
+ it("client partial lens consider overlapping obliterates", () => {
338
+ const helper = new ReconnectTestHelper();
339
+ helper.insertText("C", 0, "X");
340
+ helper.insertText("C", 0, "ABCDEFG");
341
+ helper.processAllOps();
342
+ helper.obliterateRange("B", 2, 3);
343
+ helper.obliterateRange("C", 1, 4);
344
+ helper.obliterateRange("C", 2, 3);
345
+ helper.processAllOps();
346
+ assert.equal(helper.clients.A.getText(), "AEGX");
347
+ assert.equal(helper.clients.C.getText(), "AEGX");
348
+ helper.logger.validate();
349
+ });
350
+ it("tracks obliterate refSeq when acking op for partial len calculation", () => {
351
+ const helper = new ReconnectTestHelper();
352
+ // v-----------------------v
353
+ // v--v
354
+ // v--v
355
+ // 6-(345-AB-(CD)-E-(FG)-HI-1)-2
356
+ helper.insertText("A", 0, "12");
357
+ helper.insertText("B", 0, "ABCDEFGHI");
358
+ helper.insertText("A", 0, "345");
359
+ helper.obliterateRange("A", 0, 4);
360
+ helper.obliterateRange("B", 2, 4);
361
+ helper.insertText("A", 0, "6");
362
+ helper.obliterateRange("B", 3, 5);
363
+ helper.processAllOps();
364
+ assert.equal(helper.clients.A.getText(), "62");
365
+ assert.equal(helper.clients.B.getText(), "62");
366
+ helper.logger.validate();
367
+ });
368
+ it("does not have negative len when segment obliterated before insert", () => {
369
+ const helper = new ReconnectTestHelper();
370
+ // 1234567-D-C-AB
371
+ // 12-([3-X-45]-67)-D-C-AB
372
+ helper.insertText("A", 0, "AB");
373
+ helper.insertText("A", 0, "C");
374
+ helper.insertText("A", 0, "D");
375
+ helper.insertText("A", 0, "1234567");
376
+ helper.processAllOps();
377
+ helper.logger.validate();
378
+ helper.obliterateRange("A", 2, 7);
379
+ helper.removeRange("A", 2, 5);
380
+ helper.insertText("C", 3, "X");
381
+ helper.processAllOps();
382
+ assert.equal(helper.clients.A.getText(), "12B");
383
+ assert.equal(helper.clients.B.getText(), "12B");
384
+ assert.equal(helper.clients.C.getText(), "12B");
385
+ helper.logger.validate();
386
+ });
387
+ it("does not have negative len when segment obliterated before insert", () => {
388
+ const helper = new ReconnectTestHelper();
389
+ // ABCDE-1-[2]-3
390
+ // (A-XX-B)-(CD)-E-1-3
391
+ helper.insertText("B", 0, "123");
392
+ helper.insertText("C", 0, "ABCDE");
393
+ helper.removeRange("B", 1, 2);
394
+ helper.processAllOps();
395
+ helper.logger.validate();
396
+ helper.obliterateRange("C", 0, 2);
397
+ helper.obliterateRange("C", 0, 2);
398
+ helper.insertText("B", 1, "XX");
399
+ helper.processAllOps();
400
+ assert.equal(helper.clients.A.getText(), "E13");
401
+ assert.equal(helper.clients.B.getText(), "E13");
402
+ assert.equal(helper.clients.C.getText(), "E13");
403
+ helper.logger.validate();
404
+ });
405
+ it("deletes segments between two obliterates with different seq", () => {
406
+ const helper = new ReconnectTestHelper();
407
+ // 90-8-1234-(5)-67-D-C-B-A
408
+ // 9-(EFG-[0-8-1234-(5)-67)]-D-C-B-A
409
+ helper.insertText("A", 0, "A");
410
+ helper.insertText("C", 0, "B");
411
+ helper.insertText("C", 0, "C");
412
+ helper.insertText("C", 0, "D");
413
+ helper.insertText("B", 0, "1234567");
414
+ helper.obliterateRange("B", 4, 5);
415
+ helper.insertText("A", 0, "8");
416
+ helper.insertText("A", 0, "90");
417
+ helper.processAllOps();
418
+ helper.removeRange("C", 1, 9);
419
+ helper.insertText("A", 1, "EFG");
420
+ helper.obliterateRange("A", 1, 11);
421
+ helper.processAllOps();
422
+ assert.equal(helper.clients.A.getText(), "9DCBA");
423
+ helper.logger.validate();
424
+ });
425
+ it("deletes inserted segment when obliterate of different seq in-between", () => {
426
+ const helper = new ReconnectTestHelper();
427
+ helper.insertText("A", 0, "AB");
428
+ helper.insertText("B", 0, "E");
429
+ helper.obliterateRange("A", 0, 1);
430
+ helper.insertText("A", 1, "12");
431
+ helper.insertText("A", 0, "CD");
432
+ helper.obliterateRange("A", 1, 4);
433
+ helper.processAllOps();
434
+ assert.equal(helper.clients.A.getText(), "C2");
435
+ assert.equal(helper.clients.B.getText(), "C2");
436
+ assert.equal(helper.clients.C.getText(), "C2");
437
+ helper.logger.validate();
438
+ });
439
+ it("deletes inserted segment when obliterate of different seq in-between", () => {
440
+ const helper = new ReconnectTestHelper();
441
+ helper.insertText("A", 0, "ABC");
442
+ helper.obliterateRange("A", 1, 2);
443
+ helper.processAllOps();
444
+ helper.insertText("A", 1, "D");
445
+ helper.obliterateRange("C", 0, 2);
446
+ helper.processAllOps();
447
+ assert.equal(helper.clients.A.getText(), "");
448
+ assert.equal(helper.clients.B.getText(), "");
449
+ assert.equal(helper.clients.C.getText(), "");
450
+ helper.logger.validate();
451
+ });
452
+ it("deletes inserted segment when obliterate of different seq in-between", () => {
453
+ const helper = new ReconnectTestHelper();
454
+ helper.insertText("A", 0, "ABC");
455
+ helper.obliterateRange("A", 1, 2);
456
+ helper.processAllOps();
457
+ helper.insertText("A", 1, "D");
458
+ helper.obliterateRange("C", 0, 2);
459
+ helper.processAllOps();
460
+ assert.equal(helper.clients.A.getText(), "");
461
+ assert.equal(helper.clients.B.getText(), "");
462
+ assert.equal(helper.clients.C.getText(), "");
463
+ helper.logger.validate();
464
+ });
465
+ it("considers obliterated local segments as remotely obliterate", () => {
466
+ const helper = new ReconnectTestHelper();
467
+ // G-(H-F-I-C)-J-DE-A-(B)
468
+ // G-J-(H-F-I-CD)-E
469
+ helper.insertText("A", 0, "AB");
470
+ helper.obliterateRange("A", 1, 2);
471
+ helper.insertText("C", 0, "CDE");
472
+ helper.insertText("B", 0, "F");
473
+ helper.insertText("C", 0, "GH");
474
+ helper.obliterateRange("C", 1, 3);
475
+ helper.insertText("B", 1, "I");
476
+ helper.insertText("C", 1, "J");
477
+ helper.processAllOps();
478
+ assert.equal(helper.clients.A.getText(), "GJDEA");
479
+ assert.equal(helper.clients.B.getText(), "GJDEA");
480
+ helper.logger.validate();
481
+ });
482
+ it("traverses hier block in obliterated when len at ref seq is >0 and len at len seq == 0", () => {
483
+ const helper = new ReconnectTestHelper();
484
+ helper.insertText("A", 0, "AB");
485
+ helper.insertText("A", 2, "CD");
486
+ helper.removeRange("A", 1, 3);
487
+ helper.insertText("C", 0, "12345");
488
+ helper.insertText("B", 0, "EFG");
489
+ helper.insertText("B", 1, "HIJKL");
490
+ helper.processAllOps();
491
+ helper.logger.validate();
492
+ helper.obliterateRange("A", 6, 12);
493
+ helper.removeRange("A", 5, 7);
494
+ helper.obliterateRange("C", 7, 9);
495
+ helper.processAllOps();
496
+ assert.equal(helper.clients.A.getText(), helper.clients.D.getText());
497
+ assert.equal(helper.clients.B.getText(), "EHIJKAD");
498
+ helper.logger.validate();
499
+ });
500
+ it("traverses hier block in obliterate when len at ref seq is >0 and len at len seq == 0", () => {
501
+ const helper = new ReconnectTestHelper();
502
+ // [E]-FGH-12-[A]-[B]-CD
503
+ // 3-4-F-[G-(H-1)-2]-CD
504
+ helper.insertText("B", 0, "ABCD");
505
+ helper.removeRange("B", 0, 1);
506
+ helper.insertText("C", 0, "12");
507
+ helper.insertText("A", 0, "EFGH");
508
+ helper.removeRange("B", 1, 2);
509
+ helper.removeRange("A", 0, 1);
510
+ helper.processAllOps();
511
+ helper.logger.validate();
512
+ helper.removeRange("A", 1, 5);
513
+ helper.obliterateRange("B", 2, 4);
514
+ helper.insertText("A", 0, "3");
515
+ helper.insertText("A", 0, "4");
516
+ helper.processAllOps();
517
+ assert.equal(helper.clients.A.getText(), "43FBD");
518
+ assert.equal(helper.clients.B.getText(), "43FBD");
519
+ helper.logger.validate();
520
+ });
521
+ it("ignores segments where movedSeq < seq for partial len calculations", () => {
522
+ const helper = new ReconnectTestHelper();
523
+ helper.insertText("B", 0, "ABC");
524
+ helper.insertText("A", 0, "DEF");
525
+ helper.removeRange("A", 1, 2);
526
+ helper.insertText("B", 0, "123456");
527
+ helper.obliterateRange("B", 2, 7);
528
+ helper.insertText("A", 1, "Y");
529
+ helper.processAllOps();
530
+ helper.logger.validate();
531
+ helper.insertText("B", 4, "X");
532
+ helper.processAllOps();
533
+ assert.equal(helper.clients.A.getText(), "12BCX");
534
+ assert.equal(helper.clients.B.getText(), "12BCX");
535
+ assert.equal(helper.clients.C.getText(), "12BCX");
536
+ helper.logger.validate();
537
+ });
538
+ it("accounts for overlapping obliterates from same client", () => {
539
+ const helper = new ReconnectTestHelper();
540
+ helper.insertText("A", 0, "AB");
541
+ helper.processAllOps();
542
+ helper.logger.validate();
543
+ helper.obliterateRange("B", 0, 1);
544
+ helper.obliterateRange("B", 0, 1);
545
+ helper.removeRange("A", 0, 1);
546
+ helper.processAllOps();
547
+ assert.equal(helper.clients.A.getText(), "");
548
+ assert.equal(helper.clients.B.getText(), "");
549
+ assert.equal(helper.clients.C.getText(), "");
550
+ helper.logger.validate();
551
+ });
552
+ it("accounts for concurrently obliterated segments from the perspective of the inserting client for partial lengths", () => {
553
+ const helper = new ReconnectTestHelper();
554
+ helper.insertText("B", 0, "A");
555
+ helper.insertText("C", 0, "B");
556
+ helper.insertText("C", 0, "C");
557
+ helper.insertText("A", 0, "1234");
558
+ helper.processAllOps();
559
+ helper.obliterateRange("C", 1, 3);
560
+ helper.insertText("A", 2, "D");
561
+ helper.insertText("A", 4, "E");
562
+ helper.processAllOps();
563
+ assert.equal(helper.clients.A.getText(), "1E4CBA");
564
+ assert.equal(helper.clients.B.getText(), "1E4CBA");
565
+ helper.logger.validate();
566
+ });
567
+ it("traverses segments when there is a local obliterate", () => {
568
+ const helper = new ReconnectTestHelper();
569
+ helper.insertText("A", 0, "AB");
570
+ helper.obliterateRange("A", 0, 1);
571
+ helper.insertText("C", 0, "12");
572
+ helper.processAllOps();
573
+ helper.logger.validate();
574
+ helper.insertText("C", 2, "C");
575
+ helper.obliterateRange("A", 0, 3);
576
+ helper.processAllOps();
577
+ assert.equal(helper.clients.A.getText(), "");
578
+ helper.logger.validate();
579
+ });
580
+ it("keeps track of all obliterates on a segment", () => {
581
+ const helper = new ReconnectTestHelper();
582
+ // B-A
583
+ // (B-C-(A))
584
+ helper.insertText("C", 0, "A");
585
+ helper.insertText("B", 0, "B");
586
+ helper.processAllOps();
587
+ helper.logger.validate();
588
+ helper.obliterateRange("B", 1, 2);
589
+ // bug here: because segment A has already been obliterated, we wouldn't
590
+ // mark it obliterated by this op as well, meaning that segments in
591
+ // this range would look to the right and not find a matching move seq
592
+ helper.obliterateRange("A", 0, 2);
593
+ helper.insertText("B", 1, "C");
594
+ helper.processAllOps();
595
+ assert.equal(helper.clients.A.getText(), "");
596
+ assert.equal(helper.clients.B.getText(), "");
597
+ assert.equal(helper.clients.C.getText(), "");
598
+ assert.equal(helper.clients.D.getText(), "");
599
+ helper.logger.validate();
600
+ });
601
+ it("many overlapping obliterates", () => {
602
+ const helper = new ReconnectTestHelper();
603
+ // EF-ABCD
604
+ // (1)-2-((E)-F-A)-B-(C)-D
605
+ helper.insertText("C", 0, "ABCD");
606
+ helper.insertText("B", 0, "EF");
607
+ helper.processAllOps();
608
+ helper.logger.validate();
609
+ helper.obliterateRange("B", 0, 3);
610
+ helper.insertText("A", 0, "12");
611
+ helper.removeRange("C", 0, 1);
612
+ helper.obliterateRange("A", 0, 1);
613
+ helper.obliterateRange("B", 1, 2);
614
+ helper.processAllOps();
615
+ assert.equal(helper.clients.A.getText(), "2BD");
616
+ helper.logger.validate();
617
+ });
618
+ it("overlapping obliterates at start", () => {
619
+ const helper = new ReconnectTestHelper();
620
+ // 12345-B-A
621
+ // ((1-C-2)-3)-4-D-5-B-A
622
+ helper.insertText("C", 0, "A");
623
+ helper.insertText("B", 0, "B");
624
+ helper.insertText("A", 0, "12345");
625
+ helper.processAllOps();
626
+ helper.logger.validate();
627
+ helper.obliterateRange("A", 0, 2);
628
+ helper.insertText("C", 1, "C");
629
+ helper.obliterateRange("C", 0, 4);
630
+ helper.insertText("C", 1, "D");
631
+ helper.processAllOps();
632
+ helper.logger.validate();
633
+ });
634
+ it("partial lengths updated when local insert is acked", () => {
635
+ const helper = new ReconnectTestHelper();
636
+ // A-BCDEF
637
+ // (A-B-G-C)-D-I-E-H-F
638
+ helper.insertText("A", 0, "A");
639
+ helper.insertText("A", 1, "BCDEF");
640
+ helper.processAllOps();
641
+ helper.logger.validate();
642
+ helper.obliterateRange("C", 0, 3);
643
+ helper.insertText("A", 2, "G");
644
+ helper.insertText("B", 5, "H");
645
+ helper.insertText("C", 1, "I");
646
+ helper.processAllOps();
647
+ assert.equal(helper.clients.A.getText(), "DIEHF");
648
+ assert.equal(helper.clients.B.getText(), "DIEHF");
649
+ assert.equal(helper.clients.C.getText(), "DIEHF");
650
+ assert.equal(helper.clients.D.getText(), "DIEHF");
651
+ helper.logger.validate();
652
+ });
653
+ it("two local obliterates get different seq numbers after ack", () => {
654
+ const helper = new ReconnectTestHelper();
655
+ // C-AB
656
+ // (C-A)-D-(B)
657
+ helper.insertText("C", 0, "AB");
658
+ helper.insertText("A", 0, "C");
659
+ helper.processAllOps();
660
+ helper.logger.validate();
661
+ // bug here: when the op is acked by client C, it would incorrectly give
662
+ // segment B the same movedSeq despite coming from a different op
663
+ helper.obliterateRange("C", 0, 2);
664
+ helper.insertText("B", 2, "D");
665
+ helper.obliterateRange("C", 0, 1);
666
+ helper.processAllOps();
667
+ assert.equal(helper.clients.A.getText(), "D");
668
+ assert.equal(helper.clients.C.getText(), "D");
669
+ helper.logger.validate();
670
+ });
671
+ it("acks remote segment obliterated by local op", () => {
672
+ const helper = new ReconnectTestHelper();
673
+ // (D-C-A)-B
674
+ // (D-C-A)-B-E
675
+ helper.insertText("B", 0, "AB");
676
+ helper.insertText("A", 0, "C");
677
+ helper.insertText("B", 0, "D");
678
+ // bug here: when the op is acked by client B, it wouldn't correctly
679
+ // visit the segment "C", leaving the obliterate unacked
680
+ helper.obliterateRange("B", 0, 2);
681
+ helper.processAllOps();
682
+ helper.logger.validate();
683
+ helper.insertText("C", 1, "E");
684
+ helper.processAllOps();
685
+ assert.equal(helper.clients.A.getText(), "BE");
686
+ assert.equal(helper.clients.B.getText(), "BE");
687
+ helper.logger.validate();
688
+ });
689
+ it("skips segments obliterated before refSeq when traversing for insertion", () => {
690
+ const helper = new ReconnectTestHelper();
691
+ // CDE-(A)-B
692
+ // C-(DE-F-(A)-B)
693
+ helper.insertText("A", 0, "AB");
694
+ helper.obliterateRange("A", 0, 1);
695
+ helper.insertText("A", 0, "CDE");
696
+ helper.processAllOps();
697
+ helper.logger.validate();
698
+ helper.obliterateRange("A", 1, 4);
699
+ // bug here: when traversing to see if segment should be obliterated after
700
+ // insertion, traversal would stop at segment A because it was obliterated
701
+ // before the refSeq, which made it appear as an un-deleted segment
702
+ helper.insertText("B", 3, "F");
703
+ helper.processAllOps();
704
+ assert.equal(helper.clients.A.getText(), "C");
705
+ assert.equal(helper.clients.B.getText(), "C");
706
+ assert.equal(helper.clients.C.getText(), "C");
707
+ helper.logger.validate();
708
+ });
709
+ it("applies correct movedSeq when right segment has multiple movedSeqs", () => {
710
+ const helper = new ReconnectTestHelper();
711
+ // AB
712
+ // (A-C-D-(B))
713
+ helper.insertText("B", 0, "AB");
714
+ helper.processAllOps();
715
+ helper.logger.validate();
716
+ helper.obliterateRange("A", 1, 2);
717
+ helper.obliterateRange("B", 0, 2);
718
+ // bug here: for client B, segment B had multiple movedSeqs, and when
719
+ // traversal went to the right and found a matching movedSeq in the movedSeqs
720
+ // array, it selected the lowest seq in the array, which differed from
721
+ // the correct and matching movedSeq
722
+ helper.insertText("A", 1, "C");
723
+ helper.insertText("A", 2, "D");
724
+ helper.processAllOps();
725
+ assert.equal(helper.clients.A.getText(), "");
726
+ assert.equal(helper.clients.B.getText(), "");
727
+ assert.equal(helper.clients.C.getText(), "");
728
+ helper.logger.validate();
729
+ });
730
+ it("takes the correct moved client id when multiple clientIds for right segment", () => {
731
+ const helper = new ReconnectTestHelper();
732
+ // AB
733
+ // (A-C-D-(B))
734
+ helper.insertText("A", 0, "AB");
735
+ helper.processAllOps();
736
+ helper.logger.validate();
737
+ helper.obliterateRange("A", 1, 2);
738
+ // bug here: we would incorrectly take the client id of the first element
739
+ // in the movedClientIds array because we did not take into account the
740
+ // length of _both_ the local and non-local movedSeqs arrays
741
+ helper.insertText("A", 1, "C");
742
+ helper.obliterateRange("C", 0, 2);
743
+ helper.insertText("A", 2, "D");
744
+ helper.processAllOps();
745
+ assert.equal(helper.clients.A.getText(), "");
746
+ assert.equal(helper.clients.B.getText(), "");
747
+ assert.equal(helper.clients.C.getText(), "");
748
+ helper.logger.validate();
749
+ });
750
+ it("selects clientId if 0", () => {
751
+ const helper = new ReconnectTestHelper();
752
+ // AB
753
+ // (A-D-E-(C)-B)
754
+ helper.insertText("B", 0, "AB");
755
+ helper.processAllOps();
756
+ helper.logger.validate();
757
+ // bug here: client id was 0, and the check we used was !clientId, rather
758
+ // than clientId !== undefined
759
+ helper.insertText("A", 1, "C");
760
+ helper.obliterateRange("B", 0, 2);
761
+ helper.obliterateRange("A", 1, 2);
762
+ helper.insertText("A", 1, "D");
763
+ helper.insertText("A", 2, "E");
764
+ helper.processAllOps();
765
+ assert.equal(helper.clients.A.getText(), "");
766
+ assert.equal(helper.clients.B.getText(), "");
767
+ assert.equal(helper.clients.C.getText(), "");
768
+ helper.logger.validate();
769
+ });
770
+ it("obliterates unacked segment inside non-leaf-segment", () => {
771
+ const helper = new ReconnectTestHelper();
772
+ // FGHIJ-E-12345678-D-C-A-K-B
773
+ // FGHIJ-E-12345-(6-[7-L-8-D]-C)-A-K-B
774
+ helper.insertText("A", 0, "AB");
775
+ helper.insertText("A", 0, "C");
776
+ helper.insertText("C", 0, "D");
777
+ helper.insertText("B", 0, "12345678");
778
+ helper.insertText("B", 0, "E");
779
+ helper.insertText("C", 0, "FGHIJ");
780
+ helper.insertText("A", 2, "K");
781
+ helper.processAllOps();
782
+ helper.logger.validate();
783
+ helper.removeRange("A", 12, 15);
784
+ // bug here: when traversing for obliterate, we visit unacked segments
785
+ // within the range, considering their length 0 but still marking them
786
+ // obliterated. if the segment was inside a hiernode whose length was
787
+ // also 0, we would incorrectly skip over the entire hier node, rather
788
+ // than visiting the children segments
789
+ helper.obliterateRange("A", 11, 13);
790
+ helper.insertText("B", 13, "L");
791
+ helper.processAllOps();
792
+ assert.equal(helper.clients.A.getText(), "FGHIJE12345AKB");
793
+ assert.equal(helper.clients.B.getText(), "FGHIJE12345AKB");
794
+ assert.equal(helper.clients.C.getText(), "FGHIJE12345AKB");
795
+ helper.logger.validate();
796
+ });
797
+ it("tracks length at seq of lower move/remove seq when overlapping", () => {
798
+ const helper = new ReconnectTestHelper();
799
+ // H-FG-A-CDE-B
800
+ // (H-F-[G-A)-C-I-D]-E-B
801
+ helper.insertText("C", 0, "AB");
802
+ helper.insertText("C", 1, "CDE");
803
+ helper.insertText("B", 0, "FG");
804
+ helper.insertText("A", 0, "H");
805
+ helper.processAllOps();
806
+ helper.logger.validate();
807
+ helper.obliterateRange("A", 0, 4);
808
+ helper.removeRange("B", 2, 6);
809
+ // bug here: this insert triggers a new chunk to be created. when the
810
+ // partial lengths of the new chunk were calculated, it incorrectly
811
+ // used the removedSeq instead of the moveSeq, despite the latter having
812
+ // occurred prior to the remove
813
+ helper.insertText("A", 1, "I");
814
+ helper.processAllOps();
815
+ assert.equal(helper.clients.A.getText(), "IEB");
816
+ assert.equal(helper.clients.B.getText(), "IEB");
817
+ assert.equal(helper.clients.C.getText(), "IEB");
818
+ helper.logger.validate();
819
+ });
820
+ it("segment obliterated on insert overlaps with local obliterate", () => {
821
+ const helper = new ReconnectTestHelper();
822
+ // AB
823
+ // ((A-C)-B)
824
+ helper.insertText("B", 0, "AB");
825
+ helper.processAllOps();
826
+ helper.logger.validate();
827
+ helper.insertText("B", 1, "C");
828
+ helper.obliterateRange("B", 0, 2);
829
+ helper.obliterateRange("A", 0, 2);
830
+ helper.processAllOps();
831
+ assert.equal(helper.clients.A.getText(), "");
832
+ helper.logger.validate();
833
+ });
834
+ it("obliterates entire string when concurrent inserts inside range", () => {
835
+ const helper = new ReconnectTestHelper();
836
+ // GT
837
+ // (G-O-S-Y-T)
838
+ helper.insertText("B", 0, "GT");
839
+ helper.processAllOps();
840
+ helper.logger.validate();
841
+ helper.obliterateRange("B", 0, 2);
842
+ helper.insertText("C", 1, "OY");
843
+ helper.insertText("C", 2, "S");
844
+ helper.processAllOps();
845
+ assert.equal(helper.clients.A.getText(), "");
846
+ helper.logger.validate();
847
+ });
848
+ it("obliterate ack traverses over non-obliterated remove", () => {
849
+ const helper = new ReconnectTestHelper();
850
+ // ABCDEFGH-1
851
+ // ABCDE-(F-[G]-2-H)-1
852
+ // ABCDE-(F-[G]-2-H)-1-3
853
+ helper.insertText("A", 0, "1");
854
+ helper.insertText("C", 0, "ABCDEFGH");
855
+ helper.processAllOps();
856
+ helper.logger.validate();
857
+ helper.removeRange("C", 6, 7);
858
+ helper.insertText("A", 7, "2");
859
+ // obliterate at seq 5 isn't getting acked because it stops traversal
860
+ // at the removed segment, which doesn't have move info
861
+ helper.obliterateRange("C", 5, 7);
862
+ helper.processAllOps();
863
+ helper.logger.validate();
864
+ helper.insertText("A", 6, "3");
865
+ helper.processAllOps();
866
+ assert.equal(helper.clients.A.getText(), "ABCDE13");
867
+ assert.equal(helper.clients.C.getText(), "ABCDE13");
868
+ helper.logger.validate();
869
+ });
870
+ it("overlapping remove and obliterate when remove happens last", () => {
871
+ const helper = new ReconnectTestHelper();
872
+ // FGH-E-D-BC-A
873
+ // ([F]-G)-H-E-D-B-I-C-A
874
+ helper.insertText("A", 0, "A");
875
+ helper.insertText("B", 0, "BC");
876
+ helper.insertText("C", 0, "D");
877
+ helper.insertText("B", 0, "E");
878
+ helper.insertText("B", 0, "FGH");
879
+ helper.processAllOps();
880
+ helper.logger.validate();
881
+ helper.obliterateRange("C", 0, 2);
882
+ helper.removeRange("A", 0, 1);
883
+ helper.insertText("A", 5, "I");
884
+ helper.processAllOps();
885
+ assert.equal(helper.clients.A.getText(), "HEDBICA");
886
+ assert.equal(helper.clients.B.getText(), "HEDBICA");
887
+ assert.equal(helper.clients.C.getText(), "HEDBICA");
888
+ assert.equal(helper.clients.D.getText(), "HEDBICA");
889
+ helper.logger.validate();
890
+ });
891
+ it("overlapping remove and obliterate when remove happens last _and_ partial length already exists", () => {
892
+ const helper = new ReconnectTestHelper();
893
+ // FGH-CDE-B-A
894
+ // [F-(GH)-C]-D-Z-E-B-A
895
+ helper.insertText("B", 0, "A");
896
+ helper.insertText("B", 0, "B");
897
+ helper.insertText("B", 0, "CDE");
898
+ helper.insertText("C", 0, "FGH");
899
+ helper.processAllOps();
900
+ helper.logger.validate();
901
+ helper.obliterateRange("C", 1, 2);
902
+ helper.removeRange("A", 0, 4);
903
+ helper.insertText("A", 1, "Z");
904
+ helper.processAllOps();
905
+ assert.equal(helper.clients.A.getText(), "DZEBA");
906
+ helper.logger.validate();
907
+ });
908
+ it("overlapping obliterate and remove when obliterate is larger than remove and happened last", () => {
909
+ const helper = new ReconnectTestHelper();
910
+ // H-CDEFG-B-A
911
+ // (H-C-[D]-E)-F-Z-G-B-A
912
+ helper.insertText("B", 0, "A");
913
+ helper.insertText("C", 0, "B");
914
+ helper.insertText("A", 0, "CDEFG");
915
+ helper.insertText("A", 0, "H");
916
+ helper.processAllOps();
917
+ helper.logger.validate();
918
+ helper.removeRange("A", 2, 3);
919
+ helper.obliterateRange("C", 0, 4);
920
+ helper.insertText("C", 1, "Z");
921
+ helper.processAllOps();
922
+ assert.equal(helper.clients.A.getText(), "FZGBA");
923
+ helper.logger.validate();
924
+ });
925
+ it("wasMovedOnInsert remains after leaf node is split", () => {
926
+ const helper = new ReconnectTestHelper();
927
+ // CD-B-A
928
+ // I-(C-(G)H-E)-F-D-B-A
929
+ helper.insertText("C", 0, "A");
930
+ helper.insertText("B", 0, "B");
931
+ helper.insertText("B", 0, "CD");
932
+ helper.processAllOps();
933
+ helper.logger.validate();
934
+ helper.insertText("B", 1, "EF");
935
+ helper.obliterateRange("B", 0, 2);
936
+ helper.insertText("A", 1, "GH");
937
+ helper.obliterateRange("A", 1, 2);
938
+ helper.insertText("B", 0, "I");
939
+ helper.processAllOps();
940
+ assert.equal(helper.clients.A.getText(), "IFDBA");
941
+ helper.logger.validate();
942
+ });
943
+ it("overlapping obliterates, segment is obliterated on insert and by local client", () => {
944
+ const helper = new ReconnectTestHelper();
945
+ // DEFG-BC-A
946
+ // v-----------v
947
+ // v-----v
948
+ // (D-(E-H-F)-G)-B-I-C-A
949
+ helper.insertText("B", 0, "A");
950
+ helper.insertText("C", 0, "BC");
951
+ helper.insertText("B", 0, "DEFG");
952
+ helper.processAllOps();
953
+ helper.logger.validate();
954
+ helper.obliterateRange("B", 1, 3);
955
+ helper.insertText("A", 2, "H");
956
+ helper.obliterateRange("A", 0, 5);
957
+ helper.insertText("A", 1, "I");
958
+ helper.processAllOps();
959
+ assert.equal(helper.clients.A.getText(), "BICA");
960
+ helper.logger.validate();
961
+ });
962
+ it("overlapping obliterates and remove", () => {
963
+ const helper = new ReconnectTestHelper();
964
+ // FGHIJKL-BCDE-A
965
+ // (FGHI-[JK-(L-B)-C]-D)-E-M-A
966
+ helper.insertText("C", 0, "A");
967
+ helper.insertText("B", 0, "BCDE");
968
+ helper.insertText("A", 0, "FGHIJKL");
969
+ helper.processAllOps();
970
+ helper.logger.validate();
971
+ helper.removeRange("B", 4, 9);
972
+ helper.obliterateRange("A", 6, 8);
973
+ helper.obliterateRange("C", 0, 10);
974
+ helper.insertText("C", 1, "M");
975
+ helper.processAllOps();
976
+ assert.equal(helper.clients.A.getText(), "EMA");
977
+ helper.logger.validate();
978
+ });
979
+ it("does not mark obliterated on insert for non-acked obliterates", () => {
980
+ const helper = new ReconnectTestHelper();
981
+ // CDE-B-A
982
+ // I-((C-F)-G-D)-H-E-B-A
983
+ helper.insertText("B", 0, "A");
984
+ helper.insertText("A", 0, "B");
985
+ helper.insertText("C", 0, "CDE");
986
+ helper.processAllOps();
987
+ helper.logger.validate();
988
+ helper.insertText("A", 1, "FG");
989
+ helper.obliterateRange("A", 0, 2);
990
+ helper.insertText("A", 2, "H");
991
+ helper.obliterateRange("C", 0, 2);
992
+ helper.insertText("C", 0, "I");
993
+ helper.processAllOps();
994
+ assert.equal(helper.clients.A.getText(), "IHEBA");
995
+ helper.logger.validate();
996
+ });
997
+ it("partial len isLocal when seq is -1 but moveSeq > -1", () => {
998
+ const helper = new ReconnectTestHelper();
999
+ // CDEFG-AB
1000
+ // C-((D-I-E)-F)-G-A-H-B
1001
+ helper.insertText("A", 0, "AB");
1002
+ helper.insertText("B", 0, "CDEFG");
1003
+ helper.processAllOps();
1004
+ helper.logger.validate();
1005
+ helper.obliterateRange("C", 1, 4);
1006
+ helper.obliterateRange("B", 1, 3);
1007
+ helper.insertText("B", 4, "H");
1008
+ helper.insertText("A", 2, "I");
1009
+ helper.processAllOps();
1010
+ assert.equal(helper.clients.A.getText(), "CGAHB");
1011
+ helper.logger.validate();
1012
+ });
1013
+ it("obliterated on insert by overlapping obliterates", () => {
1014
+ const helper = new ReconnectTestHelper();
1015
+ // B-DEFG-C-A
1016
+ // ((B-D-H-E)-F-I-G-C)-A
1017
+ helper.insertText("C", 0, "A");
1018
+ helper.insertText("A", 0, "BC");
1019
+ helper.insertText("A", 1, "DEFG");
1020
+ helper.processAllOps();
1021
+ helper.logger.validate();
1022
+ helper.obliterateRange("B", 0, 6);
1023
+ helper.obliterateRange("A", 0, 3);
1024
+ helper.insertText("C", 2, "H");
1025
+ helper.insertText("A", 1, "I");
1026
+ helper.processAllOps();
1027
+ assert.equal(helper.clients.A.getText(), "A");
1028
+ helper.logger.validate();
1029
+ });
1030
+ it("overlapping obliterates", () => {
1031
+ const helper = new ReconnectTestHelper();
1032
+ // ABCDEF
1033
+ // v-------------v
1034
+ // v-----------v
1035
+ // v-------v
1036
+ // I-((AB-(C-G)-H-D)-E)-F
1037
+ helper.insertText("A", 0, "ABCDEF");
1038
+ helper.processAllOps();
1039
+ helper.logger.validate();
1040
+ helper.obliterateRange("B", 0, 4);
1041
+ helper.obliterateRange("C", 2, 5);
1042
+ helper.insertText("A", 3, "GH");
1043
+ helper.insertText("C", 0, "I");
1044
+ helper.obliterateRange("A", 0, 4);
1045
+ helper.processAllOps();
1046
+ assert.equal(helper.clients.A.getText(), "IF");
1047
+ helper.logger.validate();
1048
+ });
1049
+ it("overlapping obliterates", () => {
1050
+ const helper = new ReconnectTestHelper();
1051
+ // CDEF-AB
1052
+ // v-------------------v
1053
+ // v---------v
1054
+ // v-v
1055
+ // ((C-(G)-H-D)-E-I-F-A)-B
1056
+ helper.insertText("B", 0, "AB");
1057
+ helper.insertText("C", 0, "CDEF");
1058
+ helper.processAllOps();
1059
+ helper.logger.validate();
1060
+ helper.obliterateRange("B", 0, 5);
1061
+ helper.obliterateRange("C", 0, 2);
1062
+ helper.insertText("A", 1, "GH");
1063
+ helper.insertText("C", 1, "I");
1064
+ helper.obliterateRange("A", 1, 2);
1065
+ helper.processAllOps();
1066
+ assert.equal(helper.clients.A.getText(), "B");
1067
+ helper.logger.validate();
1068
+ });
1069
+ it("overlapping remove and obliterate, local obliterate does not have a remote obliterated len", () => {
1070
+ const helper = new ReconnectTestHelper();
1071
+ // v-v------v-v
1072
+ // G-(H-[F]-E)-D-[A]-B-I-C
1073
+ helper.insertText("A", 0, "ABC");
1074
+ helper.insertText("B", 0, "D");
1075
+ helper.insertText("B", 0, "E");
1076
+ helper.insertText("A", 0, "F");
1077
+ helper.removeRange("A", 0, 2);
1078
+ helper.insertText("B", 0, "GH");
1079
+ helper.insertText("A", 1, "I");
1080
+ helper.obliterateRange("B", 1, 3);
1081
+ helper.processAllOps();
1082
+ assert.equal(helper.clients.A.getText(), "GDBIC");
1083
+ helper.logger.validate();
1084
+ });
1085
+ it("triple overlapping obliterate and overlapping remove", () => {
1086
+ const helper = new ReconnectTestHelper();
1087
+ // I-H-BCDEFG-A
1088
+ // v------------v
1089
+ // v-------v
1090
+ // v-v
1091
+ // v-------------------------v
1092
+ // [[I]-H-BCD-(E-(F-(J)-G))-A]
1093
+ helper.insertText("C", 0, "A");
1094
+ helper.insertText("B", 0, "BCDEFG");
1095
+ helper.insertText("B", 0, "H");
1096
+ helper.insertText("B", 0, "I");
1097
+ helper.processAllOps();
1098
+ helper.logger.validate();
1099
+ helper.obliterateRange("B", 6, 8);
1100
+ helper.obliterateRange("A", 5, 8);
1101
+ helper.removeRange("C", 0, 1);
1102
+ helper.insertText("C", 6, "J");
1103
+ helper.obliterateRange("C", 6, 7);
1104
+ helper.removeRange("A", 0, 6);
1105
+ helper.processAllOps();
1106
+ assert.equal(helper.clients.A.getText(), "");
1107
+ assert.equal(helper.clients.C.getText(), "");
1108
+ helper.logger.validate();
1109
+ });
1110
+ it("triple overlapping obliterate with one being local", () => {
1111
+ const helper = new ReconnectTestHelper();
1112
+ // CDEFG-B-A
1113
+ // v--------v
1114
+ // v--------v
1115
+ // v------v
1116
+ // J-(CD-((E-H)-F))-I-G-B-A
1117
+ helper.insertText("C", 0, "A");
1118
+ helper.insertText("B", 0, "B");
1119
+ helper.insertText("C", 0, "CDEFG");
1120
+ helper.processAllOps();
1121
+ helper.logger.validate();
1122
+ helper.obliterateRange("A", 2, 4);
1123
+ helper.insertText("C", 3, "H");
1124
+ helper.obliterateRange("C", 0, 4);
1125
+ helper.insertText("C", 1, "I");
1126
+ helper.insertText("B", 0, "J");
1127
+ helper.obliterateRange("B", 3, 5);
1128
+ helper.processAllOps();
1129
+ assert.equal(helper.clients.C.getText(), "JIGBA");
1130
+ helper.logger.validate();
1131
+ });
1132
+ it("obliterate ack traversal is not stopped by moved segment", () => {
1133
+ const helper = new ReconnectTestHelper();
1134
+ // ABCD
1135
+ // (A-(B)-E-C)-D-F
1136
+ helper.insertText("B", 0, "ABCD");
1137
+ helper.processAllOps();
1138
+ helper.logger.validate();
1139
+ helper.obliterateRange("A", 1, 2);
1140
+ helper.insertText("C", 2, "E");
1141
+ helper.obliterateRange("A", 0, 2);
1142
+ helper.processAllOps();
1143
+ helper.logger.validate();
1144
+ helper.insertText("C", 1, "F");
1145
+ helper.processAllOps();
1146
+ assert.equal(helper.clients.A.getText(), "DF");
1147
+ assert.equal(helper.clients.C.getText(), "DF");
1148
+ helper.logger.validate();
1149
+ });
1150
+ it("updates partial lengths for segments when doing obliterate ack traversal", () => {
1151
+ const helper = new ReconnectTestHelper();
1152
+ // O-JKLMN-FGHI-E-CD-AB
1153
+ // v-v---v-----v
1154
+ // (P-O-JKLMN-FG-[H]-Q-[I-E-C]-D-A)-B
1155
+ // (P-O-JKLMN-FG-[H]-Q-[I-E-C]-D-A)-B-R
1156
+ // problematic segment: H-Q-I-E
1157
+ helper.insertText("B", 0, "AB");
1158
+ helper.insertText("A", 0, "CD");
1159
+ helper.insertText("A", 0, "E");
1160
+ helper.insertText("A", 0, "FGHI");
1161
+ helper.insertText("C", 0, "JKLMN");
1162
+ helper.insertText("B", 0, "O");
1163
+ helper.processAllOps();
1164
+ helper.logger.validate();
1165
+ helper.insertText("A", 0, "P");
1166
+ helper.insertText("B", 9, "Q");
1167
+ helper.removeRange("A", 9, 13);
1168
+ helper.obliterateRange("A", 0, 11);
1169
+ helper.processAllOps();
1170
+ helper.logger.validate();
1171
+ helper.insertText("B", 1, "R");
1172
+ helper.processAllOps();
1173
+ assert.equal(helper.clients.A.getText(), "BR");
1174
+ helper.logger.validate();
1175
+ });
1176
+ // fails only for incremental
1177
+ it("combines remote obliterated length ", () => {
1178
+ const helper = new ReconnectTestHelper();
1179
+ // R-XYZ12-STUVW-LMNOP-DEFGHIJK-A-34567890-Q-BC
1180
+ // v---------------v------------v------v--------v------------v
1181
+ // [R-XYZ12-STUVW-L]-abcdefghij-[MNOP-D]-klmnop-[EFGHIJK-A-34]-5-(6-x-7)-890-Q-BC
1182
+ // v--------v
1183
+ // v--------v
1184
+ // a-T-b-S-c-[def]-ghij-k-Q-l-R-mno-[p-5-8-[9]-0-Q-B]-C
1185
+ // v--------v
1186
+ // v--------v
1187
+ // segment is R-mno-[p-5-8-[9]-0-Q-B]-C
1188
+ // v-------------------------------v
1189
+ // v--------v
1190
+ // v------------v
1191
+ // R-mno-[p-[EFGHIJK-A-34]-5-(6-x-7)-8-[9]-0-Q-B]-C
1192
+ helper.insertText("A", 0, "ABC");
1193
+ helper.insertText("C", 0, "DEFGHIJK");
1194
+ helper.insertText("C", 0, "LMNOP");
1195
+ helper.insertText("A", 1, "Q");
1196
+ helper.insertText("B", 0, "RSTUVW");
1197
+ helper.insertText("B", 1, "XYZ12");
1198
+ helper.insertText("A", 1, "34567890");
1199
+ helper.processAllOps();
1200
+ helper.logger.validate();
1201
+ helper.insertText("C", 29, "x");
1202
+ helper.removeRange("B", 0, 27);
1203
+ helper.insertText("A", 12, "abcdefghij");
1204
+ helper.obliterateRange("A", 38, 40);
1205
+ helper.insertText("C", 17, "klmnop");
1206
+ helper.processAllOps();
1207
+ assert.equal(helper.clients.A.getText(), "abcdefghijklmnop5890QBC");
1208
+ helper.logger.validate();
1209
+ helper.removeRange("B", 3, 6);
1210
+ helper.insertText("C", 11, "Q");
1211
+ helper.insertText("B", 9, "R");
1212
+ helper.insertText("B", 2, "S");
1213
+ helper.removeRange("C", 19, 23);
1214
+ helper.obliterateRange("B", 14, 18);
1215
+ helper.insertText("B", 1, "T");
1216
+ helper.processAllOps();
1217
+ assert.equal(helper.clients.A.getText(), "aTbScghijkQlRmnoC");
1218
+ helper.logger.validate();
1219
+ });
1220
+ it("three obliterates on same segment", () => {
1221
+ const helper = new ReconnectTestHelper();
1222
+ // A
1223
+ // (C-B-D-((A)))
1224
+ helper.insertText("B", 0, "A");
1225
+ helper.processAllOps();
1226
+ helper.logger.validate();
1227
+ helper.obliterateRange("B", 0, 1);
1228
+ helper.obliterateRange("A", 0, 1);
1229
+ helper.insertText("A", 0, "B");
1230
+ helper.insertText("C", 0, "C");
1231
+ helper.insertText("A", 1, "D");
1232
+ helper.obliterateRange("C", 0, 2);
1233
+ helper.processAllOps();
1234
+ helper.logger.validate();
1235
+ });
1236
+ describe("incremental partial length updates", () => {
1237
+ it("obliterates concurrently inserted segment", () => {
1238
+ const helper = new ReconnectTestHelper();
1239
+ // (C-B-A)
1240
+ helper.insertText("A", 0, "A");
1241
+ helper.insertText("B", 0, "B");
1242
+ helper.insertText("A", 0, "C");
1243
+ helper.obliterateRange("A", 0, 2);
1244
+ helper.processAllOps();
1245
+ assert.equal(helper.clients.A.getText(), "");
1246
+ helper.logger.validate();
1247
+ });
1248
+ it("obliterates 2 concurrently inserted segments", () => {
1249
+ const helper = new ReconnectTestHelper();
1250
+ // (C-B-D-A)
1251
+ helper.insertText("B", 0, "A");
1252
+ helper.insertText("A", 0, "B");
1253
+ helper.insertText("B", 0, "C");
1254
+ helper.obliterateRange("B", 0, 2);
1255
+ helper.insertText("A", 1, "D");
1256
+ helper.processAllOps();
1257
+ assert.equal(helper.clients.A.getText(), "");
1258
+ helper.logger.validate();
1259
+ });
1260
+ it("obliterates 4 concurrently inserted segments", () => {
1261
+ const helper = new ReconnectTestHelper();
1262
+ // I-F-(G-D-H-E-C-A)-B
1263
+ helper.insertText("B", 0, "AB");
1264
+ helper.insertText("B", 0, "C");
1265
+ helper.insertText("A", 0, "DE");
1266
+ helper.insertText("B", 0, "FG");
1267
+ helper.obliterateRange("B", 1, 4);
1268
+ helper.insertText("A", 1, "H");
1269
+ helper.insertText("B", 0, "I");
1270
+ helper.processAllOps();
1271
+ assert.equal(helper.clients.A.getText(), "IFB");
1272
+ helper.logger.validate();
1273
+ });
1274
+ it("obliterates 3 concurrently inserted segments", () => {
1275
+ const helper = new ReconnectTestHelper();
1276
+ // I-G-(H-D-F-E-B)-C-A
1277
+ helper.insertText("B", 0, "A");
1278
+ helper.insertText("B", 0, "BC");
1279
+ helper.insertText("A", 0, "DE");
1280
+ helper.insertText("A", 1, "F");
1281
+ helper.insertText("B", 0, "GH");
1282
+ helper.obliterateRange("B", 1, 3);
1283
+ helper.insertText("B", 0, "I");
1284
+ helper.processAllOps();
1285
+ assert.equal(helper.clients.A.getText(), "IGCA");
1286
+ helper.logger.validate();
1287
+ });
1288
+ it("overlapping remove + obliterate, remove happened first", () => {
1289
+ const helper = new ReconnectTestHelper();
1290
+ // D-EFG-B-H-C-A
1291
+ // I-D-([E]-F)-G-B-H-C-A
1292
+ helper.insertText("A", 0, "A");
1293
+ helper.insertText("B", 0, "BC");
1294
+ helper.insertText("C", 0, "DEFG");
1295
+ helper.insertText("B", 1, "H");
1296
+ helper.processAllOps();
1297
+ helper.logger.validate();
1298
+ helper.removeRange("B", 1, 2);
1299
+ helper.obliterateRange("A", 1, 3);
1300
+ helper.insertText("A", 0, "I");
1301
+ helper.processAllOps();
1302
+ assert.equal(helper.clients.A.getText(), "IDGBHCA");
1303
+ helper.logger.validate();
1304
+ });
1305
+ it("overlapping remove + obliterate, remove happened last", () => {
1306
+ const helper = new ReconnectTestHelper();
1307
+ // DEFGH-C-B-A
1308
+ // [D]-[E-(F)-G]-H-C-B-A
1309
+ helper.insertText("C", 0, "A");
1310
+ helper.insertText("B", 0, "B");
1311
+ helper.insertText("A", 0, "C");
1312
+ helper.insertText("B", 0, "DEFGH");
1313
+ helper.processAllOps();
1314
+ helper.logger.validate();
1315
+ helper.obliterateRange("C", 2, 3);
1316
+ helper.removeRange("A", 1, 4);
1317
+ helper.removeRange("A", 0, 1);
1318
+ helper.processAllOps();
1319
+ assert.equal(helper.clients.A.getText(), "HCBA");
1320
+ helper.logger.validate();
1321
+ });
1322
+ it("segment inside locally obliterated segment group is split", () => {
1323
+ const helper = new ReconnectTestHelper();
1324
+ // CDEF-AB
1325
+ // [C]-DE-(F-(G)-H-A)-B
1326
+ // [C]-DE-(F-(G)-H-A)-(B)
1327
+ helper.insertText("B", 0, "AB");
1328
+ helper.insertText("B", 0, "CDEF");
1329
+ helper.processAllOps();
1330
+ helper.logger.validate();
1331
+ helper.removeRange("C", 0, 1);
1332
+ helper.insertText("C", 3, "GH");
1333
+ helper.obliterateRange("C", 3, 4);
1334
+ helper.obliterateRange("A", 3, 5);
1335
+ helper.processAllOps();
1336
+ helper.logger.validate();
1337
+ helper.obliterateRange("B", 2, 3);
1338
+ helper.processAllOps();
1339
+ assert.equal(helper.clients.A.getText(), "DE");
1340
+ helper.logger.validate();
1341
+ });
1342
+ it("continues traversal past locally removed segment inserted before first obliterate", () => {
1343
+ const helper = new ReconnectTestHelper();
1344
+ // ABC
1345
+ // (E-D-(A)-[B]-C)
1346
+ helper.insertText("A", 0, "ABC");
1347
+ helper.processAllOps();
1348
+ helper.logger.validate();
1349
+ helper.obliterateRange("C", 0, 1);
1350
+ helper.insertText("B", 0, "D");
1351
+ helper.removeRange("C", 0, 1);
1352
+ helper.insertText("C", 0, "E");
1353
+ helper.obliterateRange("C", 0, 2);
1354
+ helper.processAllOps();
1355
+ assert.equal(helper.clients.A.getText(), "");
1356
+ helper.logger.validate();
1357
+ });
1358
+ it("keeps track of remote obliterated length when hier node contains hier nodes", () => {
1359
+ const helper = new ReconnectTestHelper();
1360
+ // LMNO-HIJ-E-K-FG-D-C-AB
1361
+ // lmnopq-L-[M]-NO-H-ghijk-I-(J-E-K-FG-D-C-A-a)-bc-ef-d-B
1362
+ // v--------------------------------------v
1363
+ // v-------------------v
1364
+ // r-l-x-mn-[opq-L-[M]-NO-H-gh-s]-t-(u-i-[j]-k-I-(J-E-K-FG-D-C-A-a)-b-v-c-e)-f-d-B
1365
+ // bad segment: (I-(J-E-K-FG-D-C-A-a)-b-v-c-e)-f-d-B
1366
+ helper.insertText("B", 0, "AB");
1367
+ helper.insertText("C", 0, "C");
1368
+ helper.insertText("A", 0, "D");
1369
+ helper.insertText("B", 0, "EFG");
1370
+ helper.insertText("C", 0, "HIJ");
1371
+ helper.insertText("B", 1, "K");
1372
+ helper.insertText("B", 0, "LMNO");
1373
+ helper.processAllOps();
1374
+ helper.logger.validate();
1375
+ helper.removeRange("A", 1, 2);
1376
+ helper.insertText("A", 13, "abcd");
1377
+ helper.obliterateRange("A", 5, 14);
1378
+ helper.insertText("A", 7, "ef"); // seq: 11, len: 7
1379
+ helper.insertText("B", 5, "ghijk");
1380
+ helper.insertText("C", 0, "lmnopq"); // seq: 13, len: 7
1381
+ helper.processAllOps();
1382
+ assert.equal(helper.clients.A.getText(), "lmnopqLNOHghijkIbcefdB");
1383
+ helper.logger.validate();
1384
+ helper.insertText("A", 0, "r");
1385
+ helper.insertText("B", 12, "stu");
1386
+ helper.insertText("A", 18, "v"); // seq: 16, len: 8
1387
+ helper.obliterateRange("B", 14, 22); // seq: 17, len: 3
1388
+ helper.removeRange("B", 3, 13); // seq: 18, len: 3
1389
+ helper.removeRange("A", 14, 15); // seq: 19, len: 3
1390
+ helper.insertText("B", 1, "x");
1391
+ helper.processAllOps();
1392
+ assert.equal(helper.clients.A.getText(), "rlxmntfdB");
1393
+ helper.logger.validate();
1394
+ });
1395
+ it("combines remote obliterated length for parent node of tree with depth >=3", () => {
1396
+ const helper = new ReconnectTestHelper();
1397
+ // VWXYZ0-(K)-[L]-M-[N]-O-EFGHIJ-[A]-B-P-TU-QRS-CD
1398
+ // v-v------v------------v
1399
+ // v--------------------v
1400
+ // v----v---------v-v-----v-----v------------------------------v-v
1401
+ // V-c-W-[XYZ0]-(K)-[L]-[M]-[N]-[O-EFG]-[H]-a-[b-[IJ-[A]-B-P-T]-U-Q]-[R]-S-C-d-f-e-D
1402
+ // v-v------v-v---v-----------v
1403
+ // v-------------------------v
1404
+ // v------v---------v-v-----v---v---v--v-----------------------------------v-v
1405
+ // v---------v
1406
+ // j-i-(V-c-W-[XY)-Z0]-(K)-[L]-[M]-[N]-[O-E]-h-[FG]-[H]-a-[b-[I]-g-[J-[A]-B-P-T]-U-Q]-[R]-S-C-d-f-e-D
1407
+ // problem segment: j-i-(V-c-W-[XY)-Z0]-(K)-[L]-[M]-[N]-[O-E]-h-[FG]-[H]-a-[b]
1408
+ // specifically: j-(V-c-W
1409
+ helper.insertText("C", 0, "ABCD");
1410
+ helper.removeRange("C", 0, 1);
1411
+ helper.insertText("B", 0, "EFGHIJ");
1412
+ helper.insertText("A", 0, "KLMNO");
1413
+ helper.obliterateRange("A", 0, 1);
1414
+ helper.removeRange("A", 0, 1);
1415
+ helper.insertText("C", 1, "PQRS");
1416
+ helper.insertText("C", 2, "TU");
1417
+ helper.removeRange("A", 1, 2);
1418
+ helper.insertText("A", 0, "VWXYZ0"); // seq: 10, len: 2
1419
+ helper.processAllOps();
1420
+ assert.equal(helper.clients.A.getText(), "VWXYZ0MOEFGHIJBPTUQRSCD");
1421
+ helper.logger.validate();
1422
+ helper.insertText("C", 12, "ab");
1423
+ helper.removeRange("B", 11, 17);
1424
+ helper.removeRange("C", 13, 21);
1425
+ helper.insertText("B", 1, "c"); // seq: 14, len: 3
1426
+ helper.insertText("C", 16, "de");
1427
+ helper.insertText("C", 17, "f");
1428
+ helper.removeRange("B", 3, 15);
1429
+ helper.insertText("A", 13, "g");
1430
+ helper.insertText("A", 9, "h");
1431
+ helper.obliterateRange("C", 0, 4); // seq: 20, len: 0
1432
+ helper.insertText("C", 0, "i");
1433
+ helper.insertText("A", 0, "j"); // seq: 22, len: 1
1434
+ helper.processAllOps();
1435
+ assert.equal(helper.clients.A.getText(), "jihagSCdfeD");
1436
+ helper.logger.validate();
1437
+ });
1438
+ });
1439
+ });
1440
+ }
1441
+ //# sourceMappingURL=obliterate.concurrent.spec.js.map