@fluidframework/merge-tree 2.31.1 → 2.32.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 (137) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/client.d.ts +7 -1
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +153 -44
  5. package/dist/client.js.map +1 -1
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +3 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/mergeTree.d.ts +17 -5
  11. package/dist/mergeTree.d.ts.map +1 -1
  12. package/dist/mergeTree.js +188 -79
  13. package/dist/mergeTree.js.map +1 -1
  14. package/dist/mergeTreeNodes.d.ts +16 -18
  15. package/dist/mergeTreeNodes.d.ts.map +1 -1
  16. package/dist/mergeTreeNodes.js +6 -0
  17. package/dist/mergeTreeNodes.js.map +1 -1
  18. package/dist/perspective.d.ts +9 -0
  19. package/dist/perspective.d.ts.map +1 -1
  20. package/dist/perspective.js +14 -1
  21. package/dist/perspective.js.map +1 -1
  22. package/dist/segmentInfos.d.ts +32 -4
  23. package/dist/segmentInfos.d.ts.map +1 -1
  24. package/dist/segmentInfos.js +3 -1
  25. package/dist/segmentInfos.js.map +1 -1
  26. package/dist/sortedSegmentSet.d.ts +1 -0
  27. package/dist/sortedSegmentSet.d.ts.map +1 -1
  28. package/dist/sortedSegmentSet.js +3 -0
  29. package/dist/sortedSegmentSet.js.map +1 -1
  30. package/dist/test/beastTest.spec.js +5 -5
  31. package/dist/test/beastTest.spec.js.map +1 -1
  32. package/dist/test/client.localReference.spec.js +3 -3
  33. package/dist/test/client.localReference.spec.js.map +1 -1
  34. package/dist/test/client.rollback.spec.js +17 -0
  35. package/dist/test/client.rollback.spec.js.map +1 -1
  36. package/dist/test/clientTestHelper.d.ts +100 -0
  37. package/dist/test/clientTestHelper.d.ts.map +1 -0
  38. package/dist/test/clientTestHelper.js +196 -0
  39. package/dist/test/clientTestHelper.js.map +1 -0
  40. package/dist/test/mergeTree.annotate.spec.js +12 -12
  41. package/dist/test/mergeTree.annotate.spec.js.map +1 -1
  42. package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +1 -1
  43. package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -1
  44. package/dist/test/obliterate.concurrent.spec.js +93 -90
  45. package/dist/test/obliterate.concurrent.spec.js.map +1 -1
  46. package/dist/test/obliterate.deltaCallback.spec.js +121 -116
  47. package/dist/test/obliterate.deltaCallback.spec.js.map +1 -1
  48. package/dist/test/obliterate.rangeExpansion.spec.js +29 -79
  49. package/dist/test/obliterate.rangeExpansion.spec.js.map +1 -1
  50. package/dist/test/obliterate.reconnect.spec.js +235 -58
  51. package/dist/test/obliterate.reconnect.spec.js.map +1 -1
  52. package/dist/test/testClient.js +1 -1
  53. package/dist/test/testClient.js.map +1 -1
  54. package/dist/test/testUtils.d.ts +13 -0
  55. package/dist/test/testUtils.d.ts.map +1 -1
  56. package/dist/test/testUtils.js +22 -1
  57. package/dist/test/testUtils.js.map +1 -1
  58. package/lib/client.d.ts +7 -1
  59. package/lib/client.d.ts.map +1 -1
  60. package/lib/client.js +155 -46
  61. package/lib/client.js.map +1 -1
  62. package/lib/index.d.ts +1 -1
  63. package/lib/index.d.ts.map +1 -1
  64. package/lib/index.js +1 -0
  65. package/lib/index.js.map +1 -1
  66. package/lib/mergeTree.d.ts +17 -5
  67. package/lib/mergeTree.d.ts.map +1 -1
  68. package/lib/mergeTree.js +192 -83
  69. package/lib/mergeTree.js.map +1 -1
  70. package/lib/mergeTreeNodes.d.ts +16 -18
  71. package/lib/mergeTreeNodes.d.ts.map +1 -1
  72. package/lib/mergeTreeNodes.js +7 -1
  73. package/lib/mergeTreeNodes.js.map +1 -1
  74. package/lib/perspective.d.ts +9 -0
  75. package/lib/perspective.d.ts.map +1 -1
  76. package/lib/perspective.js +12 -0
  77. package/lib/perspective.js.map +1 -1
  78. package/lib/segmentInfos.d.ts +32 -4
  79. package/lib/segmentInfos.d.ts.map +1 -1
  80. package/lib/segmentInfos.js +2 -1
  81. package/lib/segmentInfos.js.map +1 -1
  82. package/lib/sortedSegmentSet.d.ts +1 -0
  83. package/lib/sortedSegmentSet.d.ts.map +1 -1
  84. package/lib/sortedSegmentSet.js +3 -0
  85. package/lib/sortedSegmentSet.js.map +1 -1
  86. package/lib/test/beastTest.spec.js +5 -5
  87. package/lib/test/beastTest.spec.js.map +1 -1
  88. package/lib/test/client.localReference.spec.js +3 -3
  89. package/lib/test/client.localReference.spec.js.map +1 -1
  90. package/lib/test/client.rollback.spec.js +18 -1
  91. package/lib/test/client.rollback.spec.js.map +1 -1
  92. package/lib/test/clientTestHelper.d.ts +100 -0
  93. package/lib/test/clientTestHelper.d.ts.map +1 -0
  94. package/lib/test/clientTestHelper.js +192 -0
  95. package/lib/test/clientTestHelper.js.map +1 -0
  96. package/lib/test/mergeTree.annotate.spec.js +12 -12
  97. package/lib/test/mergeTree.annotate.spec.js.map +1 -1
  98. package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +1 -1
  99. package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -1
  100. package/lib/test/obliterate.concurrent.spec.js +93 -90
  101. package/lib/test/obliterate.concurrent.spec.js.map +1 -1
  102. package/lib/test/obliterate.deltaCallback.spec.js +121 -116
  103. package/lib/test/obliterate.deltaCallback.spec.js.map +1 -1
  104. package/lib/test/obliterate.rangeExpansion.spec.js +1 -51
  105. package/lib/test/obliterate.rangeExpansion.spec.js.map +1 -1
  106. package/lib/test/obliterate.reconnect.spec.js +236 -59
  107. package/lib/test/obliterate.reconnect.spec.js.map +1 -1
  108. package/lib/test/testClient.js +1 -1
  109. package/lib/test/testClient.js.map +1 -1
  110. package/lib/test/testUtils.d.ts +13 -0
  111. package/lib/test/testUtils.d.ts.map +1 -1
  112. package/lib/test/testUtils.js +20 -0
  113. package/lib/test/testUtils.js.map +1 -1
  114. package/package.json +18 -17
  115. package/src/client.ts +286 -55
  116. package/src/index.ts +1 -1
  117. package/src/mergeTree.ts +265 -98
  118. package/src/mergeTreeNodes.ts +24 -18
  119. package/src/perspective.ts +21 -0
  120. package/src/segmentInfos.ts +48 -6
  121. package/src/sortedSegmentSet.ts +4 -0
  122. package/dist/test/partialSyncHelper.d.ts +0 -42
  123. package/dist/test/partialSyncHelper.d.ts.map +0 -1
  124. package/dist/test/partialSyncHelper.js +0 -96
  125. package/dist/test/partialSyncHelper.js.map +0 -1
  126. package/dist/test/reconnectHelper.d.ts +0 -50
  127. package/dist/test/reconnectHelper.d.ts.map +0 -1
  128. package/dist/test/reconnectHelper.js +0 -106
  129. package/dist/test/reconnectHelper.js.map +0 -1
  130. package/lib/test/partialSyncHelper.d.ts +0 -42
  131. package/lib/test/partialSyncHelper.d.ts.map +0 -1
  132. package/lib/test/partialSyncHelper.js +0 -92
  133. package/lib/test/partialSyncHelper.js.map +0 -1
  134. package/lib/test/reconnectHelper.d.ts +0 -50
  135. package/lib/test/reconnectHelper.d.ts.map +0 -1
  136. package/lib/test/reconnectHelper.js +0 -102
  137. package/lib/test/reconnectHelper.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @fluidframework/merge-tree
2
2
 
3
+ ## 2.32.0
4
+
5
+ Dependency updates only.
6
+
3
7
  ## 2.31.0
4
8
 
5
9
  Dependency updates only.
package/dist/client.d.ts CHANGED
@@ -227,6 +227,11 @@ export declare class Client extends TypedEventEmitter<IClientEvents> {
227
227
  * @param localSeq - The localSeq to find the position of the segment at
228
228
  */
229
229
  findReconnectionPosition(segment: ISegment, localSeq: number): number;
230
+ /**
231
+ * Rebases a sided local reference to the best fitting position in the current tree.
232
+ */
233
+ private rebaseSidedLocalReference;
234
+ private computeNewObliterateEndpoints;
230
235
  private resetPendingDeltaToOps;
231
236
  private applyRemoteOp;
232
237
  applyStashedOp(op: IMergeTreeOp): void;
@@ -241,8 +246,9 @@ export declare class Client extends TypedEventEmitter<IClientEvents> {
241
246
  * @param remoteClientId - The client id of the remote client
242
247
  */
243
248
  resolveRemoteClientPosition(remoteClientPosition: number, remoteClientRefSeq: number, remoteClientId: string): number | undefined;
244
- private lastNormalizationRefSeq;
249
+ private lastNormalization;
245
250
  private pendingRebase;
251
+ private readonly cachedObliterateRebases;
246
252
  /**
247
253
  * Given a pending operation and segment group, regenerate the op, so it
248
254
  * can be resubmitted
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js CHANGED
@@ -37,6 +37,7 @@ const internal_4 = require("@fluidframework/telemetry-utils/internal");
37
37
  const MergeTreeTextHelper_js_1 = require("./MergeTreeTextHelper.js");
38
38
  const index_js_1 = require("./collections/index.js");
39
39
  const constants_js_1 = require("./constants.js");
40
+ const localReference_js_1 = require("./localReference.js");
40
41
  const mergeTree_js_1 = require("./mergeTree.js");
41
42
  const mergeTreeNodeWalk_js_1 = require("./mergeTreeNodeWalk.js");
42
43
  const mergeTreeNodes_js_1 = require("./mergeTreeNodes.js");
@@ -82,7 +83,7 @@ class Client extends client_utils_1.TypedEventEmitter {
82
83
  this.getMinInFlightRefSeq = getMinInFlightRefSeq;
83
84
  this.clientNameToIds = new index_js_1.RedBlackTree(mergeTreeNodes_js_1.compareStrings);
84
85
  this.shortClientIdMap = [];
85
- this.lastNormalizationRefSeq = 0;
86
+ this.cachedObliterateRebases = new Map();
86
87
  this._mergeTree = new mergeTree_js_1.MergeTree(options);
87
88
  this._mergeTree.mergeTreeDeltaCallback = (opArgs, deltaArgs) => {
88
89
  this.emit("delta", opArgs, deltaArgs, this);
@@ -518,7 +519,7 @@ class Client extends client_utils_1.TypedEventEmitter {
518
519
  ackPendingSegment(opArgs) {
519
520
  if (opArgs.op.type === ops_js_1.MergeTreeDeltaType.GROUP) {
520
521
  for (const memberOp of opArgs.op.ops) {
521
- this._mergeTree.ackPendingSegment({
522
+ this._mergeTree.ackOp({
522
523
  groupOp: opArgs.op,
523
524
  op: memberOp,
524
525
  sequencedMessage: opArgs.sequencedMessage,
@@ -526,7 +527,7 @@ class Client extends client_utils_1.TypedEventEmitter {
526
527
  }
527
528
  }
528
529
  else {
529
- this._mergeTree.ackPendingSegment(opArgs);
530
+ this._mergeTree.ackOp(opArgs);
530
531
  }
531
532
  }
532
533
  getOrAddShortClientId(longClientId) {
@@ -566,22 +567,140 @@ class Client extends client_utils_1.TypedEventEmitter {
566
567
  const perspective = new perspective_js_1.LocalReconnectingPerspective(currentSeq, clientId, localSeq);
567
568
  return this._mergeTree.getPosition(segment, perspective);
568
569
  }
570
+ /**
571
+ * Rebases a sided local reference to the best fitting position in the current tree.
572
+ */
573
+ rebaseSidedLocalReference(ref, side, reconnectingPerspective, slidePreference) {
574
+ const oldSegment = ref.getSegment();
575
+ const oldOffset = ref.getOffset();
576
+ (0, internal_1.assert)(oldSegment !== undefined && oldOffset !== undefined, 0xb61 /* Invalid old reference */);
577
+ const useNewSlidingBehavior = true;
578
+ // Destructuring segment + offset is convenient and segment is reassigned
579
+ // eslint-disable-next-line prefer-const
580
+ let { segment: newSegment, offset: newOffset } = (0, mergeTree_js_1.getSlideToSegoff)({ segment: oldSegment, offset: oldOffset }, slidePreference, reconnectingPerspective, useNewSlidingBehavior);
581
+ newSegment ??=
582
+ slidePreference === localReference_js_1.SlidingPreference.FORWARD
583
+ ? this._mergeTree.endOfTree
584
+ : this._mergeTree.startOfTree;
585
+ (0, internal_1.assert)((0, mergeTreeNodes_js_1.isSegmentLeaf)(newSegment) && newOffset !== undefined, 0xb62 /* Invalid new segment on rebase */);
586
+ const newSide = newSegment === oldSegment
587
+ ? side
588
+ : // If the reference slid to a new position, the closest fit to the original position will be independent of
589
+ // the original side and "in the direction of where the reference was".
590
+ slidePreference === localReference_js_1.SlidingPreference.FORWARD
591
+ ? sequencePlace_js_1.Side.Before
592
+ : sequencePlace_js_1.Side.After;
593
+ return { segment: newSegment, offset: newOffset, side: newSide };
594
+ }
595
+ computeNewObliterateEndpoints(obliterateInfo) {
596
+ const { currentSeq, clientId } = this.getCollabWindow();
597
+ const reconnectingPerspective = new perspective_js_1.LocalReconnectingPerspective(currentSeq, clientId, obliterateInfo.stamp.localSeq - 1);
598
+ const newStart = this.rebaseSidedLocalReference(obliterateInfo.start, obliterateInfo.startSide, reconnectingPerspective, localReference_js_1.SlidingPreference.FORWARD);
599
+ const newEnd = this.rebaseSidedLocalReference(obliterateInfo.end, obliterateInfo.endSide, reconnectingPerspective, localReference_js_1.SlidingPreference.BACKWARD);
600
+ return {
601
+ start: newStart,
602
+ end: newEnd,
603
+ };
604
+ }
569
605
  resetPendingDeltaToOps(resetOp, segmentGroup) {
570
606
  (0, internal_1.assert)(!!segmentGroup, 0x033 /* "Segment group undefined" */);
571
607
  const NACKedSegmentGroup = this.pendingRebase?.shift()?.data;
572
608
  (0, internal_1.assert)(segmentGroup === NACKedSegmentGroup, 0x034 /* "Segment group not at head of pending rebase queue" */);
609
+ (0, internal_1.assert)(segmentGroup.localSeq !== undefined, 0x867 /* expected segment group localSeq to be defined */);
573
610
  if (this.pendingRebase?.empty) {
574
611
  this.pendingRebase = undefined;
575
612
  }
576
- // if this is an obliterate op, keep all segments in same segment group
577
- const obliterateSegmentGroup = {
578
- segments: [],
579
- localSeq: segmentGroup.localSeq,
580
- refSeq: this.getCollabWindow().currentSeq,
581
- obliterateInfo: {
582
- ...segmentGroup.obliterateInfo,
583
- },
584
- };
613
+ if (resetOp.type === ops_js_1.MergeTreeDeltaType.OBLITERATE ||
614
+ resetOp.type === ops_js_1.MergeTreeDeltaType.OBLITERATE_SIDED) {
615
+ (0, mergeTree_js_1.errorIfOptionNotTrue)(this._mergeTree.options, "mergeTreeEnableObliterateReconnect");
616
+ // sliceRemove reconnect logic is characteristically different from other ops (which can only apply to segments they originally saw).
617
+ // This is because the ranges that other ops apply to can be broken up by concurrent insertions, so even though setRemoves are originally
618
+ // applied to a contiguous set of segments, at resubmission time they may no longer be.
619
+ // On the other hand, the closest analog to a `sliceRemove` that we can submit is obtained by resolving the "closest" start and end points
620
+ // for that slice, updating the local obliterate metadata to reflect that slice, and submitting a single op.
621
+ const obliterateInfo = segmentGroup.obliterateInfo;
622
+ (0, internal_1.assert)(obliterateInfo !== undefined, 0xb63 /* Resubmitting obliterate op without obliterate info in segment group */);
623
+ (0, internal_1.assert)(obliterateInfo.stamp.localSeq === segmentGroup.localSeq, 0xb64 /* Local seq mismatch */);
624
+ const cachedNewPositions = this.cachedObliterateRebases.get(obliterateInfo.stamp.localSeq);
625
+ (0, internal_1.assert)(cachedNewPositions !== undefined, 0xb65 /* didn't compute new positions for obliterate on reconnect early enough */);
626
+ const { start: { segment: newStartSegment, offset: newStartOffset, side: newStartSide }, end: { segment: newEndSegment, offset: newEndOffset, side: newEndSide }, } = cachedNewPositions;
627
+ const { currentSeq, clientId } = this.getCollabWindow();
628
+ if (newEndSegment.ordinal < newStartSegment.ordinal) {
629
+ for (const segment of segmentGroup.segments) {
630
+ (0, internal_1.assert)((0, mergeTree_js_1.isRemovedAndAcked)(segment), 0xb66 /* On reconnect, obliterate applied to new segments even though original ones were not removed. */);
631
+ const lastRemove = segment.removes[segment.removes.length - 1];
632
+ (0, internal_1.assert)(lastRemove.type === "sliceRemove" && lastRemove.localSeq === segmentGroup.localSeq, 0xb67 /* Last remove should be the obliterate that is being resubmitted. */);
633
+ // The original obliterate affected this segment, but it has since been removed and overlapping removes
634
+ // are only possible when they are concurrent. We adjust the metadata on that segment now to reflect
635
+ // the fact that the obliterate no longer affects it.
636
+ segment.removes.pop();
637
+ }
638
+ this._mergeTree.rebaseObliterateTo(obliterateInfo, undefined);
639
+ return [];
640
+ }
641
+ (0, internal_1.assert)(obliterateInfo.tiebreakTrackingGroup !== undefined, 0xb68 /* Tiebreak tracking group missing */);
642
+ const newObliterate = {
643
+ // Recreate the start position using the perspective that other clients will see.
644
+ // This may not be at the same position as the original reference, since the segment the original reference was on could have been removed.
645
+ start: this._mergeTree.createLocalReferencePosition(newStartSegment, newStartOffset, ops_js_1.ReferenceType.StayOnRemove, undefined),
646
+ startSide: newStartSide,
647
+ end: this._mergeTree.createLocalReferencePosition(newEndSegment, newEndOffset, ops_js_1.ReferenceType.StayOnRemove, undefined),
648
+ endSide: newEndSide,
649
+ refSeq: currentSeq,
650
+ // We reuse the localSeq from the original obliterate.
651
+ stamp: obliterateInfo.stamp,
652
+ segmentGroup: undefined,
653
+ tiebreakTrackingGroup: obliterateInfo.tiebreakTrackingGroup,
654
+ };
655
+ newObliterate.start.addProperties({ obliterate: newObliterate });
656
+ newObliterate.end.addProperties({ obliterate: newObliterate });
657
+ newObliterate.segmentGroup = {
658
+ segments: [],
659
+ localSeq: segmentGroup.localSeq,
660
+ refSeq: this.getCollabWindow().currentSeq,
661
+ obliterateInfo: newObliterate,
662
+ };
663
+ for (const segment of segmentGroup.segments) {
664
+ (0, internal_1.assert)(segment.segmentGroups?.remove(segmentGroup) === true, 0x035 /* "Segment group not in segment pending queue" */);
665
+ if ((segment.ordinal > newStartSegment.ordinal &&
666
+ segment.ordinal < newEndSegment.ordinal) ||
667
+ (segment === newStartSegment && newStartSide === sequencePlace_js_1.Side.Before) ||
668
+ (segment === newEndSegment && newEndSide === sequencePlace_js_1.Side.After)) {
669
+ segment.segmentGroups.enqueue(newObliterate.segmentGroup);
670
+ }
671
+ else {
672
+ (0, internal_1.assert)((0, mergeTree_js_1.isRemovedAndAcked)(segment), 0xb69 /* On reconnect, obliterate applied to new segments even though original ones were not removed. */);
673
+ const lastRemove = segment.removes[segment.removes.length - 1];
674
+ (0, internal_1.assert)(lastRemove.type === "sliceRemove" && lastRemove.localSeq === segmentGroup.localSeq, 0xb6a /* Last remove should be the obliterate that is being resubmitted. */);
675
+ // The original obliterate affected this segment, but it has since been removed and it's impossible to apply the
676
+ // local obliterate so that is so. We adjust the metadata on that segment now.
677
+ segment.removes.pop();
678
+ }
679
+ }
680
+ this._mergeTree.rebaseObliterateTo(obliterateInfo, newObliterate);
681
+ this._mergeTree.pendingSegments.push(newObliterate.segmentGroup);
682
+ const reconnectingPerspective = new perspective_js_1.LocalReconnectingPerspective(currentSeq, clientId, obliterateInfo.stamp.localSeq - 1);
683
+ const newStartPos = this._mergeTree.getPosition(newStartSegment, reconnectingPerspective) + newStartOffset;
684
+ const newEndPos = this._mergeTree.getPosition(newEndSegment, reconnectingPerspective) + newEndOffset;
685
+ if (resetOp.type === ops_js_1.MergeTreeDeltaType.OBLITERATE) {
686
+ (0, internal_1.assert)(newStartSide === sequencePlace_js_1.Side.Before && newEndSide === sequencePlace_js_1.Side.After, 0xb6b /* Non-sided obliterate should have start side before and end side after */);
687
+ // Use a non-sided obliterate op if the original op was non-sided. Some combinations of feature flags disallow sided obliterate ops
688
+ // but allow non-sided ones, and if we convert a non-sided op to a sided one on reconnect, we may cause errors.
689
+ return [
690
+ (0, opBuilder_js_1.createObliterateRangeOp)(newStartPos, newEndPos +
691
+ 1 /* to make the end exclusive, see corresponding -1 in `createObliterateRangeOpSided` on converting non-sided to sided. */),
692
+ ];
693
+ }
694
+ return [
695
+ (0, opBuilder_js_1.createObliterateRangeOpSided)({
696
+ pos: newStartPos,
697
+ side: newStartSide,
698
+ }, {
699
+ pos: newEndPos,
700
+ side: newEndSide,
701
+ }),
702
+ ];
703
+ }
585
704
  const opList = [];
586
705
  // We need to sort the segments by ordinal, as the segments are not sorted in the segment group.
587
706
  // The reason they need them sorted, as they have the same local sequence number and which means
@@ -589,8 +708,7 @@ class Client extends client_utils_1.TypedEventEmitter {
589
708
  // By sorting we ensure the nearer segment will be applied and sequenced before the farther segments
590
709
  // so their recalculated positions will be correct.
591
710
  for (const segment of segmentGroup.segments.sort((a, b) => a.ordinal < b.ordinal ? -1 : 1)) {
592
- (0, internal_1.assert)(segment.segmentGroups?.remove(segmentGroup) === true, 0x035 /* "Segment group not in segment pending queue" */);
593
- (0, internal_1.assert)(segmentGroup.localSeq !== undefined, 0x867 /* expected segment group localSeq to be defined */);
711
+ (0, internal_1.assert)(segment.segmentGroups?.remove(segmentGroup) === true, 0xb6c /* Segment group not in segment pending queue */);
594
712
  const segmentPosition = this.findReconnectionPosition(segment, segmentGroup.localSeq);
595
713
  let newOp;
596
714
  switch (resetOp.type) {
@@ -644,33 +762,11 @@ class Client extends client_utils_1.TypedEventEmitter {
644
762
  }
645
763
  break;
646
764
  }
647
- case ops_js_1.MergeTreeDeltaType.OBLITERATE: {
648
- (0, mergeTree_js_1.errorIfOptionNotTrue)(this._mergeTree.options, "mergeTreeEnableObliterateReconnect");
649
- // Only bother resubmitting if nobody else has removed it in the meantime.
650
- // When that happens, the first removal will have been acked.
651
- if ((0, segmentInfos_js_1.isRemoved)(segment) && opstampUtils.isLocal(segment.removes[0])) {
652
- newOp = (0, opBuilder_js_1.createObliterateRangeOp)(segmentPosition, segmentPosition + segment.cachedLength);
653
- }
654
- break;
655
- }
656
765
  default: {
657
766
  throw new Error(`Invalid op type`);
658
767
  }
659
768
  }
660
- if (newOp && resetOp.type === ops_js_1.MergeTreeDeltaType.OBLITERATE) {
661
- segment.segmentGroups.enqueue(obliterateSegmentGroup);
662
- const first = opList[0];
663
- if (!!first &&
664
- first.pos2 !== undefined &&
665
- first.type !== ops_js_1.MergeTreeDeltaType.OBLITERATE_SIDED &&
666
- newOp.type !== ops_js_1.MergeTreeDeltaType.OBLITERATE_SIDED) {
667
- first.pos2 += newOp.pos2 - newOp.pos1;
668
- }
669
- else {
670
- opList.push(newOp);
671
- }
672
- }
673
- else if (newOp) {
769
+ if (newOp) {
674
770
  const newSegmentGroup = {
675
771
  segments: [],
676
772
  localSeq: segmentGroup.localSeq,
@@ -681,10 +777,6 @@ class Client extends client_utils_1.TypedEventEmitter {
681
777
  opList.push(newOp);
682
778
  }
683
779
  }
684
- if (resetOp.type === ops_js_1.MergeTreeDeltaType.OBLITERATE &&
685
- obliterateSegmentGroup.segments.length > 0) {
686
- this._mergeTree.pendingSegments.push(obliterateSegmentGroup);
687
- }
688
780
  return opList;
689
781
  }
690
782
  applyRemoteOp(opArgs) {
@@ -815,11 +907,28 @@ class Client extends client_utils_1.TypedEventEmitter {
815
907
  (0, internal_1.assert)(firstGroupNode !== undefined, 0x70e /* segment group must exist in pending list */);
816
908
  this.pendingRebase = this._mergeTree.pendingSegments.splice(firstGroupNode);
817
909
  }
818
- const rebaseTo = this.getCollabWindow().currentSeq;
819
- if (rebaseTo !== this.lastNormalizationRefSeq) {
910
+ const collabWindow = this.getCollabWindow();
911
+ if (this.lastNormalization === undefined ||
912
+ collabWindow.currentSeq !== this.lastNormalization.refSeq ||
913
+ collabWindow.localSeq !== this.lastNormalization.localRefSeq) {
914
+ // Compute obliterate endpoint destinations before segments are normalized.
915
+ // Segment normalization can affect what should be the semantically correct segments for the endpoints to be placed on.
916
+ this.cachedObliterateRebases.clear();
917
+ for (const group of [...this._mergeTree.pendingSegments, ...this.pendingRebase]) {
918
+ const { obliterateInfo } = group.data;
919
+ if (obliterateInfo !== undefined) {
920
+ const { start, end } = this.computeNewObliterateEndpoints(obliterateInfo);
921
+ const { localSeq } = obliterateInfo.stamp;
922
+ (0, internal_1.assert)(localSeq !== undefined, 0xb6d /* Local seq must be defined */);
923
+ this.cachedObliterateRebases.set(localSeq, { start, end });
924
+ }
925
+ }
820
926
  this.emit("normalize", this);
821
927
  this._mergeTree.normalizeSegmentsOnRebase();
822
- this.lastNormalizationRefSeq = rebaseTo;
928
+ this.lastNormalization = {
929
+ refSeq: collabWindow.currentSeq,
930
+ localRefSeq: collabWindow.localSeq,
931
+ };
823
932
  }
824
933
  const opList = [];
825
934
  if (resetOp.type === ops_js_1.MergeTreeDeltaType.GROUP) {