@fluidframework/merge-tree 2.41.0 → 2.43.0-343119

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 (154) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/client.d.ts +9 -6
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +79 -36
  5. package/dist/client.js.map +1 -1
  6. package/dist/collections/list.d.ts +95 -5
  7. package/dist/collections/list.d.ts.map +1 -1
  8. package/dist/collections/list.js +67 -5
  9. package/dist/collections/list.js.map +1 -1
  10. package/dist/constants.d.ts +5 -0
  11. package/dist/constants.d.ts.map +1 -1
  12. package/dist/constants.js +6 -1
  13. package/dist/constants.js.map +1 -1
  14. package/dist/index.d.ts +1 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +3 -2
  17. package/dist/index.js.map +1 -1
  18. package/dist/mergeTree.d.ts +9 -9
  19. package/dist/mergeTree.d.ts.map +1 -1
  20. package/dist/mergeTree.js +15 -7
  21. package/dist/mergeTree.js.map +1 -1
  22. package/dist/perspective.d.ts +15 -0
  23. package/dist/perspective.d.ts.map +1 -1
  24. package/dist/perspective.js +25 -1
  25. package/dist/perspective.js.map +1 -1
  26. package/dist/revertibles.js +1 -1
  27. package/dist/revertibles.js.map +1 -1
  28. package/dist/stamps.d.ts +1 -0
  29. package/dist/stamps.d.ts.map +1 -1
  30. package/dist/stamps.js +5 -1
  31. package/dist/stamps.js.map +1 -1
  32. package/dist/test/beastTest.spec.js +1 -1
  33. package/dist/test/beastTest.spec.js.map +1 -1
  34. package/dist/test/client.annotateMarker.spec.js +1 -1
  35. package/dist/test/client.annotateMarker.spec.js.map +1 -1
  36. package/dist/test/client.applyMsg.spec.js +25 -25
  37. package/dist/test/client.applyMsg.spec.js.map +1 -1
  38. package/dist/test/client.applyStashedOpFarm.spec.d.ts.map +1 -1
  39. package/dist/test/client.applyStashedOpFarm.spec.js +3 -3
  40. package/dist/test/client.applyStashedOpFarm.spec.js.map +1 -1
  41. package/dist/test/client.attributionFarm.spec.js +1 -1
  42. package/dist/test/client.attributionFarm.spec.js.map +1 -1
  43. package/dist/test/client.getPosition.spec.js +1 -0
  44. package/dist/test/client.getPosition.spec.js.map +1 -1
  45. package/dist/test/client.localReference.spec.js +62 -48
  46. package/dist/test/client.localReference.spec.js.map +1 -1
  47. package/dist/test/client.localReferenceFarm.spec.js +1 -0
  48. package/dist/test/client.localReferenceFarm.spec.js.map +1 -1
  49. package/dist/test/client.reconnectFarm.spec.js +1 -1
  50. package/dist/test/client.reconnectFarm.spec.js.map +1 -1
  51. package/dist/test/client.rollback.spec.js +8 -6
  52. package/dist/test/client.rollback.spec.js.map +1 -1
  53. package/dist/test/client.searchForMarker.spec.js +2 -2
  54. package/dist/test/client.searchForMarker.spec.js.map +1 -1
  55. package/dist/test/clientTestHelper.js +1 -1
  56. package/dist/test/clientTestHelper.js.map +1 -1
  57. package/dist/test/mergeTree.annotate.spec.js +25 -25
  58. package/dist/test/mergeTree.annotate.spec.js.map +1 -1
  59. package/dist/test/mergeTree.markRangeRemoved.spec.js +1 -1
  60. package/dist/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
  61. package/dist/test/obliterate.spec.js +4 -4
  62. package/dist/test/obliterate.spec.js.map +1 -1
  63. package/dist/test/resetPendingSegmentsToOp.spec.js +14 -14
  64. package/dist/test/resetPendingSegmentsToOp.spec.js.map +1 -1
  65. package/dist/test/snapshot.utils.js +1 -1
  66. package/dist/test/snapshot.utils.js.map +1 -1
  67. package/dist/test/sortedSegmentSet.spec.js +3 -3
  68. package/dist/test/sortedSegmentSet.spec.js.map +1 -1
  69. package/dist/test/testClient.js +3 -3
  70. package/dist/test/testClient.js.map +1 -1
  71. package/dist/test/tracking.spec.js +7 -7
  72. package/dist/test/tracking.spec.js.map +1 -1
  73. package/dist/test/wordUnitTests.spec.js.map +1 -1
  74. package/lib/client.d.ts +9 -6
  75. package/lib/client.d.ts.map +1 -1
  76. package/lib/client.js +81 -38
  77. package/lib/client.js.map +1 -1
  78. package/lib/collections/list.d.ts +95 -5
  79. package/lib/collections/list.d.ts.map +1 -1
  80. package/lib/collections/list.js +67 -5
  81. package/lib/collections/list.js.map +1 -1
  82. package/lib/constants.d.ts +5 -0
  83. package/lib/constants.d.ts.map +1 -1
  84. package/lib/constants.js +5 -0
  85. package/lib/constants.js.map +1 -1
  86. package/lib/index.d.ts +1 -1
  87. package/lib/index.d.ts.map +1 -1
  88. package/lib/index.js +1 -1
  89. package/lib/index.js.map +1 -1
  90. package/lib/mergeTree.d.ts +9 -9
  91. package/lib/mergeTree.d.ts.map +1 -1
  92. package/lib/mergeTree.js +15 -7
  93. package/lib/mergeTree.js.map +1 -1
  94. package/lib/perspective.d.ts +15 -0
  95. package/lib/perspective.d.ts.map +1 -1
  96. package/lib/perspective.js +23 -0
  97. package/lib/perspective.js.map +1 -1
  98. package/lib/revertibles.js +1 -1
  99. package/lib/revertibles.js.map +1 -1
  100. package/lib/stamps.d.ts +1 -0
  101. package/lib/stamps.d.ts.map +1 -1
  102. package/lib/stamps.js +4 -1
  103. package/lib/stamps.js.map +1 -1
  104. package/lib/test/beastTest.spec.js +1 -1
  105. package/lib/test/beastTest.spec.js.map +1 -1
  106. package/lib/test/client.annotateMarker.spec.js +1 -1
  107. package/lib/test/client.annotateMarker.spec.js.map +1 -1
  108. package/lib/test/client.applyMsg.spec.js +25 -25
  109. package/lib/test/client.applyMsg.spec.js.map +1 -1
  110. package/lib/test/client.applyStashedOpFarm.spec.d.ts.map +1 -1
  111. package/lib/test/client.applyStashedOpFarm.spec.js +3 -3
  112. package/lib/test/client.applyStashedOpFarm.spec.js.map +1 -1
  113. package/lib/test/client.attributionFarm.spec.js +1 -1
  114. package/lib/test/client.attributionFarm.spec.js.map +1 -1
  115. package/lib/test/client.getPosition.spec.js +1 -0
  116. package/lib/test/client.getPosition.spec.js.map +1 -1
  117. package/lib/test/client.localReference.spec.js +62 -48
  118. package/lib/test/client.localReference.spec.js.map +1 -1
  119. package/lib/test/client.localReferenceFarm.spec.js +1 -0
  120. package/lib/test/client.localReferenceFarm.spec.js.map +1 -1
  121. package/lib/test/client.reconnectFarm.spec.js +1 -1
  122. package/lib/test/client.reconnectFarm.spec.js.map +1 -1
  123. package/lib/test/client.rollback.spec.js +8 -6
  124. package/lib/test/client.rollback.spec.js.map +1 -1
  125. package/lib/test/client.searchForMarker.spec.js +2 -2
  126. package/lib/test/client.searchForMarker.spec.js.map +1 -1
  127. package/lib/test/clientTestHelper.js +1 -1
  128. package/lib/test/clientTestHelper.js.map +1 -1
  129. package/lib/test/mergeTree.annotate.spec.js +25 -25
  130. package/lib/test/mergeTree.annotate.spec.js.map +1 -1
  131. package/lib/test/mergeTree.markRangeRemoved.spec.js +1 -1
  132. package/lib/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
  133. package/lib/test/obliterate.spec.js +4 -4
  134. package/lib/test/obliterate.spec.js.map +1 -1
  135. package/lib/test/resetPendingSegmentsToOp.spec.js +14 -14
  136. package/lib/test/resetPendingSegmentsToOp.spec.js.map +1 -1
  137. package/lib/test/snapshot.utils.js +1 -1
  138. package/lib/test/snapshot.utils.js.map +1 -1
  139. package/lib/test/sortedSegmentSet.spec.js +3 -3
  140. package/lib/test/sortedSegmentSet.spec.js.map +1 -1
  141. package/lib/test/testClient.js +3 -3
  142. package/lib/test/testClient.js.map +1 -1
  143. package/lib/test/tracking.spec.js +7 -7
  144. package/lib/test/tracking.spec.js.map +1 -1
  145. package/lib/test/wordUnitTests.spec.js.map +1 -1
  146. package/package.json +16 -16
  147. package/src/client.ts +117 -50
  148. package/src/collections/list.ts +101 -5
  149. package/src/constants.ts +6 -0
  150. package/src/index.ts +3 -0
  151. package/src/mergeTree.ts +30 -24
  152. package/src/perspective.ts +26 -0
  153. package/src/revertibles.ts +1 -1
  154. package/src/stamps.ts +9 -1
@@ -1 +1 @@
1
- {"version":3,"file":"obliterate.spec.js","sourceRoot":"","sources":["../../src/test/obliterate.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 type { ISegmentPrivate, ObliterateInfo } from \"../mergeTreeNodes.js\";\nimport { MergeTreeDeltaType } from \"../ops.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { TestClient } from \"./testClient.js\";\nimport { makeRemoteClient } from \"./testUtils.js\";\n\ndescribe(\"obliterate\", () => {\n\tlet client: TestClient;\n\tlet refSeq: number;\n\tconst remoteClient1 = makeRemoteClient({ clientId: 18 });\n\tconst remoteClient2 = makeRemoteClient({ clientId: 19 });\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\tclient.obliterateRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\t});\n\n\tdescribe(\"concurrent obliterate and insert\", () => {\n\t\tit(\"removes text for obliterate then insert\", () => {\n\t\t\tclient.mergeTree.obliterateRange(\n\t\t\t\t0,\n\t\t\t\tclient.getLength(),\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 1 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tclient.mergeTree.insertSegments(\n\t\t\t\t1,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tremoteClient2.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient2.stampAt({ seq: refSeq + 2 }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"\");\n\t\t});\n\t\tit(\"removes text for insert then obliterate when deleting entire string\", () => {\n\t\t\tclient.mergeTree.insertSegments(\n\t\t\t\t1,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tremoteClient2.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient2.stampAt({ seq: refSeq + 1 }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\t\t\tclient.mergeTree.obliterateRange(\n\t\t\t\t0,\n\t\t\t\t\"hello world\".length,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 2 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"\");\n\t\t});\n\t\tit(\"removes text for insert then obliterate\", () => {\n\t\t\tclient.mergeTree.insertSegments(\n\t\t\t\t5,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tremoteClient2.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient2.stampAt({ seq: refSeq + 1 }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\t\t\tclient.mergeTree.obliterateRange(\n\t\t\t\t1,\n\t\t\t\t\"hello world\".length,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 2 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"h\");\n\t\t});\n\t});\n\n\tdescribe(\"endpoint behavior\", () => {\n\t\tit(\"does not expand to include text inserted at start\", () => {\n\t\t\tclient.mergeTree.obliterateRange(\n\t\t\t\t5,\n\t\t\t\tclient.getLength(),\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 1 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tclient.mergeTree.insertSegments(\n\t\t\t\t5,\n\t\t\t\t[TextSegment.make(\"XXX\")],\n\t\t\t\tremoteClient2.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient2.stampAt({ seq: refSeq + 2 }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"helloXXX\");\n\t\t});\n\t\tit(\"does not expand to include text inserted at end\", () => {\n\t\t\tclient.mergeTree.obliterateRange(\n\t\t\t\t0,\n\t\t\t\t\"hello\".length,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 1 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tclient.mergeTree.insertSegments(\n\t\t\t\t5,\n\t\t\t\t[TextSegment.make(\"XXX\")],\n\t\t\t\tremoteClient2.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient2.stampAt({ seq: refSeq + 2 }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"XXX world\");\n\t\t});\n\t});\n\n\tdescribe(\"local obliterate with concurrent inserts\", () => {\n\t\tit(\"removes range when pending local obliterate op\", () => {\n\t\t\tclient.obliterateRangeLocal(0, client.getLength());\n\t\t\tclient.mergeTree.insertSegments(\n\t\t\t\t1,\n\t\t\t\t[TextSegment.make(\"XXX\")],\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 1 }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"\");\n\t\t});\n\t});\n\n\tdescribe(\"local references\", () => {\n\t\tit(\"cleans up local references once the collab window advances enough\", () => {\n\t\t\tconst client2 = new TestClient({ mergeTreeEnableObliterate: true });\n\t\t\tclient2.startOrUpdateCollaboration(\"client2\");\n\n\t\t\tconst obliterateStart = 0;\n\t\t\tconst obliterateEnd = client.getLength();\n\t\t\tconst startSeg = client.getContainingSegment<ISegmentPrivate>(obliterateStart);\n\t\t\tconst endSeg = client.getContainingSegment<ISegmentPrivate>(obliterateEnd);\n\t\t\tlet seq = refSeq;\n\t\t\tclient.mergeTree.obliterateRange(\n\t\t\t\tobliterateStart,\n\t\t\t\tobliterateEnd,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: ++seq }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tclient.mergeTree.insertSegments(\n\t\t\t\t1,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tremoteClient2.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient2.stampAt({ seq: ++seq }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"\");\n\n\t\t\tstartSeg.segment?.localRefs?.walkReferences((ref) => {\n\t\t\t\tconst oblProps = ref.properties?.obliterate as ObliterateInfo;\n\t\t\t\tassert(oblProps?.start !== undefined, \"start ref should NOT be removed\");\n\t\t\t});\n\t\t\tendSeg.segment?.localRefs?.walkReferences((ref) => {\n\t\t\t\tconst oblProps = ref.properties?.obliterate as ObliterateInfo;\n\t\t\t\tassert(oblProps?.end !== undefined, \"end ref should NOT be removed\");\n\t\t\t});\n\n\t\t\t// this will force Zamboni to run\n\t\t\tfor (let i = 0; i < 5; i++) {\n\t\t\t\tconst insert = client.makeOpMessage(\n\t\t\t\t\tclient.insertTextLocal(client.getLength(), i.toString()),\n\t\t\t\t\t++seq,\n\t\t\t\t);\n\t\t\t\tinsert.minimumSequenceNumber = seq - 1;\n\t\t\t\tclient.applyMsg(insert);\n\t\t\t\tclient2.applyMsg(insert);\n\t\t\t}\n\n\t\t\t// want to check that the start and end segment don't have the obliterate refs on them\n\t\t\tstartSeg.segment?.localRefs?.walkReferences((ref) => {\n\t\t\t\tconst oblProps = ref.properties?.obliterate as ObliterateInfo;\n\t\t\t\tassert(oblProps.start === undefined, \"start ref should be removed\");\n\t\t\t});\n\t\t\tendSeg.segment?.localRefs?.walkReferences((ref) => {\n\t\t\t\tconst oblProps = ref.properties?.obliterate as ObliterateInfo;\n\t\t\t\tassert(oblProps.end === undefined, \"end ref should be removed\");\n\t\t\t});\n\t\t});\n\t});\n});\n"]}
1
+ {"version":3,"file":"obliterate.spec.js","sourceRoot":"","sources":["../../src/test/obliterate.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 type { ISegmentPrivate, ObliterateInfo } from \"../mergeTreeNodes.js\";\nimport { MergeTreeDeltaType } from \"../ops.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { TestClient } from \"./testClient.js\";\nimport { makeRemoteClient } from \"./testUtils.js\";\n\ndescribe(\"obliterate\", () => {\n\tlet client: TestClient;\n\tlet refSeq: number;\n\tconst remoteClient1 = makeRemoteClient({ clientId: 18 });\n\tconst remoteClient2 = makeRemoteClient({ clientId: 19 });\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\tclient.obliterateRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\t});\n\n\tdescribe(\"concurrent obliterate and insert\", () => {\n\t\tit(\"removes text for obliterate then insert\", () => {\n\t\t\tclient.mergeTree.obliterateRange(\n\t\t\t\t0,\n\t\t\t\tclient.getLength(),\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 1 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tclient.mergeTree.insertSegments(\n\t\t\t\t1,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tremoteClient2.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient2.stampAt({ seq: refSeq + 2 }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"\");\n\t\t});\n\t\tit(\"removes text for insert then obliterate when deleting entire string\", () => {\n\t\t\tclient.mergeTree.insertSegments(\n\t\t\t\t1,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tremoteClient2.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient2.stampAt({ seq: refSeq + 1 }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\t\t\tclient.mergeTree.obliterateRange(\n\t\t\t\t0,\n\t\t\t\t\"hello world\".length,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 2 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"\");\n\t\t});\n\t\tit(\"removes text for insert then obliterate\", () => {\n\t\t\tclient.mergeTree.insertSegments(\n\t\t\t\t5,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tremoteClient2.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient2.stampAt({ seq: refSeq + 1 }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\t\t\tclient.mergeTree.obliterateRange(\n\t\t\t\t1,\n\t\t\t\t\"hello world\".length,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 2 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"h\");\n\t\t});\n\t});\n\n\tdescribe(\"endpoint behavior\", () => {\n\t\tit(\"does not expand to include text inserted at start\", () => {\n\t\t\tclient.mergeTree.obliterateRange(\n\t\t\t\t5,\n\t\t\t\tclient.getLength(),\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 1 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tclient.mergeTree.insertSegments(\n\t\t\t\t5,\n\t\t\t\t[TextSegment.make(\"XXX\")],\n\t\t\t\tremoteClient2.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient2.stampAt({ seq: refSeq + 2 }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"helloXXX\");\n\t\t});\n\t\tit(\"does not expand to include text inserted at end\", () => {\n\t\t\tclient.mergeTree.obliterateRange(\n\t\t\t\t0,\n\t\t\t\t\"hello\".length,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 1 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tclient.mergeTree.insertSegments(\n\t\t\t\t5,\n\t\t\t\t[TextSegment.make(\"XXX\")],\n\t\t\t\tremoteClient2.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient2.stampAt({ seq: refSeq + 2 }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"XXX world\");\n\t\t});\n\t});\n\n\tdescribe(\"local obliterate with concurrent inserts\", () => {\n\t\tit(\"removes range when pending local obliterate op\", () => {\n\t\t\tclient.obliterateRangeLocal(0, client.getLength());\n\t\t\tclient.mergeTree.insertSegments(\n\t\t\t\t1,\n\t\t\t\t[TextSegment.make(\"XXX\")],\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 1 }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"\");\n\t\t});\n\t});\n\n\tdescribe(\"local references\", () => {\n\t\tit(\"cleans up local references once the collab window advances enough\", () => {\n\t\t\tconst client2 = new TestClient({ mergeTreeEnableObliterate: true });\n\t\t\tclient2.startOrUpdateCollaboration(\"client2\");\n\n\t\t\tconst obliterateStart = 0;\n\t\t\tconst obliterateEnd = client.getLength();\n\t\t\tconst startSeg = client.getContainingSegment<ISegmentPrivate>(obliterateStart);\n\t\t\tconst endSeg = client.getContainingSegment<ISegmentPrivate>(obliterateEnd);\n\t\t\tlet seq = refSeq;\n\t\t\tclient.mergeTree.obliterateRange(\n\t\t\t\tobliterateStart,\n\t\t\t\tobliterateEnd,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: ++seq }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tclient.mergeTree.insertSegments(\n\t\t\t\t1,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tremoteClient2.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient2.stampAt({ seq: ++seq }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\t\t\tassert.equal(client.getText(), \"\");\n\n\t\t\tstartSeg?.segment.localRefs?.walkReferences((ref) => {\n\t\t\t\tconst oblProps = ref.properties?.obliterate as ObliterateInfo;\n\t\t\t\tassert(oblProps?.start !== undefined, \"start ref should NOT be removed\");\n\t\t\t});\n\t\t\tendSeg?.segment.localRefs?.walkReferences((ref) => {\n\t\t\t\tconst oblProps = ref.properties?.obliterate as ObliterateInfo;\n\t\t\t\tassert(oblProps?.end !== undefined, \"end ref should NOT be removed\");\n\t\t\t});\n\n\t\t\t// this will force Zamboni to run\n\t\t\tfor (let i = 0; i < 5; i++) {\n\t\t\t\tconst insert = client.makeOpMessage(\n\t\t\t\t\tclient.insertTextLocal(client.getLength(), i.toString()),\n\t\t\t\t\t++seq,\n\t\t\t\t);\n\t\t\t\tinsert.minimumSequenceNumber = seq - 1;\n\t\t\t\tclient.applyMsg(insert);\n\t\t\t\tclient2.applyMsg(insert);\n\t\t\t}\n\n\t\t\t// want to check that the start and end segment don't have the obliterate refs on them\n\t\t\tstartSeg?.segment.localRefs?.walkReferences((ref) => {\n\t\t\t\tconst oblProps = ref.properties?.obliterate as ObliterateInfo;\n\t\t\t\tassert(oblProps.start === undefined, \"start ref should be removed\");\n\t\t\t});\n\t\t\tendSeg?.segment.localRefs?.walkReferences((ref) => {\n\t\t\t\tconst oblProps = ref.properties?.obliterate as ObliterateInfo;\n\t\t\t\tassert(oblProps.end === undefined, \"end ref should be removed\");\n\t\t\t});\n\t\t});\n\t});\n});\n"]}
@@ -72,7 +72,7 @@ describe("resetPendingSegmentsToOp", () => {
72
72
  const oldops = opList;
73
73
  const pending = [...client.mergeTree.pendingSegments.map((n) => n.data)];
74
74
  opList = oldops.map((op) => ({
75
- op: client.regeneratePendingOp(op.op, pending.shift()),
75
+ op: client.regeneratePendingOp(op.op, pending.shift(), false),
76
76
  refSeq: client.getCurrentSeq(),
77
77
  }));
78
78
  applyOpList(client);
@@ -82,7 +82,7 @@ describe("resetPendingSegmentsToOp", () => {
82
82
  const oldops = opList;
83
83
  const pending = [...client.mergeTree.pendingSegments.map((n) => n.data)];
84
84
  opList = oldops.map((op) => ({
85
- op: client.regeneratePendingOp(op.op, pending.shift()),
85
+ op: client.regeneratePendingOp(op.op, pending.shift(), false),
86
86
  refSeq: client.getCurrentSeq(),
87
87
  }));
88
88
  // we expect a nack op per segment since our original ops split segments
@@ -110,7 +110,7 @@ describe("resetPendingSegmentsToOp", () => {
110
110
  refSeq: client.getCurrentSeq(),
111
111
  });
112
112
  opList.push({
113
- op: client.regeneratePendingOp(opList.shift().op, client.mergeTree.pendingSegments.first.data),
113
+ op: client.regeneratePendingOp(opList.shift().op, client.mergeTree.pendingSegments.first.data, false),
114
114
  refSeq: client.getCurrentSeq(),
115
115
  });
116
116
  // we expect a nack op per segment since our original ops split segments
@@ -128,7 +128,7 @@ describe("resetPendingSegmentsToOp", () => {
128
128
  const oldops = opList;
129
129
  const pending = [...client.mergeTree.pendingSegments.map((n) => n.data)];
130
130
  opList = oldops.map((op) => ({
131
- op: client.regeneratePendingOp(op.op, pending.shift()),
131
+ op: client.regeneratePendingOp(op.op, pending.shift(), false),
132
132
  refSeq: client.getCurrentSeq(),
133
133
  }));
134
134
  node_assert_1.strict.equal(client.mergeTree.pendingSegments?.length, expectedSegmentCount * 2);
@@ -153,7 +153,7 @@ describe("resetPendingSegmentsToOp", () => {
153
153
  refSeq: client.getCurrentSeq(),
154
154
  });
155
155
  opList.push({
156
- op: client.regeneratePendingOp(opList.shift().op, client.mergeTree.pendingSegments.first.data),
156
+ op: client.regeneratePendingOp(opList.shift().op, client.mergeTree.pendingSegments.first.data, false),
157
157
  refSeq: client.getCurrentSeq(),
158
158
  });
159
159
  // we expect a nack op per segment since our original ops split segments
@@ -171,7 +171,7 @@ describe("resetPendingSegmentsToOp", () => {
171
171
  const oldops = opList;
172
172
  const pending = [...client.mergeTree.pendingSegments.map((n) => n.data)];
173
173
  opList = oldops.map((op) => ({
174
- op: client.regeneratePendingOp(op.op, pending.shift()),
174
+ op: client.regeneratePendingOp(op.op, pending.shift(), false),
175
175
  refSeq: client.getCurrentSeq(),
176
176
  }));
177
177
  // we expect a nack op per segment since our original ops split segments
@@ -191,14 +191,14 @@ describe("resetPendingSegmentsToOp", () => {
191
191
  prop1: "foo",
192
192
  });
193
193
  (0, node_assert_1.strict)(insertOp);
194
- const { segment } = client.getContainingSegment(0);
194
+ const { segment } = client.getContainingSegment(0) ?? {};
195
195
  (0, node_assert_1.strict)(segment !== undefined && mergeTreeNodes_js_1.Marker.is(segment));
196
196
  client.annotateMarker(segment, { prop2: "bar" });
197
197
  const otherClient = new testClient_js_1.TestClient();
198
198
  otherClient.startOrUpdateCollaboration("other user");
199
- const regeneratedInsert = client.regeneratePendingOp(insertOp, client.mergeTree.pendingSegments.first.data);
199
+ const regeneratedInsert = client.regeneratePendingOp(insertOp, client.mergeTree.pendingSegments.first.data, false);
200
200
  otherClient.applyMsg(client.makeOpMessage(regeneratedInsert, 1), false);
201
- const { segment: otherSegment } = otherClient.getContainingSegment(0);
201
+ const { segment: otherSegment } = otherClient.getContainingSegment(0) ?? {};
202
202
  (0, node_assert_1.strict)(otherSegment !== undefined && mergeTreeNodes_js_1.Marker.is(otherSegment));
203
203
  // `clone` here is because properties use a Object.create(null); to compare strict equal the prototype chain
204
204
  // should therefore not include Object.
@@ -210,9 +210,9 @@ describe("resetPendingSegmentsToOp", () => {
210
210
  client.annotateRangeLocal(0, 3, { prop2: "bar" });
211
211
  const otherClient = new testClient_js_1.TestClient();
212
212
  otherClient.startOrUpdateCollaboration("other user");
213
- const regeneratedInsert = client.regeneratePendingOp(insertOp, client.mergeTree.pendingSegments.first.data);
213
+ const regeneratedInsert = client.regeneratePendingOp(insertOp, client.mergeTree.pendingSegments.first.data, false);
214
214
  otherClient.applyMsg(client.makeOpMessage(regeneratedInsert, 1), false);
215
- const { segment: otherSegment } = otherClient.getContainingSegment(0);
215
+ const { segment: otherSegment } = otherClient.getContainingSegment(0) ?? {};
216
216
  (0, node_assert_1.strict)(otherSegment !== undefined && textSegment_js_1.TextSegment.is(otherSegment));
217
217
  node_assert_1.strict.deepStrictEqual(otherSegment.properties, (0, properties_js_1.clone)({ prop1: "foo" }));
218
218
  });
@@ -222,9 +222,9 @@ describe("resetPendingSegmentsToOp", () => {
222
222
  client.annotateRangeLocal(0, 3, { prop2: "bar" });
223
223
  const otherClient = new testClient_js_1.TestClient();
224
224
  otherClient.startOrUpdateCollaboration("other user");
225
- const regeneratedInsert = client.regeneratePendingOp(insertOp, client.mergeTree.pendingSegments.first.data);
225
+ const regeneratedInsert = client.regeneratePendingOp(insertOp, client.mergeTree.pendingSegments.first.data, false);
226
226
  otherClient.applyMsg(client.makeOpMessage(regeneratedInsert, 1), false);
227
- const { segment: otherSegment } = otherClient.getContainingSegment(0);
227
+ const { segment: otherSegment } = otherClient.getContainingSegment(0) ?? {};
228
228
  (0, node_assert_1.strict)(otherSegment !== undefined && textSegment_js_1.TextSegment.is(otherSegment));
229
229
  node_assert_1.strict.deepStrictEqual(otherSegment.properties, undefined);
230
230
  });
@@ -241,7 +241,7 @@ describe("resetPendingSegmentsToOp.rebase", () => {
241
241
  ops.push(...ops
242
242
  .splice(Math.floor(ops.length / 2))
243
243
  .map(([op, sg]) => [
244
- clients.A.makeOpMessage(clients.A.regeneratePendingOp(op.contents, sg), op.sequenceNumber),
244
+ clients.A.makeOpMessage(clients.A.regeneratePendingOp(op.contents, sg, false), op.sequenceNumber),
245
245
  clients.A.peekPendingSegmentGroups(),
246
246
  ]));
247
247
  for (const [op] of ops)
@@ -1 +1 @@
1
- {"version":3,"file":"resetPendingSegmentsToOp.spec.js","sourceRoot":"","sources":["../../src/test/resetPendingSegmentsToOp.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\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport {\n\tMarker,\n\tSegmentGroup,\n\treservedMarkerIdKey,\n\ttype ISegmentPrivate,\n} from \"../mergeTreeNodes.js\";\nimport { IMergeTreeOp, ReferenceType } from \"../ops.js\";\nimport { clone } from \"../properties.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { TestClient } from \"./testClient.js\";\nimport { TestClientLogger, createClientsAtInitialState } from \"./testClientLogger.js\";\n\ndescribe(\"resetPendingSegmentsToOp\", () => {\n\tlet client: TestClient;\n\n\tbeforeEach(() => {\n\t\tclient = new TestClient();\n\t\tclient.startOrUpdateCollaboration(\"local user\");\n\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t});\n\n\tdescribe(\"with a number of nested inserts\", () => {\n\t\tconst insertCount = 5;\n\t\tconst expectedSegmentCount = insertCount * 2 - 1;\n\t\tlet opList: { op: IMergeTreeOp; refSeq: number }[];\n\t\tlet opCount: number = 0;\n\n\t\tfunction applyOpList(cli: TestClient): void {\n\t\t\twhile (opList.length > 0) {\n\t\t\t\tconst op = opList.shift();\n\t\t\t\tif (op) {\n\t\t\t\t\tconst seqOp = cli.makeOpMessage(op.op, ++opCount, op.refSeq);\n\t\t\t\t\tcli.applyMsg(seqOp);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tbeforeEach(() => {\n\t\t\topList = [];\n\t\t\topCount = 0;\n\n\t\t\tfor (let i = 0; i < insertCount; i++) {\n\t\t\t\tconst op = client.insertTextLocal(i, \"hello\")!;\n\t\t\t\topList.push({ op, refSeq: client.getCurrentSeq() });\n\t\t\t\tassert.equal(client.mergeTree.pendingSegments?.length, i + 1);\n\t\t\t}\n\t\t});\n\n\t\tit(\"acked insertSegment\", async () => {\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t\t});\n\n\t\tit(\"only computes localPartialLengths once\", () => {\n\t\t\t// This test helps verify the asymptotic correctness of rebase.\n\t\t\t// Since local partial length information is reasonably expensive to store and compute compared to how\n\t\t\t// frequently it's used (i.e. only on reconnect), mergeTree has some logic to only do so when requested,\n\t\t\t// and invalidates that info whenever a segment update occurs.\n\t\t\t// This test verifies that local partial length information only gets computed once when regenerating\n\t\t\t// a number of ops for reconnection.\n\t\t\tlet localPartialsComputeCount = 0;\n\t\t\tconst spiedMergeTree = client.mergeTree as unknown as {\n\t\t\t\tlocalPartialsComputed: boolean;\n\t\t\t\t_localPartialsComputed: boolean;\n\t\t\t};\n\t\t\tspiedMergeTree._localPartialsComputed = spiedMergeTree.localPartialsComputed;\n\t\t\tObject.defineProperty(\n\t\t\t\tclient.mergeTree as unknown as { localPartialsComputed: boolean },\n\t\t\t\t\"localPartialsComputed\",\n\t\t\t\t{\n\t\t\t\t\tget() {\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\t\t\t\treturn this._localPartialsComputed as boolean;\n\t\t\t\t\t},\n\t\t\t\t\tset(newValue) {\n\t\t\t\t\t\tif (newValue) {\n\t\t\t\t\t\t\tlocalPartialsComputeCount++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n\t\t\t\t\t\tthis._localPartialsComputed = newValue;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst oldops = opList;\n\t\t\tconst pending = [...client.mergeTree.pendingSegments.map((n) => n.data)];\n\t\t\topList = oldops.map((op) => ({\n\t\t\t\top: client.regeneratePendingOp(op.op, pending.shift()!),\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t}));\n\t\t\tapplyOpList(client);\n\t\t\tassert.equal(localPartialsComputeCount, 1);\n\t\t});\n\n\t\tit(\"nacked insertSegment\", async () => {\n\t\t\tconst oldops = opList;\n\t\t\tconst pending = [...client.mergeTree.pendingSegments.map((n) => n.data)];\n\t\t\topList = oldops.map((op) => ({\n\t\t\t\top: client.regeneratePendingOp(op.op, pending.shift()!),\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t}));\n\t\t\t// we expect a nack op per segment since our original ops split segments\n\t\t\t// we should expect mores nack ops then original ops.\n\t\t\t// only the first op didn't split a segment, all the others did\n\t\t\tassert.equal(client.mergeTree.pendingSegments?.length, expectedSegmentCount);\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t\t});\n\n\t\tit(\"acked removeRange\", async () => {\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\n\t\t\topList.push({\n\t\t\t\top: client.removeRangeLocal(0, client.getLength())!,\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t});\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t\t});\n\n\t\tit(\"nacked removeRange\", async () => {\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\n\t\t\topList.push({\n\t\t\t\top: client.removeRangeLocal(0, client.getLength())!,\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t});\n\n\t\t\topList.push({\n\t\t\t\top: client.regeneratePendingOp(\n\t\t\t\t\topList.shift()!.op,\n\t\t\t\t\tclient.mergeTree.pendingSegments.first!.data,\n\t\t\t\t),\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t});\n\t\t\t// we expect a nack op per segment since our original ops split segments\n\t\t\t// we should expect mores nack ops then original ops.\n\t\t\t// only the first op didn't split a segment, all the others did\n\t\t\tassert.equal(client.mergeTree.pendingSegments?.length, expectedSegmentCount);\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t\t});\n\n\t\tit(\"nacked insertSegment and removeRange\", async () => {\n\t\t\topList.push({\n\t\t\t\top: client.removeRangeLocal(0, client.getLength())!,\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t});\n\t\t\tconst oldops = opList;\n\t\t\tconst pending = [...client.mergeTree.pendingSegments.map((n) => n.data)];\n\t\t\topList = oldops.map((op) => ({\n\t\t\t\top: client.regeneratePendingOp(op.op, pending.shift()!),\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t}));\n\n\t\t\tassert.equal(client.mergeTree.pendingSegments?.length, expectedSegmentCount * 2);\n\n\t\t\tapplyOpList(client);\n\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t\t});\n\n\t\tit(\"acked annotateRange\", async () => {\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\n\t\t\topList.push({\n\t\t\t\top: client.annotateRangeLocal(0, client.getLength(), { foo: \"bar\" })!,\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t});\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t\t});\n\n\t\tit(\"nacked annotateRange\", async () => {\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\n\t\t\topList.push({\n\t\t\t\top: client.annotateRangeLocal(0, client.getLength(), { foo: \"bar\" })!,\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t});\n\n\t\t\topList.push({\n\t\t\t\top: client.regeneratePendingOp(\n\t\t\t\t\topList.shift()!.op,\n\t\t\t\t\tclient.mergeTree.pendingSegments.first!.data,\n\t\t\t\t),\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t});\n\t\t\t// we expect a nack op per segment since our original ops split segments\n\t\t\t// we should expect mores nack ops then original ops.\n\t\t\t// only the first op didn't split a segment, all the others did\n\t\t\tassert.equal(client.mergeTree.pendingSegments?.length, expectedSegmentCount);\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t\t});\n\n\t\tit(\"nacked insertSegment and annotateRange\", async () => {\n\t\t\topList.push({\n\t\t\t\top: client.annotateRangeLocal(0, client.getLength(), { foo: \"bar\" })!,\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t});\n\t\t\tconst oldops = opList;\n\t\t\tconst pending = [...client.mergeTree.pendingSegments.map((n) => n.data)];\n\t\t\topList = oldops.map((op) => ({\n\t\t\t\top: client.regeneratePendingOp(op.op, pending.shift()!),\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t}));\n\t\t\t// we expect a nack op per segment since our original ops split segments\n\t\t\t// we should expect mores nack ops then original ops.\n\t\t\t// only the first op didn't split a segment, all the others did\n\t\t\tassert.equal(client.mergeTree.pendingSegments?.length, expectedSegmentCount * 2);\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t\t});\n\t});\n\n\tdescribe(\"uses original properties on insert\", () => {\n\t\t// Regression tests for an issue where regenerated insert ops would use the properties of a segment\n\t\t// at the time of regeneration rather than its properties at insertion time.\n\t\tit(\"for markers\", () => {\n\t\t\tconst insertOp = client.insertMarkerLocal(0, ReferenceType.Simple, {\n\t\t\t\t[reservedMarkerIdKey]: \"id\",\n\t\t\t\tprop1: \"foo\",\n\t\t\t});\n\t\t\tassert(insertOp);\n\t\t\tconst { segment } = client.getContainingSegment<ISegmentPrivate>(0);\n\t\t\tassert(segment !== undefined && Marker.is(segment));\n\t\t\tclient.annotateMarker(segment, { prop2: \"bar\" });\n\n\t\t\tconst otherClient = new TestClient();\n\t\t\totherClient.startOrUpdateCollaboration(\"other user\");\n\t\t\tconst regeneratedInsert = client.regeneratePendingOp(\n\t\t\t\tinsertOp,\n\t\t\t\tclient.mergeTree.pendingSegments.first!.data,\n\t\t\t);\n\t\t\totherClient.applyMsg(client.makeOpMessage(regeneratedInsert, 1), false);\n\n\t\t\tconst { segment: otherSegment } = otherClient.getContainingSegment<ISegmentPrivate>(0);\n\t\t\tassert(otherSegment !== undefined && Marker.is(otherSegment));\n\t\t\t// `clone` here is because properties use a Object.create(null); to compare strict equal the prototype chain\n\t\t\t// should therefore not include Object.\n\t\t\tassert.deepStrictEqual(\n\t\t\t\totherSegment.properties,\n\t\t\t\tclone({ [reservedMarkerIdKey]: \"id\", prop1: \"foo\" }),\n\t\t\t);\n\t\t});\n\n\t\tit(\"for text segments\", () => {\n\t\t\tconst insertOp = client.insertTextLocal(0, \"abc\", { prop1: \"foo\" });\n\t\t\tassert(insertOp);\n\t\t\tclient.annotateRangeLocal(0, 3, { prop2: \"bar\" });\n\n\t\t\tconst otherClient = new TestClient();\n\t\t\totherClient.startOrUpdateCollaboration(\"other user\");\n\t\t\tconst regeneratedInsert = client.regeneratePendingOp(\n\t\t\t\tinsertOp,\n\t\t\t\tclient.mergeTree.pendingSegments.first!.data,\n\t\t\t);\n\t\t\totherClient.applyMsg(client.makeOpMessage(regeneratedInsert, 1), false);\n\n\t\t\tconst { segment: otherSegment } = otherClient.getContainingSegment<ISegmentPrivate>(0);\n\t\t\tassert(otherSegment !== undefined && TextSegment.is(otherSegment));\n\t\t\tassert.deepStrictEqual(otherSegment.properties, clone({ prop1: \"foo\" }));\n\t\t});\n\n\t\tit(\"for text segments with no initial properties\", () => {\n\t\t\tconst insertOp = client.insertTextLocal(0, \"abc\");\n\t\t\tassert(insertOp);\n\t\t\tclient.annotateRangeLocal(0, 3, { prop2: \"bar\" });\n\n\t\t\tconst otherClient = new TestClient();\n\t\t\totherClient.startOrUpdateCollaboration(\"other user\");\n\t\t\tconst regeneratedInsert = client.regeneratePendingOp(\n\t\t\t\tinsertOp,\n\t\t\t\tclient.mergeTree.pendingSegments.first!.data,\n\t\t\t);\n\t\t\totherClient.applyMsg(client.makeOpMessage(regeneratedInsert, 1), false);\n\n\t\t\tconst { segment: otherSegment } = otherClient.getContainingSegment<ISegmentPrivate>(0);\n\t\t\tassert(otherSegment !== undefined && TextSegment.is(otherSegment));\n\t\t\tassert.deepStrictEqual(otherSegment.properties, undefined);\n\t\t});\n\t});\n});\n\ndescribe(\"resetPendingSegmentsToOp.rebase\", () => {\n\tit(\"rebase with oustanding ops\", () => {\n\t\tconst clients = createClientsAtInitialState({ initialState: \"0123456789\" }, \"A\", \"B\");\n\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tconst ops: [ISequencedDocumentMessage, SegmentGroup][] = Array.from({ length: 10 }).map(\n\t\t\t(_, i) => [\n\t\t\t\tclients.A.makeOpMessage(\n\t\t\t\t\tclients.A.annotateRangeLocal(0, clients.A.getLength(), { prop: i }),\n\t\t\t\t\ti + 1,\n\t\t\t\t),\n\t\t\t\tclients.A.peekPendingSegmentGroups()!,\n\t\t\t],\n\t\t);\n\n\t\tops.push(\n\t\t\t...ops\n\t\t\t\t.splice(Math.floor(ops.length / 2))\n\t\t\t\t.map<[ISequencedDocumentMessage, SegmentGroup]>(([op, sg]) => [\n\t\t\t\t\tclients.A.makeOpMessage(\n\t\t\t\t\t\tclients.A.regeneratePendingOp(op.contents as IMergeTreeOp, sg),\n\t\t\t\t\t\top.sequenceNumber,\n\t\t\t\t\t),\n\t\t\t\t\tclients.A.peekPendingSegmentGroups()!,\n\t\t\t\t]),\n\t\t);\n\n\t\tfor (const [op] of ops) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate();\n\t});\n});\n"]}
1
+ {"version":3,"file":"resetPendingSegmentsToOp.spec.js","sourceRoot":"","sources":["../../src/test/resetPendingSegmentsToOp.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\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport {\n\tMarker,\n\tSegmentGroup,\n\treservedMarkerIdKey,\n\ttype ISegmentPrivate,\n} from \"../mergeTreeNodes.js\";\nimport { IMergeTreeOp, ReferenceType } from \"../ops.js\";\nimport { clone } from \"../properties.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { TestClient } from \"./testClient.js\";\nimport { TestClientLogger, createClientsAtInitialState } from \"./testClientLogger.js\";\n\ndescribe(\"resetPendingSegmentsToOp\", () => {\n\tlet client: TestClient;\n\n\tbeforeEach(() => {\n\t\tclient = new TestClient();\n\t\tclient.startOrUpdateCollaboration(\"local user\");\n\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t});\n\n\tdescribe(\"with a number of nested inserts\", () => {\n\t\tconst insertCount = 5;\n\t\tconst expectedSegmentCount = insertCount * 2 - 1;\n\t\tlet opList: { op: IMergeTreeOp; refSeq: number }[];\n\t\tlet opCount: number = 0;\n\n\t\tfunction applyOpList(cli: TestClient): void {\n\t\t\twhile (opList.length > 0) {\n\t\t\t\tconst op = opList.shift();\n\t\t\t\tif (op) {\n\t\t\t\t\tconst seqOp = cli.makeOpMessage(op.op, ++opCount, op.refSeq);\n\t\t\t\t\tcli.applyMsg(seqOp);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tbeforeEach(() => {\n\t\t\topList = [];\n\t\t\topCount = 0;\n\n\t\t\tfor (let i = 0; i < insertCount; i++) {\n\t\t\t\tconst op = client.insertTextLocal(i, \"hello\")!;\n\t\t\t\topList.push({ op, refSeq: client.getCurrentSeq() });\n\t\t\t\tassert.equal(client.mergeTree.pendingSegments?.length, i + 1);\n\t\t\t}\n\t\t});\n\n\t\tit(\"acked insertSegment\", async () => {\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t\t});\n\n\t\tit(\"only computes localPartialLengths once\", () => {\n\t\t\t// This test helps verify the asymptotic correctness of rebase.\n\t\t\t// Since local partial length information is reasonably expensive to store and compute compared to how\n\t\t\t// frequently it's used (i.e. only on reconnect), mergeTree has some logic to only do so when requested,\n\t\t\t// and invalidates that info whenever a segment update occurs.\n\t\t\t// This test verifies that local partial length information only gets computed once when regenerating\n\t\t\t// a number of ops for reconnection.\n\t\t\tlet localPartialsComputeCount = 0;\n\t\t\tconst spiedMergeTree = client.mergeTree as unknown as {\n\t\t\t\tlocalPartialsComputed: boolean;\n\t\t\t\t_localPartialsComputed: boolean;\n\t\t\t};\n\t\t\tspiedMergeTree._localPartialsComputed = spiedMergeTree.localPartialsComputed;\n\t\t\tObject.defineProperty(\n\t\t\t\tclient.mergeTree as unknown as { localPartialsComputed: boolean },\n\t\t\t\t\"localPartialsComputed\",\n\t\t\t\t{\n\t\t\t\t\tget() {\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\t\t\t\treturn this._localPartialsComputed as boolean;\n\t\t\t\t\t},\n\t\t\t\t\tset(newValue) {\n\t\t\t\t\t\tif (newValue) {\n\t\t\t\t\t\t\tlocalPartialsComputeCount++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n\t\t\t\t\t\tthis._localPartialsComputed = newValue;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst oldops = opList;\n\t\t\tconst pending = [...client.mergeTree.pendingSegments.map((n) => n.data)];\n\t\t\topList = oldops.map((op) => ({\n\t\t\t\top: client.regeneratePendingOp(op.op, pending.shift()!, false),\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t}));\n\t\t\tapplyOpList(client);\n\t\t\tassert.equal(localPartialsComputeCount, 1);\n\t\t});\n\n\t\tit(\"nacked insertSegment\", async () => {\n\t\t\tconst oldops = opList;\n\t\t\tconst pending = [...client.mergeTree.pendingSegments.map((n) => n.data)];\n\t\t\topList = oldops.map((op) => ({\n\t\t\t\top: client.regeneratePendingOp(op.op, pending.shift()!, false),\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t}));\n\t\t\t// we expect a nack op per segment since our original ops split segments\n\t\t\t// we should expect mores nack ops then original ops.\n\t\t\t// only the first op didn't split a segment, all the others did\n\t\t\tassert.equal(client.mergeTree.pendingSegments?.length, expectedSegmentCount);\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t\t});\n\n\t\tit(\"acked removeRange\", async () => {\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\n\t\t\topList.push({\n\t\t\t\top: client.removeRangeLocal(0, client.getLength())!,\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t});\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t\t});\n\n\t\tit(\"nacked removeRange\", async () => {\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\n\t\t\topList.push({\n\t\t\t\top: client.removeRangeLocal(0, client.getLength())!,\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t});\n\n\t\t\topList.push({\n\t\t\t\top: client.regeneratePendingOp(\n\t\t\t\t\topList.shift()!.op,\n\t\t\t\t\tclient.mergeTree.pendingSegments.first!.data,\n\t\t\t\t\tfalse,\n\t\t\t\t),\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t});\n\t\t\t// we expect a nack op per segment since our original ops split segments\n\t\t\t// we should expect mores nack ops then original ops.\n\t\t\t// only the first op didn't split a segment, all the others did\n\t\t\tassert.equal(client.mergeTree.pendingSegments?.length, expectedSegmentCount);\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t\t});\n\n\t\tit(\"nacked insertSegment and removeRange\", async () => {\n\t\t\topList.push({\n\t\t\t\top: client.removeRangeLocal(0, client.getLength())!,\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t});\n\t\t\tconst oldops = opList;\n\t\t\tconst pending = [...client.mergeTree.pendingSegments.map((n) => n.data)];\n\t\t\topList = oldops.map((op) => ({\n\t\t\t\top: client.regeneratePendingOp(op.op, pending.shift()!, false),\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t}));\n\n\t\t\tassert.equal(client.mergeTree.pendingSegments?.length, expectedSegmentCount * 2);\n\n\t\t\tapplyOpList(client);\n\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t\t});\n\n\t\tit(\"acked annotateRange\", async () => {\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\n\t\t\topList.push({\n\t\t\t\top: client.annotateRangeLocal(0, client.getLength(), { foo: \"bar\" })!,\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t});\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t\t});\n\n\t\tit(\"nacked annotateRange\", async () => {\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\n\t\t\topList.push({\n\t\t\t\top: client.annotateRangeLocal(0, client.getLength(), { foo: \"bar\" })!,\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t});\n\n\t\t\topList.push({\n\t\t\t\top: client.regeneratePendingOp(\n\t\t\t\t\topList.shift()!.op,\n\t\t\t\t\tclient.mergeTree.pendingSegments.first!.data,\n\t\t\t\t\tfalse,\n\t\t\t\t),\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t});\n\t\t\t// we expect a nack op per segment since our original ops split segments\n\t\t\t// we should expect mores nack ops then original ops.\n\t\t\t// only the first op didn't split a segment, all the others did\n\t\t\tassert.equal(client.mergeTree.pendingSegments?.length, expectedSegmentCount);\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t\t});\n\n\t\tit(\"nacked insertSegment and annotateRange\", async () => {\n\t\t\topList.push({\n\t\t\t\top: client.annotateRangeLocal(0, client.getLength(), { foo: \"bar\" })!,\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t});\n\t\t\tconst oldops = opList;\n\t\t\tconst pending = [...client.mergeTree.pendingSegments.map((n) => n.data)];\n\t\t\topList = oldops.map((op) => ({\n\t\t\t\top: client.regeneratePendingOp(op.op, pending.shift()!, false),\n\t\t\t\trefSeq: client.getCurrentSeq(),\n\t\t\t}));\n\t\t\t// we expect a nack op per segment since our original ops split segments\n\t\t\t// we should expect mores nack ops then original ops.\n\t\t\t// only the first op didn't split a segment, all the others did\n\t\t\tassert.equal(client.mergeTree.pendingSegments?.length, expectedSegmentCount * 2);\n\t\t\tapplyOpList(client);\n\t\t\tassert(client.mergeTree.pendingSegments?.empty);\n\t\t});\n\t});\n\n\tdescribe(\"uses original properties on insert\", () => {\n\t\t// Regression tests for an issue where regenerated insert ops would use the properties of a segment\n\t\t// at the time of regeneration rather than its properties at insertion time.\n\t\tit(\"for markers\", () => {\n\t\t\tconst insertOp = client.insertMarkerLocal(0, ReferenceType.Simple, {\n\t\t\t\t[reservedMarkerIdKey]: \"id\",\n\t\t\t\tprop1: \"foo\",\n\t\t\t});\n\t\t\tassert(insertOp);\n\t\t\tconst { segment } = client.getContainingSegment<ISegmentPrivate>(0) ?? {};\n\t\t\tassert(segment !== undefined && Marker.is(segment));\n\t\t\tclient.annotateMarker(segment, { prop2: \"bar\" });\n\n\t\t\tconst otherClient = new TestClient();\n\t\t\totherClient.startOrUpdateCollaboration(\"other user\");\n\t\t\tconst regeneratedInsert = client.regeneratePendingOp(\n\t\t\t\tinsertOp,\n\t\t\t\tclient.mergeTree.pendingSegments.first!.data,\n\t\t\t\tfalse,\n\t\t\t);\n\t\t\totherClient.applyMsg(client.makeOpMessage(regeneratedInsert, 1), false);\n\n\t\t\tconst { segment: otherSegment } =\n\t\t\t\totherClient.getContainingSegment<ISegmentPrivate>(0) ?? {};\n\t\t\tassert(otherSegment !== undefined && Marker.is(otherSegment));\n\t\t\t// `clone` here is because properties use a Object.create(null); to compare strict equal the prototype chain\n\t\t\t// should therefore not include Object.\n\t\t\tassert.deepStrictEqual(\n\t\t\t\totherSegment.properties,\n\t\t\t\tclone({ [reservedMarkerIdKey]: \"id\", prop1: \"foo\" }),\n\t\t\t);\n\t\t});\n\n\t\tit(\"for text segments\", () => {\n\t\t\tconst insertOp = client.insertTextLocal(0, \"abc\", { prop1: \"foo\" });\n\t\t\tassert(insertOp);\n\t\t\tclient.annotateRangeLocal(0, 3, { prop2: \"bar\" });\n\n\t\t\tconst otherClient = new TestClient();\n\t\t\totherClient.startOrUpdateCollaboration(\"other user\");\n\t\t\tconst regeneratedInsert = client.regeneratePendingOp(\n\t\t\t\tinsertOp,\n\t\t\t\tclient.mergeTree.pendingSegments.first!.data,\n\t\t\t\tfalse,\n\t\t\t);\n\t\t\totherClient.applyMsg(client.makeOpMessage(regeneratedInsert, 1), false);\n\n\t\t\tconst { segment: otherSegment } =\n\t\t\t\totherClient.getContainingSegment<ISegmentPrivate>(0) ?? {};\n\t\t\tassert(otherSegment !== undefined && TextSegment.is(otherSegment));\n\t\t\tassert.deepStrictEqual(otherSegment.properties, clone({ prop1: \"foo\" }));\n\t\t});\n\n\t\tit(\"for text segments with no initial properties\", () => {\n\t\t\tconst insertOp = client.insertTextLocal(0, \"abc\");\n\t\t\tassert(insertOp);\n\t\t\tclient.annotateRangeLocal(0, 3, { prop2: \"bar\" });\n\n\t\t\tconst otherClient = new TestClient();\n\t\t\totherClient.startOrUpdateCollaboration(\"other user\");\n\t\t\tconst regeneratedInsert = client.regeneratePendingOp(\n\t\t\t\tinsertOp,\n\t\t\t\tclient.mergeTree.pendingSegments.first!.data,\n\t\t\t\tfalse,\n\t\t\t);\n\t\t\totherClient.applyMsg(client.makeOpMessage(regeneratedInsert, 1), false);\n\n\t\t\tconst { segment: otherSegment } =\n\t\t\t\totherClient.getContainingSegment<ISegmentPrivate>(0) ?? {};\n\t\t\tassert(otherSegment !== undefined && TextSegment.is(otherSegment));\n\t\t\tassert.deepStrictEqual(otherSegment.properties, undefined);\n\t\t});\n\t});\n});\n\ndescribe(\"resetPendingSegmentsToOp.rebase\", () => {\n\tit(\"rebase with oustanding ops\", () => {\n\t\tconst clients = createClientsAtInitialState({ initialState: \"0123456789\" }, \"A\", \"B\");\n\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tconst ops: [ISequencedDocumentMessage, SegmentGroup][] = Array.from({ length: 10 }).map(\n\t\t\t(_, i) => [\n\t\t\t\tclients.A.makeOpMessage(\n\t\t\t\t\tclients.A.annotateRangeLocal(0, clients.A.getLength(), { prop: i }),\n\t\t\t\t\ti + 1,\n\t\t\t\t),\n\t\t\t\tclients.A.peekPendingSegmentGroups()!,\n\t\t\t],\n\t\t);\n\n\t\tops.push(\n\t\t\t...ops\n\t\t\t\t.splice(Math.floor(ops.length / 2))\n\t\t\t\t.map<[ISequencedDocumentMessage, SegmentGroup]>(([op, sg]) => [\n\t\t\t\t\tclients.A.makeOpMessage(\n\t\t\t\t\t\tclients.A.regeneratePendingOp(op.contents as IMergeTreeOp, sg, false),\n\t\t\t\t\t\top.sequenceNumber,\n\t\t\t\t\t),\n\t\t\t\t\tclients.A.peekPendingSegmentGroups()!,\n\t\t\t\t]),\n\t\t);\n\n\t\tfor (const [op] of ops) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate();\n\t});\n});\n"]}
@@ -100,7 +100,7 @@ class TestString {
100
100
  this.pending.push(this.client.makeOpMessage(op, seq, refSeq, this.client.longClientId, (this.minSeq = increaseMsn ? seq : this.minSeq)));
101
101
  }
102
102
  getSegment(pos) {
103
- const { segment } = this.client.getContainingSegment(pos);
103
+ const { segment } = this.client.getContainingSegment(pos) ?? {};
104
104
  (0, node_assert_1.strict)(segment !== undefined);
105
105
  return segment;
106
106
  }
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.utils.js","sourceRoot":"","sources":["../../src/test/snapshot.utils.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\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { IFluidDataStoreRuntime } from \"@fluidframework/datastore-definitions/internal\";\nimport { ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\nimport { MockStorage } from \"@fluidframework/test-runtime-utils/internal\";\n\nimport { type IMergeTreeOptionsInternal } from \"../mergeTree.js\";\nimport { type ISegmentPrivate } from \"../mergeTreeNodes.js\";\nimport { IMergeTreeOp, ReferenceType } from \"../ops.js\";\nimport { PropertySet } from \"../properties.js\";\nimport { SnapshotV1 } from \"../snapshotV1.js\";\n\nimport { TestClient } from \"./testClient.js\";\nimport { createClientsAtInitialState } from \"./testClientLogger.js\";\nimport { TestSerializer } from \"./testSerializer.js\";\n\n// Reconstitutes a MergeTree client from a summary\nexport async function loadSnapshot(\n\tsummary: ISummaryTree,\n\toptions?: IMergeTreeOptionsInternal,\n): Promise<TestClient> {\n\tconst services = MockStorage.createFromSummary(summary);\n\tconst client2 = new TestClient(options);\n\tconst runtime: Partial<IFluidDataStoreRuntime> = {\n\t\tlogger: client2.logger,\n\t\tclientId: \"1\",\n\t};\n\n\tconst { catchupOpsP } = await client2.load(\n\t\truntime as IFluidDataStoreRuntime,\n\t\tservices,\n\t\tnew TestSerializer(),\n\t);\n\tawait catchupOpsP;\n\treturn client2;\n}\n\n// Wrapper around MergeTree client that provides a convenient SharedString-like API for tests.\nexport class TestString {\n\tprivate client: TestClient;\n\tprivate readonly pending: ISequencedDocumentMessage[] = [];\n\tprivate seq = 0;\n\tprivate minSeq = 0;\n\n\tconstructor(\n\t\tid: string,\n\t\tprivate readonly options?: IMergeTreeOptionsInternal,\n\t\tinitialState: string = \"\",\n\t) {\n\t\tthis.client = createClientsAtInitialState({ initialState, options }, id)[id]!;\n\t\tthis.client.startOrUpdateCollaboration(id);\n\t}\n\n\tpublic insert(pos: number, text: string, increaseMsn: boolean): void {\n\t\tthis.queue(\n\t\t\tthis.client.insertTextLocal(pos, text, { segment: this.pending.length })!,\n\t\t\tincreaseMsn,\n\t\t);\n\t}\n\n\tpublic annotate(start: number, end: number, props: PropertySet, increaseMsn: boolean): void {\n\t\tthis.queue(this.client.annotateRangeLocal(start, end, props)!, increaseMsn);\n\t}\n\n\tpublic append(text: string, increaseMsn: boolean): void {\n\t\tthis.insert(this.client.getLength(), text, increaseMsn);\n\t}\n\n\tpublic insertMarker(pos: number, increaseMsn: boolean): void {\n\t\tthis.queue(\n\t\t\tthis.client.insertMarkerLocal(pos, ReferenceType.Simple, {\n\t\t\t\tsegment: this.pending.length,\n\t\t\t})!,\n\t\t\tincreaseMsn,\n\t\t);\n\t}\n\n\tpublic appendMarker(increaseMsn: boolean): void {\n\t\tthis.insertMarker(this.client.getLength(), increaseMsn);\n\t}\n\n\tpublic removeRange(start: number, end: number, increaseMsn: boolean): void {\n\t\tthis.queue(this.client.removeRangeLocal(start, end)!, increaseMsn);\n\t}\n\n\tpublic obliterateRange(start: number, end: number, increaseMsn: boolean): void {\n\t\tthis.queue(this.client.obliterateRangeLocal(start, end)!, increaseMsn);\n\t}\n\n\t// Ensures the client's text matches the `expected` string and round-trips through a snapshot\n\t// into a new client. The current client is then replaced with the loaded client in the hope\n\t// that it will help detect corruption bugs as further ops are applied.\n\tpublic async expect(expected: string): Promise<void> {\n\t\tassert.equal(\n\t\t\tthis.client.getText(),\n\t\t\texpected,\n\t\t\t\"MergeTree must contain the expected text prior to applying ops.\",\n\t\t);\n\n\t\tawait this.checkSnapshot(this.options);\n\t}\n\n\t// Ensures the MergeTree client's contents successfully roundtrip through a snapshot.\n\tpublic async checkSnapshot(options?: IMergeTreeOptionsInternal): Promise<void> {\n\t\tthis.applyPendingOps();\n\t\tconst expectedAttributionKeys = this.client.getAllAttributionSeqs();\n\t\tconst summary = this.getSummary();\n\t\tconst client2 = await loadSnapshot(summary, options ?? this.options);\n\n\t\tassert.equal(\n\t\t\tthis.client.getText(),\n\t\t\tclient2.getText(),\n\t\t\t\"Snapshot must produce a MergeTree with the same text as the original\",\n\t\t);\n\n\t\t// Also check the length as weak test for non-TextSegments.\n\t\tassert.equal(\n\t\t\tthis.client.getLength(),\n\t\t\tclient2.getLength(),\n\t\t\t\"Snapshot must produce a MergeTree with the same length as the original\",\n\t\t);\n\n\t\tconst actualAttributionKeys = client2.getAllAttributionSeqs();\n\t\tassert.deepEqual(\n\t\t\tactualAttributionKeys,\n\t\t\texpectedAttributionKeys,\n\t\t\t\"Snapshot must produce a MergeTree with identical attribution as the original\",\n\t\t);\n\n\t\t// Replace our client with the one loaded by the snapshot.\n\t\tthis.client = client2;\n\t}\n\n\tpublic getSummary(): ISummaryTree {\n\t\tconst snapshot = new SnapshotV1(this.client.mergeTree, this.client.logger, (id) =>\n\t\t\tthis.client.getLongClientId(id),\n\t\t);\n\n\t\tsnapshot.extractSync();\n\t\treturn snapshot.emit(TestClient.serializer, undefined!).summary;\n\t}\n\n\tpublic getText(): string {\n\t\treturn this.client.getText();\n\t}\n\n\tpublic applyPendingOps(): void {\n\t\tfor (const msg of this.pending) {\n\t\t\tthis.client.applyMsg(msg);\n\t\t}\n\t\tthis.pending.splice(0, this.pending.length);\n\t}\n\n\tprivate queue(op: IMergeTreeOp, increaseMsn: boolean): void {\n\t\tconst refSeq = this.seq;\n\t\tconst seq = ++this.seq;\n\n\t\tthis.pending.push(\n\t\t\tthis.client.makeOpMessage(\n\t\t\t\top,\n\t\t\t\tseq,\n\t\t\t\trefSeq,\n\t\t\t\tthis.client.longClientId,\n\t\t\t\t(this.minSeq = increaseMsn ? seq : this.minSeq),\n\t\t\t),\n\t\t);\n\t}\n\n\tpublic getSegment(pos: number): ISegmentPrivate {\n\t\tconst { segment } = this.client.getContainingSegment<ISegmentPrivate>(pos);\n\t\tassert(segment !== undefined);\n\t\treturn segment;\n\t}\n}\n"]}
1
+ {"version":3,"file":"snapshot.utils.js","sourceRoot":"","sources":["../../src/test/snapshot.utils.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\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { IFluidDataStoreRuntime } from \"@fluidframework/datastore-definitions/internal\";\nimport { ISummaryTree } from \"@fluidframework/driver-definitions\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\nimport { MockStorage } from \"@fluidframework/test-runtime-utils/internal\";\n\nimport { type IMergeTreeOptionsInternal } from \"../mergeTree.js\";\nimport { type ISegmentPrivate } from \"../mergeTreeNodes.js\";\nimport { IMergeTreeOp, ReferenceType } from \"../ops.js\";\nimport { PropertySet } from \"../properties.js\";\nimport { SnapshotV1 } from \"../snapshotV1.js\";\n\nimport { TestClient } from \"./testClient.js\";\nimport { createClientsAtInitialState } from \"./testClientLogger.js\";\nimport { TestSerializer } from \"./testSerializer.js\";\n\n// Reconstitutes a MergeTree client from a summary\nexport async function loadSnapshot(\n\tsummary: ISummaryTree,\n\toptions?: IMergeTreeOptionsInternal,\n): Promise<TestClient> {\n\tconst services = MockStorage.createFromSummary(summary);\n\tconst client2 = new TestClient(options);\n\tconst runtime: Partial<IFluidDataStoreRuntime> = {\n\t\tlogger: client2.logger,\n\t\tclientId: \"1\",\n\t};\n\n\tconst { catchupOpsP } = await client2.load(\n\t\truntime as IFluidDataStoreRuntime,\n\t\tservices,\n\t\tnew TestSerializer(),\n\t);\n\tawait catchupOpsP;\n\treturn client2;\n}\n\n// Wrapper around MergeTree client that provides a convenient SharedString-like API for tests.\nexport class TestString {\n\tprivate client: TestClient;\n\tprivate readonly pending: ISequencedDocumentMessage[] = [];\n\tprivate seq = 0;\n\tprivate minSeq = 0;\n\n\tconstructor(\n\t\tid: string,\n\t\tprivate readonly options?: IMergeTreeOptionsInternal,\n\t\tinitialState: string = \"\",\n\t) {\n\t\tthis.client = createClientsAtInitialState({ initialState, options }, id)[id]!;\n\t\tthis.client.startOrUpdateCollaboration(id);\n\t}\n\n\tpublic insert(pos: number, text: string, increaseMsn: boolean): void {\n\t\tthis.queue(\n\t\t\tthis.client.insertTextLocal(pos, text, { segment: this.pending.length })!,\n\t\t\tincreaseMsn,\n\t\t);\n\t}\n\n\tpublic annotate(start: number, end: number, props: PropertySet, increaseMsn: boolean): void {\n\t\tthis.queue(this.client.annotateRangeLocal(start, end, props)!, increaseMsn);\n\t}\n\n\tpublic append(text: string, increaseMsn: boolean): void {\n\t\tthis.insert(this.client.getLength(), text, increaseMsn);\n\t}\n\n\tpublic insertMarker(pos: number, increaseMsn: boolean): void {\n\t\tthis.queue(\n\t\t\tthis.client.insertMarkerLocal(pos, ReferenceType.Simple, {\n\t\t\t\tsegment: this.pending.length,\n\t\t\t})!,\n\t\t\tincreaseMsn,\n\t\t);\n\t}\n\n\tpublic appendMarker(increaseMsn: boolean): void {\n\t\tthis.insertMarker(this.client.getLength(), increaseMsn);\n\t}\n\n\tpublic removeRange(start: number, end: number, increaseMsn: boolean): void {\n\t\tthis.queue(this.client.removeRangeLocal(start, end)!, increaseMsn);\n\t}\n\n\tpublic obliterateRange(start: number, end: number, increaseMsn: boolean): void {\n\t\tthis.queue(this.client.obliterateRangeLocal(start, end)!, increaseMsn);\n\t}\n\n\t// Ensures the client's text matches the `expected` string and round-trips through a snapshot\n\t// into a new client. The current client is then replaced with the loaded client in the hope\n\t// that it will help detect corruption bugs as further ops are applied.\n\tpublic async expect(expected: string): Promise<void> {\n\t\tassert.equal(\n\t\t\tthis.client.getText(),\n\t\t\texpected,\n\t\t\t\"MergeTree must contain the expected text prior to applying ops.\",\n\t\t);\n\n\t\tawait this.checkSnapshot(this.options);\n\t}\n\n\t// Ensures the MergeTree client's contents successfully roundtrip through a snapshot.\n\tpublic async checkSnapshot(options?: IMergeTreeOptionsInternal): Promise<void> {\n\t\tthis.applyPendingOps();\n\t\tconst expectedAttributionKeys = this.client.getAllAttributionSeqs();\n\t\tconst summary = this.getSummary();\n\t\tconst client2 = await loadSnapshot(summary, options ?? this.options);\n\n\t\tassert.equal(\n\t\t\tthis.client.getText(),\n\t\t\tclient2.getText(),\n\t\t\t\"Snapshot must produce a MergeTree with the same text as the original\",\n\t\t);\n\n\t\t// Also check the length as weak test for non-TextSegments.\n\t\tassert.equal(\n\t\t\tthis.client.getLength(),\n\t\t\tclient2.getLength(),\n\t\t\t\"Snapshot must produce a MergeTree with the same length as the original\",\n\t\t);\n\n\t\tconst actualAttributionKeys = client2.getAllAttributionSeqs();\n\t\tassert.deepEqual(\n\t\t\tactualAttributionKeys,\n\t\t\texpectedAttributionKeys,\n\t\t\t\"Snapshot must produce a MergeTree with identical attribution as the original\",\n\t\t);\n\n\t\t// Replace our client with the one loaded by the snapshot.\n\t\tthis.client = client2;\n\t}\n\n\tpublic getSummary(): ISummaryTree {\n\t\tconst snapshot = new SnapshotV1(this.client.mergeTree, this.client.logger, (id) =>\n\t\t\tthis.client.getLongClientId(id),\n\t\t);\n\n\t\tsnapshot.extractSync();\n\t\treturn snapshot.emit(TestClient.serializer, undefined!).summary;\n\t}\n\n\tpublic getText(): string {\n\t\treturn this.client.getText();\n\t}\n\n\tpublic applyPendingOps(): void {\n\t\tfor (const msg of this.pending) {\n\t\t\tthis.client.applyMsg(msg);\n\t\t}\n\t\tthis.pending.splice(0, this.pending.length);\n\t}\n\n\tprivate queue(op: IMergeTreeOp, increaseMsn: boolean): void {\n\t\tconst refSeq = this.seq;\n\t\tconst seq = ++this.seq;\n\n\t\tthis.pending.push(\n\t\t\tthis.client.makeOpMessage(\n\t\t\t\top,\n\t\t\t\tseq,\n\t\t\t\trefSeq,\n\t\t\t\tthis.client.longClientId,\n\t\t\t\t(this.minSeq = increaseMsn ? seq : this.minSeq),\n\t\t\t),\n\t\t);\n\t}\n\n\tpublic getSegment(pos: number): ISegmentPrivate {\n\t\tconst { segment } = this.client.getContainingSegment<ISegmentPrivate>(pos) ?? {};\n\t\tassert(segment !== undefined);\n\t\treturn segment;\n\t}\n}\n"]}
@@ -50,7 +50,7 @@ describe("SortedSegmentSet", () => {
50
50
  const set = new sortedSegmentSet_js_1.SortedSegmentSet();
51
51
  for (let i = 0; i < client.getLength(); i++) {
52
52
  for (const pos of [i, client.getLength() - 1 - i]) {
53
- const segment = client.getContainingSegment(pos).segment;
53
+ const segment = client.getContainingSegment(pos)?.segment;
54
54
  (0, node_assert_1.strict)(segment);
55
55
  const item = { segment };
56
56
  node_assert_1.strict.equal(set.has(item), false);
@@ -65,7 +65,7 @@ describe("SortedSegmentSet", () => {
65
65
  const set = new sortedSegmentSet_js_1.SortedSegmentSet();
66
66
  for (let i = 0; i < client.getLength(); i++) {
67
67
  for (const pos of [i, client.getLength() - 1 - i]) {
68
- const segment = client.getContainingSegment(pos).segment;
68
+ const segment = client.getContainingSegment(pos)?.segment;
69
69
  (0, node_assert_1.strict)(segment);
70
70
  set.addOrUpdate(segment);
71
71
  node_assert_1.strict.equal(set.has(segment), true);
@@ -79,7 +79,7 @@ describe("SortedSegmentSet", () => {
79
79
  const random = (0, stochastic_test_utils_1.makeRandom)(0);
80
80
  const refsAtAllPositions = [];
81
81
  for (let i = 0; i < client.getLength(); i++) {
82
- const { segment, offset } = client.getContainingSegment(i);
82
+ const { segment, offset } = client.getContainingSegment(i) ?? {};
83
83
  (0, node_assert_1.strict)(segment !== undefined);
84
84
  (0, node_assert_1.strict)(offset !== undefined);
85
85
  refsAtAllPositions.push(client.createLocalReferencePosition(segment, offset, ops_js_1.ReferenceType.SlideOnRemove, undefined));
@@ -1 +1 @@
1
- {"version":3,"file":"sortedSegmentSet.spec.js","sourceRoot":"","sources":["../../src/test/sortedSegmentSet.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 { makeRandom } from \"@fluid-private/stochastic-test-utils\";\n\nimport { LocalReferencePosition } from \"../localReference.js\";\nimport { ISegment, type ISegmentPrivate } from \"../mergeTreeNodes.js\";\nimport { TrackingGroup } from \"../mergeTreeTracking.js\";\nimport { ReferenceType } from \"../ops.js\";\nimport { toMergeNodeInfo } from \"../segmentInfos.js\";\nimport { SortedSegmentSet, SortedSegmentSetItem } from \"../sortedSegmentSet.js\";\n\nimport { TestClient } from \"./testClient.js\";\nconst segmentCount = 15;\n\nfunction validateSorted<T extends SortedSegmentSetItem>(\n\tset: SortedSegmentSet<T>,\n\tgetOrdinal: (item: T) => string | undefined,\n\tprefix: string,\n): void {\n\tfor (let i = 0; i < set.size - 1; i++) {\n\t\tconst a = getOrdinal(set.items[i]);\n\t\tconst b = getOrdinal(set.items[i + 1]);\n\t\tassert(a !== undefined, `${prefix}: Undefined ordinal ${i}`);\n\t\tassert(b !== undefined, `${prefix}: Undefined ordinal ${i + 1}`);\n\t\tassert(a <= b, `${prefix}: Not sorted at item ${i}`);\n\t}\n}\n\nfunction validateSet<T extends SortedSegmentSetItem>(\n\tclient: TestClient,\n\tset: SortedSegmentSet<T>,\n\tgetOrdinal: (item: T) => string | undefined,\n): void {\n\tvalidateSorted(set, getOrdinal, \"initial\");\n\n\t// add content to shift ordinals in tree\n\tfor (let i = 0; i < segmentCount * 5; i++) {\n\t\tclient.insertTextLocal((i * 3) % client.getLength(), `X`);\n\t}\n\tvalidateSorted(set, getOrdinal, \"after insert\");\n\n\tfor (let i = set.size; set.size > 0; i += set.size) {\n\t\t// jump around the list a bit, so its not just an in-order remove\n\t\tconst item = set.items[i % set.size];\n\t\tassert.equal(set.remove(item), true, \"remove failed\");\n\t\tassert.equal(set.has(item), false);\n\t\tvalidateSorted(set, getOrdinal, \"during remove\");\n\t}\n}\n\ndescribe(\"SortedSegmentSet\", () => {\n\tconst localUserLongId = \"localUser\";\n\tlet client: TestClient;\n\tbeforeEach(() => {\n\t\tclient = new TestClient();\n\t\tfor (let i = 0; i < segmentCount; i++) {\n\t\t\tclient.insertTextLocal(client.getLength(), i.toString()[0].repeat(i + 1));\n\t\t}\n\t\tclient.startOrUpdateCollaboration(localUserLongId);\n\t});\n\n\tit(\"SortedSegmentSet of objects with segments\", () => {\n\t\tconst set = new SortedSegmentSet<{ segment: ISegment }>();\n\t\tfor (let i = 0; i < client.getLength(); i++) {\n\t\t\tfor (const pos of [i, client.getLength() - 1 - i]) {\n\t\t\t\tconst segment = client.getContainingSegment<ISegmentPrivate>(pos).segment;\n\t\t\t\tassert(segment);\n\t\t\t\tconst item = { segment };\n\t\t\t\tassert.equal(set.has(item), false);\n\t\t\t\tset.addOrUpdate(item);\n\t\t\t\tassert.equal(set.has(item), true);\n\t\t\t}\n\t\t}\n\t\tassert.equal(set.size, client.getLength() * 2);\n\t\tvalidateSet(client, set, (i) => toMergeNodeInfo(i.segment)?.ordinal);\n\t});\n\n\tit(\"SortedSegmentSet of segments\", () => {\n\t\tconst set = new SortedSegmentSet();\n\t\tfor (let i = 0; i < client.getLength(); i++) {\n\t\t\tfor (const pos of [i, client.getLength() - 1 - i]) {\n\t\t\t\tconst segment = client.getContainingSegment<ISegmentPrivate>(pos).segment;\n\t\t\t\tassert(segment);\n\t\t\t\tset.addOrUpdate(segment);\n\t\t\t\tassert.equal(set.has(segment), true);\n\t\t\t}\n\t\t}\n\t\tassert.equal(set.size, segmentCount);\n\t\tvalidateSet(client, set, (i) => toMergeNodeInfo(i)?.ordinal);\n\t});\n\n\tdescribe(\"SortedSegmentSet of local references\", () => {\n\t\tit(\"Inserts in order\", () => {\n\t\t\tconst random = makeRandom(0);\n\t\t\tconst refsAtAllPositions: LocalReferencePosition[] = [];\n\t\t\tfor (let i = 0; i < client.getLength(); i++) {\n\t\t\t\tconst { segment, offset } = client.getContainingSegment<ISegmentPrivate>(i);\n\t\t\t\tassert(segment !== undefined);\n\t\t\t\tassert(offset !== undefined);\n\t\t\t\trefsAtAllPositions.push(\n\t\t\t\t\tclient.createLocalReferencePosition(\n\t\t\t\t\t\tsegment,\n\t\t\t\t\t\toffset,\n\t\t\t\t\t\tReferenceType.SlideOnRemove,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\trandom.shuffle(refsAtAllPositions);\n\t\t\tconst segmentSet = new SortedSegmentSet<LocalReferencePosition>();\n\t\t\tfor (const ref of refsAtAllPositions) {\n\t\t\t\tsegmentSet.addOrUpdate(ref);\n\t\t\t}\n\n\t\t\t// Validate that the set is sorted\n\t\t\tconst refsBackToPositions = segmentSet.items.map((ref) =>\n\t\t\t\tclient.localReferencePositionToPosition(ref),\n\t\t\t);\n\t\t\tassert.deepEqual(\n\t\t\t\trefsBackToPositions,\n\t\t\t\tArray.from({ length: client.getLength() }, (_, i) => i),\n\t\t\t);\n\t\t});\n\t});\n\n\tit(\"SortedSegmentSet of local references\", () => {\n\t\t// using a sorted segment set directly creates problems,\n\t\t// as we don't correctly split, or merge, so leverage\n\t\t// the tracking group for correct behavior in those case\n\t\t// and spy it's internal set\n\t\tconst set = new TrackingGroup();\n\t\tfor (let i = 0; i < client.getLength(); i++) {\n\t\t\tfor (const pos of [i, client.getLength() - 1 - i]) {\n\t\t\t\tconst segmentInfo = client.getContainingSegment<ISegmentPrivate>(pos);\n\t\t\t\tassert(segmentInfo?.segment);\n\t\t\t\tconst lref = client.createLocalReferencePosition(\n\t\t\t\t\tsegmentInfo.segment,\n\t\t\t\t\tsegmentInfo.offset,\n\t\t\t\t\tReferenceType.SlideOnRemove,\n\t\t\t\t\tundefined,\n\t\t\t\t);\n\t\t\t\tassert.equal(set.has(lref), false);\n\t\t\t\tset.link(lref);\n\t\t\t\tassert.equal(set.has(lref), true);\n\t\t\t}\n\t\t}\n\t\tassert.equal(set.size, client.getLength() * 2);\n\t\tvalidateSet<LocalReferencePosition>(\n\t\t\tclient,\n\t\t\t// Cast to any because we are validating a set of local references, but the instantiated type of trackedSet\n\t\t\t// on TrackingGroup is SortedSegmentSet<Trackable>.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n\t\t\t(set as any).trackedSet,\n\t\t\t(i) => toMergeNodeInfo(i.getSegment())?.ordinal,\n\t\t);\n\t});\n});\n"]}
1
+ {"version":3,"file":"sortedSegmentSet.spec.js","sourceRoot":"","sources":["../../src/test/sortedSegmentSet.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 { makeRandom } from \"@fluid-private/stochastic-test-utils\";\n\nimport { LocalReferencePosition } from \"../localReference.js\";\nimport { ISegment, type ISegmentPrivate } from \"../mergeTreeNodes.js\";\nimport { TrackingGroup } from \"../mergeTreeTracking.js\";\nimport { ReferenceType } from \"../ops.js\";\nimport { toMergeNodeInfo } from \"../segmentInfos.js\";\nimport { SortedSegmentSet, SortedSegmentSetItem } from \"../sortedSegmentSet.js\";\n\nimport { TestClient } from \"./testClient.js\";\nconst segmentCount = 15;\n\nfunction validateSorted<T extends SortedSegmentSetItem>(\n\tset: SortedSegmentSet<T>,\n\tgetOrdinal: (item: T) => string | undefined,\n\tprefix: string,\n): void {\n\tfor (let i = 0; i < set.size - 1; i++) {\n\t\tconst a = getOrdinal(set.items[i]);\n\t\tconst b = getOrdinal(set.items[i + 1]);\n\t\tassert(a !== undefined, `${prefix}: Undefined ordinal ${i}`);\n\t\tassert(b !== undefined, `${prefix}: Undefined ordinal ${i + 1}`);\n\t\tassert(a <= b, `${prefix}: Not sorted at item ${i}`);\n\t}\n}\n\nfunction validateSet<T extends SortedSegmentSetItem>(\n\tclient: TestClient,\n\tset: SortedSegmentSet<T>,\n\tgetOrdinal: (item: T) => string | undefined,\n): void {\n\tvalidateSorted(set, getOrdinal, \"initial\");\n\n\t// add content to shift ordinals in tree\n\tfor (let i = 0; i < segmentCount * 5; i++) {\n\t\tclient.insertTextLocal((i * 3) % client.getLength(), `X`);\n\t}\n\tvalidateSorted(set, getOrdinal, \"after insert\");\n\n\tfor (let i = set.size; set.size > 0; i += set.size) {\n\t\t// jump around the list a bit, so its not just an in-order remove\n\t\tconst item = set.items[i % set.size];\n\t\tassert.equal(set.remove(item), true, \"remove failed\");\n\t\tassert.equal(set.has(item), false);\n\t\tvalidateSorted(set, getOrdinal, \"during remove\");\n\t}\n}\n\ndescribe(\"SortedSegmentSet\", () => {\n\tconst localUserLongId = \"localUser\";\n\tlet client: TestClient;\n\tbeforeEach(() => {\n\t\tclient = new TestClient();\n\t\tfor (let i = 0; i < segmentCount; i++) {\n\t\t\tclient.insertTextLocal(client.getLength(), i.toString()[0].repeat(i + 1));\n\t\t}\n\t\tclient.startOrUpdateCollaboration(localUserLongId);\n\t});\n\n\tit(\"SortedSegmentSet of objects with segments\", () => {\n\t\tconst set = new SortedSegmentSet<{ segment: ISegment }>();\n\t\tfor (let i = 0; i < client.getLength(); i++) {\n\t\t\tfor (const pos of [i, client.getLength() - 1 - i]) {\n\t\t\t\tconst segment = client.getContainingSegment<ISegmentPrivate>(pos)?.segment;\n\t\t\t\tassert(segment);\n\t\t\t\tconst item = { segment };\n\t\t\t\tassert.equal(set.has(item), false);\n\t\t\t\tset.addOrUpdate(item);\n\t\t\t\tassert.equal(set.has(item), true);\n\t\t\t}\n\t\t}\n\t\tassert.equal(set.size, client.getLength() * 2);\n\t\tvalidateSet(client, set, (i) => toMergeNodeInfo(i.segment)?.ordinal);\n\t});\n\n\tit(\"SortedSegmentSet of segments\", () => {\n\t\tconst set = new SortedSegmentSet();\n\t\tfor (let i = 0; i < client.getLength(); i++) {\n\t\t\tfor (const pos of [i, client.getLength() - 1 - i]) {\n\t\t\t\tconst segment = client.getContainingSegment<ISegmentPrivate>(pos)?.segment;\n\t\t\t\tassert(segment);\n\t\t\t\tset.addOrUpdate(segment);\n\t\t\t\tassert.equal(set.has(segment), true);\n\t\t\t}\n\t\t}\n\t\tassert.equal(set.size, segmentCount);\n\t\tvalidateSet(client, set, (i) => toMergeNodeInfo(i)?.ordinal);\n\t});\n\n\tdescribe(\"SortedSegmentSet of local references\", () => {\n\t\tit(\"Inserts in order\", () => {\n\t\t\tconst random = makeRandom(0);\n\t\t\tconst refsAtAllPositions: LocalReferencePosition[] = [];\n\t\t\tfor (let i = 0; i < client.getLength(); i++) {\n\t\t\t\tconst { segment, offset } = client.getContainingSegment<ISegmentPrivate>(i) ?? {};\n\t\t\t\tassert(segment !== undefined);\n\t\t\t\tassert(offset !== undefined);\n\t\t\t\trefsAtAllPositions.push(\n\t\t\t\t\tclient.createLocalReferencePosition(\n\t\t\t\t\t\tsegment,\n\t\t\t\t\t\toffset,\n\t\t\t\t\t\tReferenceType.SlideOnRemove,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\trandom.shuffle(refsAtAllPositions);\n\t\t\tconst segmentSet = new SortedSegmentSet<LocalReferencePosition>();\n\t\t\tfor (const ref of refsAtAllPositions) {\n\t\t\t\tsegmentSet.addOrUpdate(ref);\n\t\t\t}\n\n\t\t\t// Validate that the set is sorted\n\t\t\tconst refsBackToPositions = segmentSet.items.map((ref) =>\n\t\t\t\tclient.localReferencePositionToPosition(ref),\n\t\t\t);\n\t\t\tassert.deepEqual(\n\t\t\t\trefsBackToPositions,\n\t\t\t\tArray.from({ length: client.getLength() }, (_, i) => i),\n\t\t\t);\n\t\t});\n\t});\n\n\tit(\"SortedSegmentSet of local references\", () => {\n\t\t// using a sorted segment set directly creates problems,\n\t\t// as we don't correctly split, or merge, so leverage\n\t\t// the tracking group for correct behavior in those case\n\t\t// and spy it's internal set\n\t\tconst set = new TrackingGroup();\n\t\tfor (let i = 0; i < client.getLength(); i++) {\n\t\t\tfor (const pos of [i, client.getLength() - 1 - i]) {\n\t\t\t\tconst segmentInfo = client.getContainingSegment<ISegmentPrivate>(pos);\n\t\t\t\tassert(segmentInfo?.segment);\n\t\t\t\tconst lref = client.createLocalReferencePosition(\n\t\t\t\t\tsegmentInfo.segment,\n\t\t\t\t\tsegmentInfo.offset,\n\t\t\t\t\tReferenceType.SlideOnRemove,\n\t\t\t\t\tundefined,\n\t\t\t\t);\n\t\t\t\tassert.equal(set.has(lref), false);\n\t\t\t\tset.link(lref);\n\t\t\t\tassert.equal(set.has(lref), true);\n\t\t\t}\n\t\t}\n\t\tassert.equal(set.size, client.getLength() * 2);\n\t\tvalidateSet<LocalReferencePosition>(\n\t\t\tclient,\n\t\t\t// Cast to any because we are validating a set of local references, but the instantiated type of trackedSet\n\t\t\t// on TrackingGroup is SortedSegmentSet<Trackable>.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n\t\t\t(set as any).trackedSet,\n\t\t\t(i) => toMergeNodeInfo(i.getSegment())?.ordinal,\n\t\t);\n\t});\n});\n"]}
@@ -222,8 +222,8 @@ class TestClient extends client_js_1.Client {
222
222
  return posAccumulated <= pos;
223
223
  });
224
224
  (0, node_assert_1.strict)(segment !== undefined, "No segment found");
225
- const segoff = (0, mergeTree_js_1.getSlideToSegoff)({ segment, offset }, undefined, perspective) ?? segment;
226
- if (segoff.segment === undefined || segoff.offset === undefined) {
225
+ const segoff = (0, mergeTree_js_1.getSlideToSegoff)({ segment, offset }, undefined, perspective);
226
+ if (segoff === undefined) {
227
227
  return referencePositions_js_1.DetachedReferencePosition;
228
228
  }
229
229
  return this.findReconnectionPosition(segoff.segment, localSeq) + segoff.offset;
@@ -307,7 +307,7 @@ class TestClient extends client_js_1.Client {
307
307
  }
308
308
  slowSearchForMarker(startPos, markerLabel, forwards = true) {
309
309
  let foundMarker;
310
- const { segment } = this.getContainingSegment(startPos);
310
+ const { segment } = this.getContainingSegment(startPos) ?? {};
311
311
  (0, mergeTreeNodes_js_1.assertSegmentLeaf)(segment);
312
312
  if (mergeTreeNodes_js_1.Marker.is(segment)) {
313
313
  if ((0, referencePositions_js_1.refHasTileLabel)(segment, markerLabel)) {