@fluidframework/merge-tree 2.30.0 → 2.31.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 (308) hide show
  1. package/CHANGELOG.md +403 -399
  2. package/api-report/merge-tree.legacy.alpha.api.md +1 -0
  3. package/dist/MergeTreeTextHelper.d.ts +9 -3
  4. package/dist/MergeTreeTextHelper.d.ts.map +1 -1
  5. package/dist/MergeTreeTextHelper.js +5 -5
  6. package/dist/MergeTreeTextHelper.js.map +1 -1
  7. package/dist/client.d.ts +7 -13
  8. package/dist/client.d.ts.map +1 -1
  9. package/dist/client.js +136 -110
  10. package/dist/client.js.map +1 -1
  11. package/dist/endOfTreeSegment.d.ts +12 -8
  12. package/dist/endOfTreeSegment.d.ts.map +1 -1
  13. package/dist/endOfTreeSegment.js +2 -4
  14. package/dist/endOfTreeSegment.js.map +1 -1
  15. package/dist/index.d.ts +6 -3
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +2 -3
  18. package/dist/index.js.map +1 -1
  19. package/dist/mergeTree.d.ts +37 -23
  20. package/dist/mergeTree.d.ts.map +1 -1
  21. package/dist/mergeTree.js +400 -483
  22. package/dist/mergeTree.js.map +1 -1
  23. package/dist/mergeTreeDeltaCallback.d.ts +4 -8
  24. package/dist/mergeTreeDeltaCallback.d.ts.map +1 -1
  25. package/dist/mergeTreeDeltaCallback.js.map +1 -1
  26. package/dist/mergeTreeNodes.d.ts +32 -10
  27. package/dist/mergeTreeNodes.d.ts.map +1 -1
  28. package/dist/mergeTreeNodes.js +43 -28
  29. package/dist/mergeTreeNodes.js.map +1 -1
  30. package/dist/partialLengths.d.ts +2 -2
  31. package/dist/partialLengths.d.ts.map +1 -1
  32. package/dist/partialLengths.js +181 -109
  33. package/dist/partialLengths.js.map +1 -1
  34. package/dist/perspective.d.ts +8 -27
  35. package/dist/perspective.d.ts.map +1 -1
  36. package/dist/perspective.js +7 -67
  37. package/dist/perspective.js.map +1 -1
  38. package/dist/revertibles.d.ts.map +1 -1
  39. package/dist/revertibles.js +2 -2
  40. package/dist/revertibles.js.map +1 -1
  41. package/dist/segmentInfos.d.ts +20 -106
  42. package/dist/segmentInfos.d.ts.map +1 -1
  43. package/dist/segmentInfos.js +28 -42
  44. package/dist/segmentInfos.js.map +1 -1
  45. package/dist/segmentPropertiesManager.d.ts +1 -14
  46. package/dist/segmentPropertiesManager.d.ts.map +1 -1
  47. package/dist/segmentPropertiesManager.js +3 -17
  48. package/dist/segmentPropertiesManager.js.map +1 -1
  49. package/dist/snapshotLoader.d.ts.map +1 -1
  50. package/dist/snapshotLoader.js +62 -19
  51. package/dist/snapshotLoader.js.map +1 -1
  52. package/dist/snapshotV1.d.ts.map +1 -1
  53. package/dist/snapshotV1.js +55 -24
  54. package/dist/snapshotV1.js.map +1 -1
  55. package/dist/snapshotlegacy.d.ts.map +1 -1
  56. package/dist/snapshotlegacy.js +6 -9
  57. package/dist/snapshotlegacy.js.map +1 -1
  58. package/dist/stamps.d.ts +1 -1
  59. package/dist/stamps.js +1 -1
  60. package/dist/stamps.js.map +1 -1
  61. package/dist/test/Insertion.perf.spec.js +6 -51
  62. package/dist/test/Insertion.perf.spec.js.map +1 -1
  63. package/dist/test/PartialLengths.perf.spec.js +18 -25
  64. package/dist/test/PartialLengths.perf.spec.js.map +1 -1
  65. package/dist/test/Removal.perf.spec.js +13 -41
  66. package/dist/test/Removal.perf.spec.js.map +1 -1
  67. package/dist/test/beastTest.spec.d.ts.map +1 -1
  68. package/dist/test/beastTest.spec.js +41 -66
  69. package/dist/test/beastTest.spec.js.map +1 -1
  70. package/dist/test/client.annotateMarker.spec.js +1 -11
  71. package/dist/test/client.annotateMarker.spec.js.map +1 -1
  72. package/dist/test/client.applyMsg.spec.js +14 -14
  73. package/dist/test/client.applyMsg.spec.js.map +1 -1
  74. package/dist/test/client.getPosition.spec.js +1 -1
  75. package/dist/test/client.getPosition.spec.js.map +1 -1
  76. package/dist/test/client.localReference.spec.js +1 -1
  77. package/dist/test/client.localReference.spec.js.map +1 -1
  78. package/dist/test/client.rollback.spec.js +49 -58
  79. package/dist/test/client.rollback.spec.js.map +1 -1
  80. package/dist/test/client.rollbackFarm.spec.js +1 -1
  81. package/dist/test/client.rollbackFarm.spec.js.map +1 -1
  82. package/dist/test/client.searchForMarker.spec.js +4 -21
  83. package/dist/test/client.searchForMarker.spec.js.map +1 -1
  84. package/dist/test/index.d.ts +2 -2
  85. package/dist/test/index.d.ts.map +1 -1
  86. package/dist/test/index.js +2 -6
  87. package/dist/test/index.js.map +1 -1
  88. package/dist/test/mergeTree.annotate.deltaCallback.spec.js +14 -59
  89. package/dist/test/mergeTree.annotate.deltaCallback.spec.js.map +1 -1
  90. package/dist/test/mergeTree.annotate.spec.js +47 -63
  91. package/dist/test/mergeTree.annotate.spec.js.map +1 -1
  92. package/dist/test/mergeTree.insert.deltaCallback.spec.js +9 -62
  93. package/dist/test/mergeTree.insert.deltaCallback.spec.js.map +1 -1
  94. package/dist/test/mergeTree.insertingWalk.spec.js +59 -125
  95. package/dist/test/mergeTree.insertingWalk.spec.js.map +1 -1
  96. package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +12 -93
  97. package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -1
  98. package/dist/test/mergeTree.markRangeRemoved.spec.js +10 -7
  99. package/dist/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
  100. package/dist/test/mergeTree.walk.spec.js +2 -14
  101. package/dist/test/mergeTree.walk.spec.js.map +1 -1
  102. package/dist/test/mergeTreeOperationRunner.js +2 -2
  103. package/dist/test/mergeTreeOperationRunner.js.map +1 -1
  104. package/dist/test/obliterate.concurrent.spec.js +18 -23
  105. package/dist/test/obliterate.concurrent.spec.js.map +1 -1
  106. package/dist/test/obliterate.partialLength.spec.js +166 -136
  107. package/dist/test/obliterate.partialLength.spec.js.map +1 -1
  108. package/dist/test/obliterate.spec.js +16 -126
  109. package/dist/test/obliterate.spec.js.map +1 -1
  110. package/dist/test/partialLength.spec.js +28 -196
  111. package/dist/test/partialLength.spec.js.map +1 -1
  112. package/dist/test/perspective.spec.js +34 -0
  113. package/dist/test/perspective.spec.js.map +1 -1
  114. package/dist/test/propertyManager.spec.js +1 -1
  115. package/dist/test/propertyManager.spec.js.map +1 -1
  116. package/dist/test/resetPendingSegmentsToOp.spec.js +0 -2
  117. package/dist/test/resetPendingSegmentsToOp.spec.js.map +1 -1
  118. package/dist/test/segmentGroupCollection.spec.js +10 -4
  119. package/dist/test/segmentGroupCollection.spec.js.map +1 -1
  120. package/dist/test/testClient.d.ts +1 -0
  121. package/dist/test/testClient.d.ts.map +1 -1
  122. package/dist/test/testClient.js +16 -26
  123. package/dist/test/testClient.js.map +1 -1
  124. package/dist/test/testClientLogger.d.ts.map +1 -1
  125. package/dist/test/testClientLogger.js +3 -10
  126. package/dist/test/testClientLogger.js.map +1 -1
  127. package/dist/test/testServer.d.ts +2 -1
  128. package/dist/test/testServer.d.ts.map +1 -1
  129. package/dist/test/testServer.js +7 -5
  130. package/dist/test/testServer.js.map +1 -1
  131. package/dist/test/testUtils.d.ts +36 -56
  132. package/dist/test/testUtils.d.ts.map +1 -1
  133. package/dist/test/testUtils.js +68 -77
  134. package/dist/test/testUtils.js.map +1 -1
  135. package/dist/test/text.d.ts +2 -2
  136. package/dist/test/text.d.ts.map +1 -1
  137. package/dist/test/text.js +5 -2
  138. package/dist/test/text.js.map +1 -1
  139. package/dist/textSegment.d.ts +0 -6
  140. package/dist/textSegment.d.ts.map +1 -1
  141. package/dist/textSegment.js.map +1 -1
  142. package/dist/zamboni.d.ts.map +1 -1
  143. package/dist/zamboni.js +53 -26
  144. package/dist/zamboni.js.map +1 -1
  145. package/lib/MergeTreeTextHelper.d.ts +9 -3
  146. package/lib/MergeTreeTextHelper.d.ts.map +1 -1
  147. package/lib/MergeTreeTextHelper.js +5 -5
  148. package/lib/MergeTreeTextHelper.js.map +1 -1
  149. package/lib/client.d.ts +7 -13
  150. package/lib/client.d.ts.map +1 -1
  151. package/lib/client.js +117 -116
  152. package/lib/client.js.map +1 -1
  153. package/lib/endOfTreeSegment.d.ts +12 -8
  154. package/lib/endOfTreeSegment.d.ts.map +1 -1
  155. package/lib/endOfTreeSegment.js +2 -4
  156. package/lib/endOfTreeSegment.js.map +1 -1
  157. package/lib/index.d.ts +6 -3
  158. package/lib/index.d.ts.map +1 -1
  159. package/lib/index.js +1 -1
  160. package/lib/index.js.map +1 -1
  161. package/lib/mergeTree.d.ts +37 -23
  162. package/lib/mergeTree.d.ts.map +1 -1
  163. package/lib/mergeTree.js +381 -488
  164. package/lib/mergeTree.js.map +1 -1
  165. package/lib/mergeTreeDeltaCallback.d.ts +4 -8
  166. package/lib/mergeTreeDeltaCallback.d.ts.map +1 -1
  167. package/lib/mergeTreeDeltaCallback.js.map +1 -1
  168. package/lib/mergeTreeNodes.d.ts +32 -10
  169. package/lib/mergeTreeNodes.d.ts.map +1 -1
  170. package/lib/mergeTreeNodes.js +42 -29
  171. package/lib/mergeTreeNodes.js.map +1 -1
  172. package/lib/partialLengths.d.ts +2 -2
  173. package/lib/partialLengths.d.ts.map +1 -1
  174. package/lib/partialLengths.js +160 -111
  175. package/lib/partialLengths.js.map +1 -1
  176. package/lib/perspective.d.ts +8 -27
  177. package/lib/perspective.d.ts.map +1 -1
  178. package/lib/perspective.js +8 -68
  179. package/lib/perspective.js.map +1 -1
  180. package/lib/revertibles.d.ts.map +1 -1
  181. package/lib/revertibles.js +2 -2
  182. package/lib/revertibles.js.map +1 -1
  183. package/lib/segmentInfos.d.ts +20 -106
  184. package/lib/segmentInfos.d.ts.map +1 -1
  185. package/lib/segmentInfos.js +26 -37
  186. package/lib/segmentInfos.js.map +1 -1
  187. package/lib/segmentPropertiesManager.d.ts +1 -14
  188. package/lib/segmentPropertiesManager.d.ts.map +1 -1
  189. package/lib/segmentPropertiesManager.js +2 -16
  190. package/lib/segmentPropertiesManager.js.map +1 -1
  191. package/lib/snapshotLoader.d.ts.map +1 -1
  192. package/lib/snapshotLoader.js +39 -19
  193. package/lib/snapshotLoader.js.map +1 -1
  194. package/lib/snapshotV1.d.ts.map +1 -1
  195. package/lib/snapshotV1.js +34 -26
  196. package/lib/snapshotV1.js.map +1 -1
  197. package/lib/snapshotlegacy.d.ts.map +1 -1
  198. package/lib/snapshotlegacy.js +7 -10
  199. package/lib/snapshotlegacy.js.map +1 -1
  200. package/lib/stamps.d.ts +1 -1
  201. package/lib/stamps.js +1 -1
  202. package/lib/stamps.js.map +1 -1
  203. package/lib/test/Insertion.perf.spec.js +6 -51
  204. package/lib/test/Insertion.perf.spec.js.map +1 -1
  205. package/lib/test/PartialLengths.perf.spec.js +18 -25
  206. package/lib/test/PartialLengths.perf.spec.js.map +1 -1
  207. package/lib/test/Removal.perf.spec.js +13 -41
  208. package/lib/test/Removal.perf.spec.js.map +1 -1
  209. package/lib/test/beastTest.spec.d.ts.map +1 -1
  210. package/lib/test/beastTest.spec.js +42 -67
  211. package/lib/test/beastTest.spec.js.map +1 -1
  212. package/lib/test/client.annotateMarker.spec.js +1 -11
  213. package/lib/test/client.annotateMarker.spec.js.map +1 -1
  214. package/lib/test/client.applyMsg.spec.js +14 -14
  215. package/lib/test/client.applyMsg.spec.js.map +1 -1
  216. package/lib/test/client.getPosition.spec.js +1 -1
  217. package/lib/test/client.getPosition.spec.js.map +1 -1
  218. package/lib/test/client.localReference.spec.js +1 -1
  219. package/lib/test/client.localReference.spec.js.map +1 -1
  220. package/lib/test/client.rollback.spec.js +50 -59
  221. package/lib/test/client.rollback.spec.js.map +1 -1
  222. package/lib/test/client.rollbackFarm.spec.js +1 -1
  223. package/lib/test/client.rollbackFarm.spec.js.map +1 -1
  224. package/lib/test/client.searchForMarker.spec.js +4 -21
  225. package/lib/test/client.searchForMarker.spec.js.map +1 -1
  226. package/lib/test/index.d.ts +2 -2
  227. package/lib/test/index.d.ts.map +1 -1
  228. package/lib/test/index.js +1 -1
  229. package/lib/test/index.js.map +1 -1
  230. package/lib/test/mergeTree.annotate.deltaCallback.spec.js +15 -60
  231. package/lib/test/mergeTree.annotate.deltaCallback.spec.js.map +1 -1
  232. package/lib/test/mergeTree.annotate.spec.js +48 -64
  233. package/lib/test/mergeTree.annotate.spec.js.map +1 -1
  234. package/lib/test/mergeTree.insert.deltaCallback.spec.js +10 -63
  235. package/lib/test/mergeTree.insert.deltaCallback.spec.js.map +1 -1
  236. package/lib/test/mergeTree.insertingWalk.spec.js +61 -127
  237. package/lib/test/mergeTree.insertingWalk.spec.js.map +1 -1
  238. package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +13 -94
  239. package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -1
  240. package/lib/test/mergeTree.markRangeRemoved.spec.js +10 -7
  241. package/lib/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
  242. package/lib/test/mergeTree.walk.spec.js +2 -14
  243. package/lib/test/mergeTree.walk.spec.js.map +1 -1
  244. package/lib/test/mergeTreeOperationRunner.js +3 -3
  245. package/lib/test/mergeTreeOperationRunner.js.map +1 -1
  246. package/lib/test/obliterate.concurrent.spec.js +18 -23
  247. package/lib/test/obliterate.concurrent.spec.js.map +1 -1
  248. package/lib/test/obliterate.partialLength.spec.js +167 -137
  249. package/lib/test/obliterate.partialLength.spec.js.map +1 -1
  250. package/lib/test/obliterate.spec.js +17 -127
  251. package/lib/test/obliterate.spec.js.map +1 -1
  252. package/lib/test/partialLength.spec.js +29 -197
  253. package/lib/test/partialLength.spec.js.map +1 -1
  254. package/lib/test/perspective.spec.js +34 -0
  255. package/lib/test/perspective.spec.js.map +1 -1
  256. package/lib/test/propertyManager.spec.js +2 -2
  257. package/lib/test/propertyManager.spec.js.map +1 -1
  258. package/lib/test/resetPendingSegmentsToOp.spec.js +0 -2
  259. package/lib/test/resetPendingSegmentsToOp.spec.js.map +1 -1
  260. package/lib/test/segmentGroupCollection.spec.js +10 -4
  261. package/lib/test/segmentGroupCollection.spec.js.map +1 -1
  262. package/lib/test/testClient.d.ts +1 -0
  263. package/lib/test/testClient.d.ts.map +1 -1
  264. package/lib/test/testClient.js +18 -28
  265. package/lib/test/testClient.js.map +1 -1
  266. package/lib/test/testClientLogger.d.ts.map +1 -1
  267. package/lib/test/testClientLogger.js +3 -10
  268. package/lib/test/testClientLogger.js.map +1 -1
  269. package/lib/test/testServer.d.ts +2 -1
  270. package/lib/test/testServer.d.ts.map +1 -1
  271. package/lib/test/testServer.js +7 -5
  272. package/lib/test/testServer.js.map +1 -1
  273. package/lib/test/testUtils.d.ts +36 -56
  274. package/lib/test/testUtils.d.ts.map +1 -1
  275. package/lib/test/testUtils.js +66 -48
  276. package/lib/test/testUtils.js.map +1 -1
  277. package/lib/test/text.d.ts +2 -2
  278. package/lib/test/text.d.ts.map +1 -1
  279. package/lib/test/text.js +6 -3
  280. package/lib/test/text.js.map +1 -1
  281. package/lib/textSegment.d.ts +0 -6
  282. package/lib/textSegment.d.ts.map +1 -1
  283. package/lib/textSegment.js.map +1 -1
  284. package/lib/tsdoc-metadata.json +1 -1
  285. package/lib/zamboni.d.ts.map +1 -1
  286. package/lib/zamboni.js +32 -28
  287. package/lib/zamboni.js.map +1 -1
  288. package/package.json +17 -20
  289. package/src/MergeTreeTextHelper.ts +17 -12
  290. package/src/client.ts +141 -197
  291. package/src/endOfTreeSegment.ts +11 -8
  292. package/src/index.ts +4 -3
  293. package/src/mergeTree.ts +482 -633
  294. package/src/mergeTreeDeltaCallback.ts +4 -8
  295. package/src/mergeTreeNodes.ts +66 -45
  296. package/src/partialLengths.ts +181 -137
  297. package/src/perspective.ts +17 -95
  298. package/src/revertibles.ts +2 -7
  299. package/src/segmentInfos.ts +48 -141
  300. package/src/segmentPropertiesManager.ts +2 -16
  301. package/src/snapshotLoader.ts +62 -30
  302. package/src/snapshotV1.ts +36 -28
  303. package/src/snapshotlegacy.ts +7 -16
  304. package/src/stamps.ts +1 -1
  305. package/src/textSegment.ts +0 -13
  306. package/src/zamboni.ts +38 -32
  307. package/tsconfig.json +1 -0
  308. package/prettier.config.cjs +0 -8
@@ -3,34 +3,46 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import { strict as assert } from "node:assert";
6
+ import { NonCollabClient } from "../constants.js";
6
7
  import { MergeTreeDeltaType } from "../ops.js";
8
+ import { TextSegment } from "../textSegment.js";
7
9
  import { TestClient } from "./testClient.js";
8
- import { insertText, obliterateRange, useStrictPartialLengthChecks, validatePartialLengths, } from "./testUtils.js";
10
+ import { useStrictPartialLengthChecks, validatePartialLengths } from "./testUtils.js";
9
11
  describe("obliterate partial lengths", () => {
10
12
  let client;
11
13
  let refSeq;
12
- const localClientId = 17;
13
- const remoteClientId = 18;
14
+ let initialLocalSeq;
15
+ let localClientId = Number.NaN;
16
+ let remoteClientId = Number.NaN;
17
+ let remoteClientId2 = Number.NaN;
14
18
  useStrictPartialLengthChecks();
15
19
  beforeEach(() => {
16
20
  client = new TestClient({
17
21
  mergeTreeEnableObliterate: true,
18
22
  });
19
23
  client.startOrUpdateCollaboration("local");
24
+ localClientId = client.getClientId();
25
+ remoteClientId = client.getOrAddShortClientId("remote 1");
26
+ remoteClientId2 = client.getOrAddShortClientId("remote 2");
20
27
  for (const char of "hello world") {
21
28
  client.applyMsg(client.makeOpMessage(client.insertTextLocal(client.getLength(), char), client.getCurrentSeq() + 1));
22
29
  }
23
30
  assert.equal(client.getText(), "hello world");
24
31
  refSeq = client.getCurrentSeq();
32
+ initialLocalSeq = client.getCollabWindow().localSeq;
25
33
  });
26
34
  it("removes text", () => {
27
35
  assert.equal(client.getText(), "hello world");
28
36
  const localObliterateOp = client.obliterateRangeLocal(0, "hello world".length);
29
37
  assert.equal(client.getText(), "");
30
- validatePartialLengths(localClientId, client.mergeTree, [
31
- { seq: refSeq, len: "hello world".length, localSeq: refSeq },
32
- { seq: refSeq + 1, len: "".length, localSeq: refSeq + 1 },
38
+ const minRefSeqForLocalSeq = new Map([
39
+ [initialLocalSeq, refSeq],
40
+ [initialLocalSeq + 1, refSeq + 1],
33
41
  ]);
42
+ validatePartialLengths(localClientId, client.mergeTree, [
43
+ { seq: refSeq, len: "hello world".length, localSeq: initialLocalSeq },
44
+ { seq: refSeq + 1, len: "".length, localSeq: initialLocalSeq + 1 },
45
+ ], minRefSeqForLocalSeq);
34
46
  client.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 1));
35
47
  validatePartialLengths(remoteClientId, client.mergeTree, [
36
48
  { seq: refSeq, len: "hello world".length },
@@ -40,11 +52,16 @@ describe("obliterate partial lengths", () => {
40
52
  it("correctly applies local remove after local obliterate", () => {
41
53
  const localObliterateOp = client.obliterateRangeLocal(0, "hello ".length);
42
54
  const localRemoveOp = client.removeRangeLocal(0, "world".length);
43
- validatePartialLengths(localClientId, client.mergeTree, [
44
- { seq: refSeq, len: "hello world".length },
45
- { seq: refSeq + 1, len: "world".length, localSeq: refSeq + 1 },
46
- { seq: refSeq + 2, len: "".length, localSeq: refSeq + 2 },
55
+ const minRefSeqForLocalSeq = new Map([
56
+ [initialLocalSeq, refSeq],
57
+ [initialLocalSeq + 1, refSeq],
58
+ [initialLocalSeq + 2, refSeq],
47
59
  ]);
60
+ validatePartialLengths(localClientId, client.mergeTree, [
61
+ { seq: refSeq, len: "hello world".length, localSeq: initialLocalSeq },
62
+ { seq: refSeq, len: "world".length, localSeq: initialLocalSeq + 1 },
63
+ { seq: refSeq, len: "".length, localSeq: initialLocalSeq + 2 },
64
+ ], minRefSeqForLocalSeq);
48
65
  client.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 1));
49
66
  client.applyMsg(client.makeOpMessage(localRemoveOp, refSeq + 2));
50
67
  validatePartialLengths(remoteClientId, client.mergeTree, [
@@ -59,16 +76,7 @@ describe("obliterate partial lengths", () => {
59
76
  });
60
77
  client.startOrUpdateCollaboration("local");
61
78
  for (let i = 0; i < 100; i++) {
62
- insertText({
63
- mergeTree: client.mergeTree,
64
- pos: 0,
65
- refSeq: i,
66
- clientId: localClientId,
67
- seq: i + 1,
68
- text: "a",
69
- props: undefined,
70
- opArgs: { op: { type: MergeTreeDeltaType.INSERT } },
71
- });
79
+ client.mergeTree.insertSegments(0, [TextSegment.make("a")], client.mergeTree.localPerspective, { seq: i + 1, clientId: localClientId }, { op: { type: MergeTreeDeltaType.INSERT } });
72
80
  validatePartialLengths(localClientId, client.mergeTree, [{ seq: i + 1, len: i + 1 }]);
73
81
  validatePartialLengths(remoteClientId, client.mergeTree, [{ seq: i + 1, len: i + 1 }]);
74
82
  refSeq += 1;
@@ -81,191 +89,213 @@ describe("obliterate partial lengths", () => {
81
89
  describe("overlapping remove+obliterate", () => {
82
90
  it("passes for local remove and remote obliterate", () => {
83
91
  const localRemoveOp = client.removeRangeLocal(0, "hello ".length);
84
- obliterateRange({
85
- mergeTree: client.mergeTree,
86
- start: 0,
87
- end: "hello ".length,
88
- refSeq,
89
- clientId: remoteClientId,
90
- seq: refSeq + 1,
91
- opArgs: undefined,
92
- });
92
+ client.removeRangeRemote(0, "hello ".length, refSeq + 1, refSeq, client.getLongClientId(remoteClientId));
93
+ const minRefSeqForLocalSeq = new Map([
94
+ [initialLocalSeq, refSeq],
95
+ [initialLocalSeq + 1, refSeq],
96
+ ]);
93
97
  validatePartialLengths(localClientId, client.mergeTree, [
94
- { seq: refSeq, len: "hello world".length, localSeq: refSeq },
95
- { seq: refSeq + 1, len: "world".length, localSeq: refSeq + 1 },
98
+ { seq: refSeq, len: "hello world".length, localSeq: initialLocalSeq },
99
+ { seq: refSeq, len: "world".length, localSeq: initialLocalSeq + 1 },
100
+ { seq: refSeq + 1, len: "world".length, localSeq: initialLocalSeq },
101
+ { seq: refSeq + 1, len: "world".length, localSeq: initialLocalSeq + 1 },
102
+ ], minRefSeqForLocalSeq);
103
+ client.applyMsg(client.makeOpMessage(localRemoveOp, refSeq + 2));
104
+ validatePartialLengths(NonCollabClient, client.mergeTree, [
105
+ { seq: refSeq, len: "hello world".length },
106
+ { seq: refSeq + 1, len: "world".length },
107
+ { seq: refSeq + 2, len: "world".length },
96
108
  ]);
97
- client.applyMsg(client.makeOpMessage(localRemoveOp, refSeq + 1));
98
109
  validatePartialLengths(remoteClientId, client.mergeTree, [
99
- { seq: refSeq, len: "hello world".length },
100
- { seq: refSeq + 1, len: "world".length, localSeq: refSeq + 1 },
101
- ], refSeq);
110
+ { seq: refSeq, len: "world".length },
111
+ { seq: refSeq + 1, len: "world".length },
112
+ { seq: refSeq + 2, len: "world".length },
113
+ ]);
102
114
  });
103
115
  it("passes for remote remove and local obliterate", () => {
104
- client.removeRangeRemote(0, "hello ".length, refSeq + 1, refSeq, client.getLongClientId(remoteClientId));
105
116
  const localObliterateOp = client.obliterateRangeLocal(0, "hello ".length);
106
- validatePartialLengths(localClientId, client.mergeTree, [
107
- { seq: refSeq, len: "hello world".length, localSeq: refSeq },
108
- { seq: refSeq + 1, len: "world".length, localSeq: refSeq + 1 },
109
- { seq: refSeq + 2, len: "world".length, localSeq: refSeq + 2 },
117
+ client.removeRangeRemote(0, "hello ".length, refSeq + 1, refSeq, client.getLongClientId(remoteClientId));
118
+ const minRefSeqForLocalSeq = new Map([
119
+ [initialLocalSeq, refSeq],
120
+ [initialLocalSeq + 1, refSeq],
110
121
  ]);
122
+ validatePartialLengths(localClientId, client.mergeTree, [
123
+ { seq: refSeq, len: "hello world".length, localSeq: initialLocalSeq },
124
+ { seq: refSeq, len: "world".length, localSeq: initialLocalSeq + 1 },
125
+ { seq: refSeq + 1, len: "world".length, localSeq: initialLocalSeq },
126
+ { seq: refSeq + 1, len: "world".length, localSeq: initialLocalSeq + 1 },
127
+ ], minRefSeqForLocalSeq);
111
128
  client.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));
112
- validatePartialLengths(remoteClientId, client.mergeTree, [
129
+ validatePartialLengths(NonCollabClient, client.mergeTree, [
113
130
  { seq: refSeq, len: "hello world".length },
114
- { seq: refSeq + 1, len: "hello world".length },
131
+ { seq: refSeq + 1, len: "world".length },
132
+ { seq: refSeq + 2, len: "world".length },
133
+ ]);
134
+ validatePartialLengths(remoteClientId, client.mergeTree, [
135
+ { seq: refSeq, len: "world".length },
136
+ { seq: refSeq + 1, len: "world".length },
115
137
  { seq: refSeq + 2, len: "world".length },
116
138
  ]);
117
139
  });
118
140
  it("passes for remote remove and remote obliterate", () => {
119
141
  client.removeRangeRemote(0, "hello ".length, refSeq + 1, refSeq, client.getLongClientId(remoteClientId));
120
- obliterateRange({
121
- mergeTree: client.mergeTree,
122
- start: 0,
123
- end: "hello ".length,
124
- refSeq,
125
- clientId: remoteClientId + 1,
126
- seq: refSeq + 2,
127
- opArgs: undefined,
128
- });
129
- validatePartialLengths(localClientId, client.mergeTree, [
142
+ client.removeRangeRemote(0, "hello ".length, refSeq + 2, refSeq, client.getLongClientId(remoteClientId2));
143
+ validatePartialLengths(NonCollabClient, client.mergeTree, [
130
144
  { seq: refSeq, len: "hello world".length },
131
- { seq: refSeq + 1, len: "hello world".length },
145
+ { seq: refSeq + 1, len: "world".length },
132
146
  { seq: refSeq + 2, len: "world".length },
133
147
  ]);
134
148
  validatePartialLengths(remoteClientId, client.mergeTree, [
135
- { seq: refSeq, len: "hello world".length },
136
- { seq: refSeq + 1, len: "hello world".length },
149
+ { seq: refSeq, len: "world".length },
150
+ { seq: refSeq + 1, len: "world".length },
137
151
  { seq: refSeq + 2, len: "world".length },
138
- ], 0);
139
- validatePartialLengths(remoteClientId + 1, client.mergeTree, [
140
- { seq: refSeq, len: "hello world".length },
141
- { seq: refSeq + 1, len: "hello world".length },
152
+ ]);
153
+ validatePartialLengths(remoteClientId2, client.mergeTree, [
154
+ { seq: refSeq, len: "world".length },
155
+ { seq: refSeq + 1, len: "world".length },
142
156
  { seq: refSeq + 2, len: "world".length },
143
- ], 0);
157
+ ]);
144
158
  });
145
159
  });
146
160
  describe("overlapping obliterate+obliterate", () => {
147
161
  it("passes for local obliterate and remote obliterate", () => {
148
162
  const localObliterateOp = client.obliterateRangeLocal(0, "hello ".length);
149
- obliterateRange({
150
- mergeTree: client.mergeTree,
151
- start: 0,
152
- end: "hello ".length,
153
- refSeq,
154
- clientId: remoteClientId,
155
- seq: refSeq + 1,
156
- opArgs: undefined,
157
- });
163
+ client.obliterateRangeRemote(0, "hello ".length, refSeq + 1, refSeq, client.getLongClientId(remoteClientId));
164
+ const minRefSeqForLocalSeq = new Map([
165
+ [initialLocalSeq, refSeq],
166
+ [initialLocalSeq + 1, refSeq],
167
+ ]);
158
168
  validatePartialLengths(localClientId, client.mergeTree, [
169
+ { seq: refSeq, len: "hello world".length, localSeq: initialLocalSeq },
170
+ { seq: refSeq, len: "world".length, localSeq: initialLocalSeq + 1 },
171
+ { seq: refSeq + 1, len: "world".length, localSeq: initialLocalSeq },
172
+ { seq: refSeq + 1, len: "world".length, localSeq: initialLocalSeq + 1 },
173
+ ], minRefSeqForLocalSeq);
174
+ client.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));
175
+ validatePartialLengths(NonCollabClient, client.mergeTree, [
159
176
  { seq: refSeq, len: "hello world".length },
160
177
  { seq: refSeq + 1, len: "world".length },
161
178
  { seq: refSeq + 2, len: "world".length },
162
179
  ]);
163
- client.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));
164
180
  validatePartialLengths(remoteClientId, client.mergeTree, [
165
- { seq: refSeq, len: "hello world".length },
166
- { seq: refSeq + 1, len: "world".length, localSeq: refSeq + 1 },
167
- { seq: refSeq + 2, len: "world".length, localSeq: refSeq + 2 },
168
- ], refSeq);
169
- });
170
- it("passes for remote obliterate and local obliterate", () => {
171
- obliterateRange({
172
- mergeTree: client.mergeTree,
173
- start: 0,
174
- end: "hello ".length,
175
- refSeq,
176
- clientId: remoteClientId,
177
- seq: refSeq + 1,
178
- opArgs: undefined,
179
- });
180
- const localObliterateOp = client.obliterateRangeLocal(0, "hello".length);
181
- validatePartialLengths(localClientId, client.mergeTree, [
182
- { seq: refSeq, len: "hello world".length },
181
+ { seq: refSeq, len: "world".length },
183
182
  { seq: refSeq + 1, len: "world".length },
184
183
  { seq: refSeq + 2, len: "world".length },
185
184
  ]);
186
- client.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));
187
- validatePartialLengths(remoteClientId, client.mergeTree, [
188
- { seq: refSeq, len: "hello world".length, localSeq: refSeq },
189
- { seq: refSeq + 1, len: "world".length, localSeq: refSeq + 1 },
190
- { seq: refSeq + 2, len: "".length, localSeq: refSeq + 2 },
191
- ], refSeq);
192
185
  });
193
186
  });
194
187
  describe("obliterate with concurrent inserts", () => {
195
188
  it("obliterates when concurrent insert in middle of string", () => {
196
189
  const localObliterateOp = client.obliterateRangeLocal(0, client.getLength());
197
- insertText({
198
- mergeTree: client.mergeTree,
199
- pos: "hello".length,
200
- refSeq,
201
- clientId: remoteClientId,
202
- seq: refSeq + 1,
203
- text: "more ",
204
- props: undefined,
205
- opArgs: { op: { type: MergeTreeDeltaType.INSERT } },
206
- });
190
+ client.insertTextRemote("hello".length, "more ", undefined, refSeq + 1, refSeq, client.getLongClientId(remoteClientId));
207
191
  assert.equal(client.getText(), "");
192
+ const minRefSeqForLocalSeq = new Map([
193
+ [initialLocalSeq, refSeq],
194
+ [initialLocalSeq + 1, refSeq],
195
+ ]);
208
196
  validatePartialLengths(localClientId, client.mergeTree, [
197
+ { seq: refSeq, len: "hello world".length, localSeq: initialLocalSeq },
198
+ { seq: refSeq, len: "".length, localSeq: initialLocalSeq + 1 },
199
+ { seq: refSeq + 1, len: "hellomore world".length, localSeq: initialLocalSeq },
200
+ { seq: refSeq + 1, len: "".length, localSeq: initialLocalSeq + 1 },
201
+ ], minRefSeqForLocalSeq);
202
+ client.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));
203
+ validatePartialLengths(NonCollabClient, client.mergeTree, [
209
204
  { seq: refSeq, len: "hello world".length },
210
205
  { seq: refSeq + 1, len: "hellomore world".length },
211
- { seq: refSeq + 1, len: "".length, localSeq: refSeq + 1 },
206
+ { seq: refSeq + 2, len: "".length },
212
207
  ]);
213
- client.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));
214
208
  validatePartialLengths(remoteClientId, client.mergeTree, [
215
- { seq: refSeq, len: "hello world".length },
209
+ { seq: refSeq, len: "hellomore world".length },
216
210
  { seq: refSeq + 1, len: "hellomore world".length },
217
- { seq: refSeq + 2, len: "".length, localSeq: refSeq + 2 },
218
- ], refSeq);
211
+ { seq: refSeq + 2, len: "".length },
212
+ ]);
219
213
  });
220
214
  it("obliterate does not affect concurrent insert at start of string", () => {
221
215
  const localObliterateOp = client.obliterateRangeLocal(0, client.getLength());
222
- insertText({
223
- mergeTree: client.mergeTree,
224
- pos: 0,
225
- refSeq,
226
- clientId: remoteClientId,
227
- seq: refSeq + 1,
228
- text: "more ",
229
- props: undefined,
230
- opArgs: { op: { type: MergeTreeDeltaType.INSERT } },
231
- });
216
+ client.insertTextRemote(0, "more ", undefined, refSeq + 1, refSeq, client.getLongClientId(remoteClientId));
232
217
  assert.equal(client.getText(), "more ");
218
+ const minRefSeqForLocalSeq = new Map([
219
+ [initialLocalSeq, refSeq],
220
+ [initialLocalSeq + 1, refSeq],
221
+ ]);
233
222
  validatePartialLengths(localClientId, client.mergeTree, [
223
+ { seq: refSeq, len: "hello world".length, localSeq: initialLocalSeq },
224
+ { seq: refSeq, len: "".length, localSeq: initialLocalSeq + 1 },
225
+ { seq: refSeq + 1, len: "more hello world".length, localSeq: initialLocalSeq },
226
+ { seq: refSeq + 1, len: "more ".length, localSeq: initialLocalSeq + 1 },
227
+ ], minRefSeqForLocalSeq);
228
+ client.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));
229
+ validatePartialLengths(NonCollabClient, client.mergeTree, [
234
230
  { seq: refSeq, len: "hello world".length },
235
231
  { seq: refSeq + 1, len: "more hello world".length },
236
- { seq: refSeq + 1, len: "more ".length, localSeq: refSeq + 1 },
232
+ { seq: refSeq + 2, len: "more ".length },
237
233
  ]);
238
- client.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));
239
234
  validatePartialLengths(remoteClientId, client.mergeTree, [
240
- { seq: refSeq, len: "hello world".length },
235
+ { seq: refSeq, len: "more hello world".length },
241
236
  { seq: refSeq + 1, len: "more hello world".length },
242
237
  { seq: refSeq + 2, len: "more ".length },
243
- ], refSeq);
238
+ ]);
244
239
  });
245
240
  it("obliterate does not affect concurrent insert at end of string", () => {
246
241
  const localObliterateOp = client.obliterateRangeLocal(0, client.getLength());
247
- insertText({
248
- mergeTree: client.mergeTree,
249
- pos: "hello world".length,
250
- refSeq,
251
- clientId: remoteClientId,
252
- seq: refSeq + 1,
253
- text: "more ",
254
- props: undefined,
255
- opArgs: { op: { type: MergeTreeDeltaType.INSERT } },
256
- });
242
+ client.insertTextRemote("hello world".length, "more ", undefined, refSeq + 1, refSeq, client.getLongClientId(remoteClientId));
257
243
  assert.equal(client.getText(), "more ");
258
244
  validatePartialLengths(localClientId, client.mergeTree, [
245
+ { seq: refSeq, len: "hello world".length, localSeq: initialLocalSeq },
246
+ { seq: refSeq, len: "".length, localSeq: initialLocalSeq + 1 },
247
+ { seq: refSeq + 1, len: "hello worldmore ".length, localSeq: initialLocalSeq },
248
+ { seq: refSeq + 1, len: "more ".length, localSeq: initialLocalSeq + 1 },
249
+ ]);
250
+ client.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));
251
+ validatePartialLengths(NonCollabClient, client.mergeTree, [
259
252
  { seq: refSeq, len: "hello world".length },
260
253
  { seq: refSeq + 1, len: "hello worldmore ".length },
261
- { seq: refSeq + 1, len: "more ".length, localSeq: refSeq + 1 },
254
+ { seq: refSeq + 2, len: "more ".length },
262
255
  ]);
263
- client.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));
264
256
  validatePartialLengths(remoteClientId, client.mergeTree, [
265
- { seq: refSeq, len: "hello world".length },
257
+ { seq: refSeq, len: "hello worldmore ".length },
266
258
  { seq: refSeq + 1, len: "hello worldmore ".length },
267
259
  { seq: refSeq + 2, len: "more ".length },
268
- ], refSeq);
260
+ ]);
261
+ });
262
+ });
263
+ describe("Overlapping remote/local obliterate with insertion within the collab window", () => {
264
+ it("acked insertion", () => {
265
+ let seq = client.getCurrentSeq();
266
+ const initialSeq = seq;
267
+ client.insertTextRemote(0, "more ", undefined, ++seq, refSeq, client.getLongClientId(remoteClientId));
268
+ const insertSeq = seq;
269
+ client.obliterateRangeLocal(0, 5);
270
+ const localRemoveLocalSeq = client.getCollabWindow().localSeq;
271
+ client.obliterateRangeRemote(0, 5, ++seq, insertSeq, client.getLongClientId(remoteClientId));
272
+ const obliterateSeq = seq;
273
+ validatePartialLengths(localClientId, client.mergeTree, [
274
+ { seq: initialSeq, localSeq: initialLocalSeq, len: "hello world".length },
275
+ { seq: insertSeq, localSeq: initialLocalSeq, len: "more hello world".length },
276
+ { seq: obliterateSeq, localSeq: initialLocalSeq, len: "hello world".length },
277
+ { seq: initialSeq, localSeq: localRemoveLocalSeq, len: "hello world".length },
278
+ { seq: insertSeq, localSeq: localRemoveLocalSeq, len: "hello world".length },
279
+ { seq: obliterateSeq, localSeq: localRemoveLocalSeq, len: "hello world".length },
280
+ ]);
281
+ });
282
+ it("local insertion", () => {
283
+ let seq = client.getCurrentSeq();
284
+ const initialSeq = seq;
285
+ client.insertTextLocal(6, "more ");
286
+ const insertLocalSeq = client.getCollabWindow().localSeq;
287
+ client.obliterateRangeLocal(6, 11); // Remove the added "more "
288
+ const localRemoveLocalSeq = client.getCollabWindow().localSeq;
289
+ client.obliterateRangeRemote(0, "hello world".length, ++seq, initialSeq, client.getLongClientId(remoteClientId));
290
+ const obliterateSeq = seq;
291
+ validatePartialLengths(localClientId, client.mergeTree, [
292
+ { seq: initialSeq, localSeq: initialLocalSeq, len: "hello world".length },
293
+ { seq: initialSeq, localSeq: insertLocalSeq, len: "hello more world".length },
294
+ { seq: initialSeq, localSeq: localRemoveLocalSeq, len: "hello world".length },
295
+ { seq: obliterateSeq, localSeq: initialLocalSeq, len: "".length },
296
+ { seq: obliterateSeq, localSeq: insertLocalSeq, len: "".length },
297
+ { seq: obliterateSeq, localSeq: localRemoveLocalSeq, len: "".length },
298
+ ]);
269
299
  });
270
300
  });
271
301
  });
@@ -1 +1 @@
1
- {"version":3,"file":"obliterate.partialLength.spec.js","sourceRoot":"","sources":["../../src/test/obliterate.partialLength.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { MergeTreeDeltaType } from \"../ops.js\";\n\nimport { TestClient } from \"./testClient.js\";\nimport {\n\tinsertText,\n\tobliterateRange,\n\tuseStrictPartialLengthChecks,\n\tvalidatePartialLengths,\n} from \"./testUtils.js\";\n\ndescribe(\"obliterate partial lengths\", () => {\n\tlet client: TestClient;\n\tlet refSeq: number;\n\tconst localClientId = 17;\n\tconst remoteClientId = 18;\n\n\tuseStrictPartialLengthChecks();\n\n\tbeforeEach(() => {\n\t\tclient = new TestClient({\n\t\t\tmergeTreeEnableObliterate: true,\n\t\t});\n\t\tclient.startOrUpdateCollaboration(\"local\");\n\t\tfor (const char of \"hello world\") {\n\t\t\tclient.applyMsg(\n\t\t\t\tclient.makeOpMessage(\n\t\t\t\t\tclient.insertTextLocal(client.getLength(), char),\n\t\t\t\t\tclient.getCurrentSeq() + 1,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tassert.equal(client.getText(), \"hello world\");\n\t\trefSeq = client.getCurrentSeq();\n\t});\n\n\tit(\"removes text\", () => {\n\t\tassert.equal(client.getText(), \"hello world\");\n\t\tconst localObliterateOp = client.obliterateRangeLocal(0, \"hello world\".length);\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tvalidatePartialLengths(localClientId, client.mergeTree, [\n\t\t\t{ seq: refSeq, len: \"hello world\".length, localSeq: refSeq },\n\t\t\t{ seq: refSeq + 1, len: \"\".length, localSeq: refSeq + 1 },\n\t\t]);\n\n\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 1));\n\n\t\tvalidatePartialLengths(remoteClientId, client.mergeTree, [\n\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t{ seq: refSeq + 1, len: \"\".length },\n\t\t]);\n\t});\n\n\tit(\"correctly applies local remove after local obliterate\", () => {\n\t\tconst localObliterateOp = client.obliterateRangeLocal(0, \"hello \".length);\n\t\tconst localRemoveOp = client.removeRangeLocal(0, \"world\".length);\n\n\t\tvalidatePartialLengths(localClientId, client.mergeTree, [\n\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t{ seq: refSeq + 1, len: \"world\".length, localSeq: refSeq + 1 },\n\t\t\t{ seq: refSeq + 2, len: \"\".length, localSeq: refSeq + 2 },\n\t\t]);\n\n\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 1));\n\t\tclient.applyMsg(client.makeOpMessage(localRemoveOp, refSeq + 2));\n\n\t\tvalidatePartialLengths(remoteClientId, client.mergeTree, [\n\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t{ seq: refSeq + 1, len: \"world\".length },\n\t\t\t{ seq: refSeq + 2, len: \"\".length },\n\t\t]);\n\t});\n\n\tit(\"is correct for different heights\", () => {\n\t\tclient = new TestClient({\n\t\t\tmergeTreeEnableObliterate: true,\n\t\t});\n\t\tclient.startOrUpdateCollaboration(\"local\");\n\n\t\tfor (let i = 0; i < 100; i++) {\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: 0,\n\t\t\t\trefSeq: i,\n\t\t\t\tclientId: localClientId,\n\t\t\t\tseq: i + 1,\n\t\t\t\ttext: \"a\",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\n\t\t\tvalidatePartialLengths(localClientId, client.mergeTree, [{ seq: i + 1, len: i + 1 }]);\n\t\t\tvalidatePartialLengths(remoteClientId, client.mergeTree, [{ seq: i + 1, len: i + 1 }]);\n\n\t\t\trefSeq += 1;\n\t\t}\n\n\t\tconst localObliterateOp = client.obliterateRangeLocal(50, 100);\n\n\t\tvalidatePartialLengths(localClientId, client.mergeTree);\n\n\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 1));\n\n\t\tvalidatePartialLengths(remoteClientId, client.mergeTree);\n\t});\n\n\tdescribe(\"overlapping remove+obliterate\", () => {\n\t\tit(\"passes for local remove and remote obliterate\", () => {\n\t\t\tconst localRemoveOp = client.removeRangeLocal(0, \"hello \".length);\n\t\t\tobliterateRange({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tstart: 0,\n\t\t\t\tend: \"hello \".length,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\n\t\t\tvalidatePartialLengths(localClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length, localSeq: refSeq },\n\t\t\t\t{ seq: refSeq + 1, len: \"world\".length, localSeq: refSeq + 1 },\n\t\t\t]);\n\n\t\t\tclient.applyMsg(client.makeOpMessage(localRemoveOp, refSeq + 1));\n\n\t\t\tvalidatePartialLengths(\n\t\t\t\tremoteClientId,\n\t\t\t\tclient.mergeTree,\n\t\t\t\t[\n\t\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"world\".length, localSeq: refSeq + 1 },\n\t\t\t\t],\n\t\t\t\trefSeq,\n\t\t\t);\n\t\t});\n\n\t\tit(\"passes for remote remove and local obliterate\", () => {\n\t\t\tclient.removeRangeRemote(\n\t\t\t\t0,\n\t\t\t\t\"hello \".length,\n\t\t\t\trefSeq + 1,\n\t\t\t\trefSeq,\n\t\t\t\tclient.getLongClientId(remoteClientId),\n\t\t\t);\n\t\t\tconst localObliterateOp = client.obliterateRangeLocal(0, \"hello \".length);\n\n\t\t\tvalidatePartialLengths(localClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length, localSeq: refSeq },\n\t\t\t\t{ seq: refSeq + 1, len: \"world\".length, localSeq: refSeq + 1 },\n\t\t\t\t{ seq: refSeq + 2, len: \"world\".length, localSeq: refSeq + 2 },\n\t\t\t]);\n\n\t\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));\n\n\t\t\tvalidatePartialLengths(remoteClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"hello world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"world\".length },\n\t\t\t]);\n\t\t});\n\n\t\tit(\"passes for remote remove and remote obliterate\", () => {\n\t\t\tclient.removeRangeRemote(\n\t\t\t\t0,\n\t\t\t\t\"hello \".length,\n\t\t\t\trefSeq + 1,\n\t\t\t\trefSeq,\n\t\t\t\tclient.getLongClientId(remoteClientId),\n\t\t\t);\n\t\t\tobliterateRange({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tstart: 0,\n\t\t\t\tend: \"hello \".length,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId + 1,\n\t\t\t\tseq: refSeq + 2,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\n\t\t\tvalidatePartialLengths(localClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"hello world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"world\".length },\n\t\t\t]);\n\t\t\tvalidatePartialLengths(\n\t\t\t\tremoteClientId,\n\t\t\t\tclient.mergeTree,\n\t\t\t\t[\n\t\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"hello world\".length },\n\t\t\t\t\t{ seq: refSeq + 2, len: \"world\".length },\n\t\t\t\t],\n\t\t\t\t0,\n\t\t\t);\n\t\t\tvalidatePartialLengths(\n\t\t\t\tremoteClientId + 1,\n\t\t\t\tclient.mergeTree,\n\t\t\t\t[\n\t\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"hello world\".length },\n\t\t\t\t\t{ seq: refSeq + 2, len: \"world\".length },\n\t\t\t\t],\n\t\t\t\t0,\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe(\"overlapping obliterate+obliterate\", () => {\n\t\tit(\"passes for local obliterate and remote obliterate\", () => {\n\t\t\tconst localObliterateOp = client.obliterateRangeLocal(0, \"hello \".length);\n\t\t\tobliterateRange({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tstart: 0,\n\t\t\t\tend: \"hello \".length,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\n\t\t\tvalidatePartialLengths(localClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"world\".length },\n\t\t\t]);\n\n\t\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));\n\n\t\t\tvalidatePartialLengths(\n\t\t\t\tremoteClientId,\n\t\t\t\tclient.mergeTree,\n\t\t\t\t[\n\t\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"world\".length, localSeq: refSeq + 1 },\n\t\t\t\t\t{ seq: refSeq + 2, len: \"world\".length, localSeq: refSeq + 2 },\n\t\t\t\t],\n\t\t\t\trefSeq,\n\t\t\t);\n\t\t});\n\n\t\tit(\"passes for remote obliterate and local obliterate\", () => {\n\t\t\tobliterateRange({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tstart: 0,\n\t\t\t\tend: \"hello \".length,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\topArgs: undefined as never,\n\t\t\t});\n\t\t\tconst localObliterateOp = client.obliterateRangeLocal(0, \"hello\".length);\n\n\t\t\tvalidatePartialLengths(localClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"world\".length },\n\t\t\t]);\n\n\t\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));\n\n\t\t\tvalidatePartialLengths(\n\t\t\t\tremoteClientId,\n\t\t\t\tclient.mergeTree,\n\t\t\t\t[\n\t\t\t\t\t{ seq: refSeq, len: \"hello world\".length, localSeq: refSeq },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"world\".length, localSeq: refSeq + 1 },\n\t\t\t\t\t{ seq: refSeq + 2, len: \"\".length, localSeq: refSeq + 2 },\n\t\t\t\t],\n\t\t\t\trefSeq,\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe(\"obliterate with concurrent inserts\", () => {\n\t\tit(\"obliterates when concurrent insert in middle of string\", () => {\n\t\t\tconst localObliterateOp = client.obliterateRangeLocal(0, client.getLength());\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: \"hello\".length,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\ttext: \"more \",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"\");\n\n\t\t\tvalidatePartialLengths(localClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"hellomore world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"\".length, localSeq: refSeq + 1 },\n\t\t\t]);\n\n\t\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));\n\n\t\t\tvalidatePartialLengths(\n\t\t\t\tremoteClientId,\n\t\t\t\tclient.mergeTree,\n\t\t\t\t[\n\t\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"hellomore world\".length },\n\t\t\t\t\t{ seq: refSeq + 2, len: \"\".length, localSeq: refSeq + 2 },\n\t\t\t\t],\n\t\t\t\trefSeq,\n\t\t\t);\n\t\t});\n\n\t\tit(\"obliterate does not affect concurrent insert at start of string\", () => {\n\t\t\tconst localObliterateOp = client.obliterateRangeLocal(0, client.getLength());\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: 0,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\ttext: \"more \",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"more \");\n\n\t\t\tvalidatePartialLengths(localClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"more hello world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"more \".length, localSeq: refSeq + 1 },\n\t\t\t]);\n\n\t\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));\n\n\t\t\tvalidatePartialLengths(\n\t\t\t\tremoteClientId,\n\t\t\t\tclient.mergeTree,\n\t\t\t\t[\n\t\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"more hello world\".length },\n\t\t\t\t\t{ seq: refSeq + 2, len: \"more \".length },\n\t\t\t\t],\n\t\t\t\trefSeq,\n\t\t\t);\n\t\t});\n\n\t\tit(\"obliterate does not affect concurrent insert at end of string\", () => {\n\t\t\tconst localObliterateOp = client.obliterateRangeLocal(0, client.getLength());\n\t\t\tinsertText({\n\t\t\t\tmergeTree: client.mergeTree,\n\t\t\t\tpos: \"hello world\".length,\n\t\t\t\trefSeq,\n\t\t\t\tclientId: remoteClientId,\n\t\t\t\tseq: refSeq + 1,\n\t\t\t\ttext: \"more \",\n\t\t\t\tprops: undefined,\n\t\t\t\topArgs: { op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t});\n\t\t\tassert.equal(client.getText(), \"more \");\n\n\t\t\tvalidatePartialLengths(localClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"hello worldmore \".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"more \".length, localSeq: refSeq + 1 },\n\t\t\t]);\n\n\t\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));\n\n\t\t\tvalidatePartialLengths(\n\t\t\t\tremoteClientId,\n\t\t\t\tclient.mergeTree,\n\t\t\t\t[\n\t\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"hello worldmore \".length },\n\t\t\t\t\t{ seq: refSeq + 2, len: \"more \".length },\n\t\t\t\t],\n\t\t\t\trefSeq,\n\t\t\t);\n\t\t});\n\t});\n});\n"]}
1
+ {"version":3,"file":"obliterate.partialLength.spec.js","sourceRoot":"","sources":["../../src/test/obliterate.partialLength.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { NonCollabClient } from \"../constants.js\";\nimport { MergeTreeDeltaType } from \"../ops.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { TestClient } from \"./testClient.js\";\nimport { useStrictPartialLengthChecks, validatePartialLengths } from \"./testUtils.js\";\n\ndescribe(\"obliterate partial lengths\", () => {\n\tlet client: TestClient;\n\tlet refSeq: number;\n\tlet initialLocalSeq: number;\n\tlet localClientId: number = Number.NaN;\n\tlet remoteClientId: number = Number.NaN;\n\tlet remoteClientId2: number = Number.NaN;\n\n\tuseStrictPartialLengthChecks();\n\n\tbeforeEach(() => {\n\t\tclient = new TestClient({\n\t\t\tmergeTreeEnableObliterate: true,\n\t\t});\n\t\tclient.startOrUpdateCollaboration(\"local\");\n\t\tlocalClientId = client.getClientId();\n\t\tremoteClientId = client.getOrAddShortClientId(\"remote 1\");\n\t\tremoteClientId2 = client.getOrAddShortClientId(\"remote 2\");\n\t\tfor (const char of \"hello world\") {\n\t\t\tclient.applyMsg(\n\t\t\t\tclient.makeOpMessage(\n\t\t\t\t\tclient.insertTextLocal(client.getLength(), char),\n\t\t\t\t\tclient.getCurrentSeq() + 1,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tassert.equal(client.getText(), \"hello world\");\n\t\trefSeq = client.getCurrentSeq();\n\t\tinitialLocalSeq = client.getCollabWindow().localSeq;\n\t});\n\n\tit(\"removes text\", () => {\n\t\tassert.equal(client.getText(), \"hello world\");\n\t\tconst localObliterateOp = client.obliterateRangeLocal(0, \"hello world\".length);\n\t\tassert.equal(client.getText(), \"\");\n\t\tconst minRefSeqForLocalSeq = new Map<number, number>([\n\t\t\t[initialLocalSeq, refSeq],\n\t\t\t[initialLocalSeq + 1, refSeq + 1],\n\t\t]);\n\t\tvalidatePartialLengths(\n\t\t\tlocalClientId,\n\t\t\tclient.mergeTree,\n\t\t\t[\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length, localSeq: initialLocalSeq },\n\t\t\t\t{ seq: refSeq + 1, len: \"\".length, localSeq: initialLocalSeq + 1 },\n\t\t\t],\n\t\t\tminRefSeqForLocalSeq,\n\t\t);\n\n\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 1));\n\n\t\tvalidatePartialLengths(remoteClientId, client.mergeTree, [\n\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t{ seq: refSeq + 1, len: \"\".length },\n\t\t]);\n\t});\n\n\tit(\"correctly applies local remove after local obliterate\", () => {\n\t\tconst localObliterateOp = client.obliterateRangeLocal(0, \"hello \".length);\n\t\tconst localRemoveOp = client.removeRangeLocal(0, \"world\".length);\n\n\t\tconst minRefSeqForLocalSeq = new Map<number, number>([\n\t\t\t[initialLocalSeq, refSeq],\n\t\t\t[initialLocalSeq + 1, refSeq],\n\t\t\t[initialLocalSeq + 2, refSeq],\n\t\t]);\n\t\tvalidatePartialLengths(\n\t\t\tlocalClientId,\n\t\t\tclient.mergeTree,\n\t\t\t[\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length, localSeq: initialLocalSeq },\n\t\t\t\t{ seq: refSeq, len: \"world\".length, localSeq: initialLocalSeq + 1 },\n\t\t\t\t{ seq: refSeq, len: \"\".length, localSeq: initialLocalSeq + 2 },\n\t\t\t],\n\t\t\tminRefSeqForLocalSeq,\n\t\t);\n\n\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 1));\n\t\tclient.applyMsg(client.makeOpMessage(localRemoveOp, refSeq + 2));\n\n\t\tvalidatePartialLengths(remoteClientId, client.mergeTree, [\n\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t{ seq: refSeq + 1, len: \"world\".length },\n\t\t\t{ seq: refSeq + 2, len: \"\".length },\n\t\t]);\n\t});\n\n\tit(\"is correct for different heights\", () => {\n\t\tclient = new TestClient({\n\t\t\tmergeTreeEnableObliterate: true,\n\t\t});\n\t\tclient.startOrUpdateCollaboration(\"local\");\n\n\t\tfor (let i = 0; i < 100; i++) {\n\t\t\tclient.mergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"a\")],\n\t\t\t\tclient.mergeTree.localPerspective,\n\t\t\t\t{ seq: i + 1, clientId: localClientId },\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, client.mergeTree, [{ seq: i + 1, len: i + 1 }]);\n\t\t\tvalidatePartialLengths(remoteClientId, client.mergeTree, [{ seq: i + 1, len: i + 1 }]);\n\n\t\t\trefSeq += 1;\n\t\t}\n\n\t\tconst localObliterateOp = client.obliterateRangeLocal(50, 100);\n\n\t\tvalidatePartialLengths(localClientId, client.mergeTree);\n\n\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 1));\n\n\t\tvalidatePartialLengths(remoteClientId, client.mergeTree);\n\t});\n\n\tdescribe(\"overlapping remove+obliterate\", () => {\n\t\tit(\"passes for local remove and remote obliterate\", () => {\n\t\t\tconst localRemoveOp = client.removeRangeLocal(0, \"hello \".length);\n\t\t\tclient.removeRangeRemote(\n\t\t\t\t0,\n\t\t\t\t\"hello \".length,\n\t\t\t\trefSeq + 1,\n\t\t\t\trefSeq,\n\t\t\t\tclient.getLongClientId(remoteClientId),\n\t\t\t);\n\n\t\t\tconst minRefSeqForLocalSeq = new Map<number, number>([\n\t\t\t\t[initialLocalSeq, refSeq],\n\t\t\t\t[initialLocalSeq + 1, refSeq],\n\t\t\t]);\n\t\t\tvalidatePartialLengths(\n\t\t\t\tlocalClientId,\n\t\t\t\tclient.mergeTree,\n\t\t\t\t[\n\t\t\t\t\t{ seq: refSeq, len: \"hello world\".length, localSeq: initialLocalSeq },\n\t\t\t\t\t{ seq: refSeq, len: \"world\".length, localSeq: initialLocalSeq + 1 },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"world\".length, localSeq: initialLocalSeq },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"world\".length, localSeq: initialLocalSeq + 1 },\n\t\t\t\t],\n\t\t\t\tminRefSeqForLocalSeq,\n\t\t\t);\n\n\t\t\tclient.applyMsg(client.makeOpMessage(localRemoveOp, refSeq + 2));\n\n\t\t\tvalidatePartialLengths(NonCollabClient, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"world\".length },\n\t\t\t]);\n\t\t\tvalidatePartialLengths(remoteClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"world\".length },\n\t\t\t]);\n\t\t});\n\n\t\tit(\"passes for remote remove and local obliterate\", () => {\n\t\t\tconst localObliterateOp = client.obliterateRangeLocal(0, \"hello \".length);\n\t\t\tclient.removeRangeRemote(\n\t\t\t\t0,\n\t\t\t\t\"hello \".length,\n\t\t\t\trefSeq + 1,\n\t\t\t\trefSeq,\n\t\t\t\tclient.getLongClientId(remoteClientId),\n\t\t\t);\n\n\t\t\tconst minRefSeqForLocalSeq = new Map<number, number>([\n\t\t\t\t[initialLocalSeq, refSeq],\n\t\t\t\t[initialLocalSeq + 1, refSeq],\n\t\t\t]);\n\n\t\t\tvalidatePartialLengths(\n\t\t\t\tlocalClientId,\n\t\t\t\tclient.mergeTree,\n\t\t\t\t[\n\t\t\t\t\t{ seq: refSeq, len: \"hello world\".length, localSeq: initialLocalSeq },\n\t\t\t\t\t{ seq: refSeq, len: \"world\".length, localSeq: initialLocalSeq + 1 },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"world\".length, localSeq: initialLocalSeq },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"world\".length, localSeq: initialLocalSeq + 1 },\n\t\t\t\t],\n\t\t\t\tminRefSeqForLocalSeq,\n\t\t\t);\n\n\t\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));\n\n\t\t\tvalidatePartialLengths(NonCollabClient, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"world\".length },\n\t\t\t]);\n\t\t\tvalidatePartialLengths(remoteClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"world\".length },\n\t\t\t]);\n\t\t});\n\n\t\tit(\"passes for remote remove and remote obliterate\", () => {\n\t\t\tclient.removeRangeRemote(\n\t\t\t\t0,\n\t\t\t\t\"hello \".length,\n\t\t\t\trefSeq + 1,\n\t\t\t\trefSeq,\n\t\t\t\tclient.getLongClientId(remoteClientId),\n\t\t\t);\n\t\t\tclient.removeRangeRemote(\n\t\t\t\t0,\n\t\t\t\t\"hello \".length,\n\t\t\t\trefSeq + 2,\n\t\t\t\trefSeq,\n\t\t\t\tclient.getLongClientId(remoteClientId2),\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(NonCollabClient, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"world\".length },\n\t\t\t]);\n\t\t\tvalidatePartialLengths(remoteClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"world\".length },\n\t\t\t]);\n\t\t\tvalidatePartialLengths(remoteClientId2, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"world\".length },\n\t\t\t]);\n\t\t});\n\t});\n\n\tdescribe(\"overlapping obliterate+obliterate\", () => {\n\t\tit(\"passes for local obliterate and remote obliterate\", () => {\n\t\t\tconst localObliterateOp = client.obliterateRangeLocal(0, \"hello \".length);\n\t\t\tclient.obliterateRangeRemote(\n\t\t\t\t0,\n\t\t\t\t\"hello \".length,\n\t\t\t\trefSeq + 1,\n\t\t\t\trefSeq,\n\t\t\t\tclient.getLongClientId(remoteClientId),\n\t\t\t);\n\n\t\t\tconst minRefSeqForLocalSeq = new Map<number, number>([\n\t\t\t\t[initialLocalSeq, refSeq],\n\t\t\t\t[initialLocalSeq + 1, refSeq],\n\t\t\t]);\n\t\t\tvalidatePartialLengths(\n\t\t\t\tlocalClientId,\n\t\t\t\tclient.mergeTree,\n\t\t\t\t[\n\t\t\t\t\t{ seq: refSeq, len: \"hello world\".length, localSeq: initialLocalSeq },\n\t\t\t\t\t{ seq: refSeq, len: \"world\".length, localSeq: initialLocalSeq + 1 },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"world\".length, localSeq: initialLocalSeq },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"world\".length, localSeq: initialLocalSeq + 1 },\n\t\t\t\t],\n\t\t\t\tminRefSeqForLocalSeq,\n\t\t\t);\n\n\t\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));\n\n\t\t\tvalidatePartialLengths(NonCollabClient, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"world\".length },\n\t\t\t]);\n\t\t\tvalidatePartialLengths(remoteClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"world\".length },\n\t\t\t]);\n\t\t});\n\t});\n\n\tdescribe(\"obliterate with concurrent inserts\", () => {\n\t\tit(\"obliterates when concurrent insert in middle of string\", () => {\n\t\t\tconst localObliterateOp = client.obliterateRangeLocal(0, client.getLength());\n\n\t\t\tclient.insertTextRemote(\n\t\t\t\t\"hello\".length,\n\t\t\t\t\"more \",\n\t\t\t\tundefined,\n\t\t\t\trefSeq + 1,\n\t\t\t\trefSeq,\n\t\t\t\tclient.getLongClientId(remoteClientId),\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"\");\n\n\t\t\tconst minRefSeqForLocalSeq = new Map<number, number>([\n\t\t\t\t[initialLocalSeq, refSeq],\n\t\t\t\t[initialLocalSeq + 1, refSeq],\n\t\t\t]);\n\t\t\tvalidatePartialLengths(\n\t\t\t\tlocalClientId,\n\t\t\t\tclient.mergeTree,\n\t\t\t\t[\n\t\t\t\t\t{ seq: refSeq, len: \"hello world\".length, localSeq: initialLocalSeq },\n\t\t\t\t\t{ seq: refSeq, len: \"\".length, localSeq: initialLocalSeq + 1 },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"hellomore world\".length, localSeq: initialLocalSeq },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"\".length, localSeq: initialLocalSeq + 1 },\n\t\t\t\t],\n\t\t\t\tminRefSeqForLocalSeq,\n\t\t\t);\n\n\t\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));\n\n\t\t\tvalidatePartialLengths(NonCollabClient, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"hellomore world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"\".length },\n\t\t\t]);\n\t\t\tvalidatePartialLengths(remoteClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hellomore world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"hellomore world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"\".length },\n\t\t\t]);\n\t\t});\n\n\t\tit(\"obliterate does not affect concurrent insert at start of string\", () => {\n\t\t\tconst localObliterateOp = client.obliterateRangeLocal(0, client.getLength());\n\t\t\tclient.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"more \",\n\t\t\t\tundefined,\n\t\t\t\trefSeq + 1,\n\t\t\t\trefSeq,\n\t\t\t\tclient.getLongClientId(remoteClientId),\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"more \");\n\n\t\t\tconst minRefSeqForLocalSeq = new Map<number, number>([\n\t\t\t\t[initialLocalSeq, refSeq],\n\t\t\t\t[initialLocalSeq + 1, refSeq],\n\t\t\t]);\n\t\t\tvalidatePartialLengths(\n\t\t\t\tlocalClientId,\n\t\t\t\tclient.mergeTree,\n\t\t\t\t[\n\t\t\t\t\t{ seq: refSeq, len: \"hello world\".length, localSeq: initialLocalSeq },\n\t\t\t\t\t{ seq: refSeq, len: \"\".length, localSeq: initialLocalSeq + 1 },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"more hello world\".length, localSeq: initialLocalSeq },\n\t\t\t\t\t{ seq: refSeq + 1, len: \"more \".length, localSeq: initialLocalSeq + 1 },\n\t\t\t\t],\n\t\t\t\tminRefSeqForLocalSeq,\n\t\t\t);\n\n\t\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));\n\n\t\t\tvalidatePartialLengths(NonCollabClient, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"more hello world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"more \".length },\n\t\t\t]);\n\t\t\tvalidatePartialLengths(remoteClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"more hello world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"more hello world\".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"more \".length },\n\t\t\t]);\n\t\t});\n\n\t\tit(\"obliterate does not affect concurrent insert at end of string\", () => {\n\t\t\tconst localObliterateOp = client.obliterateRangeLocal(0, client.getLength());\n\t\t\tclient.insertTextRemote(\n\t\t\t\t\"hello world\".length,\n\t\t\t\t\"more \",\n\t\t\t\tundefined,\n\t\t\t\trefSeq + 1,\n\t\t\t\trefSeq,\n\t\t\t\tclient.getLongClientId(remoteClientId),\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"more \");\n\n\t\t\tvalidatePartialLengths(localClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length, localSeq: initialLocalSeq },\n\t\t\t\t{ seq: refSeq, len: \"\".length, localSeq: initialLocalSeq + 1 },\n\t\t\t\t{ seq: refSeq + 1, len: \"hello worldmore \".length, localSeq: initialLocalSeq },\n\t\t\t\t{ seq: refSeq + 1, len: \"more \".length, localSeq: initialLocalSeq + 1 },\n\t\t\t]);\n\n\t\t\tclient.applyMsg(client.makeOpMessage(localObliterateOp, refSeq + 2));\n\n\t\t\tvalidatePartialLengths(NonCollabClient, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"hello worldmore \".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"more \".length },\n\t\t\t]);\n\t\t\tvalidatePartialLengths(remoteClientId, client.mergeTree, [\n\t\t\t\t{ seq: refSeq, len: \"hello worldmore \".length },\n\t\t\t\t{ seq: refSeq + 1, len: \"hello worldmore \".length },\n\t\t\t\t{ seq: refSeq + 2, len: \"more \".length },\n\t\t\t]);\n\t\t});\n\t});\n\n\tdescribe(\"Overlapping remote/local obliterate with insertion within the collab window\", () => {\n\t\tit(\"acked insertion\", () => {\n\t\t\tlet seq = client.getCurrentSeq();\n\t\t\tconst initialSeq = seq;\n\t\t\tclient.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"more \",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\trefSeq,\n\t\t\t\tclient.getLongClientId(remoteClientId),\n\t\t\t);\n\t\t\tconst insertSeq = seq;\n\n\t\t\tclient.obliterateRangeLocal(0, 5);\n\t\t\tconst localRemoveLocalSeq = client.getCollabWindow().localSeq;\n\t\t\tclient.obliterateRangeRemote(\n\t\t\t\t0,\n\t\t\t\t5,\n\t\t\t\t++seq,\n\t\t\t\tinsertSeq,\n\t\t\t\tclient.getLongClientId(remoteClientId),\n\t\t\t);\n\t\t\tconst obliterateSeq = seq;\n\t\t\tvalidatePartialLengths(localClientId, client.mergeTree, [\n\t\t\t\t{ seq: initialSeq, localSeq: initialLocalSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: insertSeq, localSeq: initialLocalSeq, len: \"more hello world\".length },\n\t\t\t\t{ seq: obliterateSeq, localSeq: initialLocalSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: initialSeq, localSeq: localRemoveLocalSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: insertSeq, localSeq: localRemoveLocalSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: obliterateSeq, localSeq: localRemoveLocalSeq, len: \"hello world\".length },\n\t\t\t]);\n\t\t});\n\n\t\tit(\"local insertion\", () => {\n\t\t\tlet seq = client.getCurrentSeq();\n\t\t\tconst initialSeq = seq;\n\t\t\tclient.insertTextLocal(6, \"more \");\n\t\t\tconst insertLocalSeq = client.getCollabWindow().localSeq;\n\n\t\t\tclient.obliterateRangeLocal(6, 11); // Remove the added \"more \"\n\t\t\tconst localRemoveLocalSeq = client.getCollabWindow().localSeq;\n\t\t\tclient.obliterateRangeRemote(\n\t\t\t\t0,\n\t\t\t\t\"hello world\".length,\n\t\t\t\t++seq,\n\t\t\t\tinitialSeq,\n\t\t\t\tclient.getLongClientId(remoteClientId),\n\t\t\t);\n\t\t\tconst obliterateSeq = seq;\n\t\t\tvalidatePartialLengths(localClientId, client.mergeTree, [\n\t\t\t\t{ seq: initialSeq, localSeq: initialLocalSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: initialSeq, localSeq: insertLocalSeq, len: \"hello more world\".length },\n\t\t\t\t{ seq: initialSeq, localSeq: localRemoveLocalSeq, len: \"hello world\".length },\n\t\t\t\t{ seq: obliterateSeq, localSeq: initialLocalSeq, len: \"\".length },\n\t\t\t\t{ seq: obliterateSeq, localSeq: insertLocalSeq, len: \"\".length },\n\t\t\t\t{ seq: obliterateSeq, localSeq: localRemoveLocalSeq, len: \"\".length },\n\t\t\t]);\n\t\t});\n\t});\n});\n"]}