@fluidframework/merge-tree 2.30.0 → 2.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +403 -399
- package/api-report/merge-tree.legacy.alpha.api.md +1 -0
- package/dist/MergeTreeTextHelper.d.ts +9 -3
- package/dist/MergeTreeTextHelper.d.ts.map +1 -1
- package/dist/MergeTreeTextHelper.js +5 -5
- package/dist/MergeTreeTextHelper.js.map +1 -1
- package/dist/client.d.ts +7 -13
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +136 -110
- package/dist/client.js.map +1 -1
- package/dist/endOfTreeSegment.d.ts +12 -8
- package/dist/endOfTreeSegment.d.ts.map +1 -1
- package/dist/endOfTreeSegment.js +2 -4
- package/dist/endOfTreeSegment.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/mergeTree.d.ts +37 -23
- package/dist/mergeTree.d.ts.map +1 -1
- package/dist/mergeTree.js +400 -483
- package/dist/mergeTree.js.map +1 -1
- package/dist/mergeTreeDeltaCallback.d.ts +4 -8
- package/dist/mergeTreeDeltaCallback.d.ts.map +1 -1
- package/dist/mergeTreeDeltaCallback.js.map +1 -1
- package/dist/mergeTreeNodes.d.ts +32 -10
- package/dist/mergeTreeNodes.d.ts.map +1 -1
- package/dist/mergeTreeNodes.js +43 -28
- package/dist/mergeTreeNodes.js.map +1 -1
- package/dist/partialLengths.d.ts +2 -2
- package/dist/partialLengths.d.ts.map +1 -1
- package/dist/partialLengths.js +181 -109
- package/dist/partialLengths.js.map +1 -1
- package/dist/perspective.d.ts +8 -27
- package/dist/perspective.d.ts.map +1 -1
- package/dist/perspective.js +7 -67
- package/dist/perspective.js.map +1 -1
- package/dist/revertibles.d.ts.map +1 -1
- package/dist/revertibles.js +2 -2
- package/dist/revertibles.js.map +1 -1
- package/dist/segmentInfos.d.ts +20 -106
- package/dist/segmentInfos.d.ts.map +1 -1
- package/dist/segmentInfos.js +28 -42
- package/dist/segmentInfos.js.map +1 -1
- package/dist/segmentPropertiesManager.d.ts +1 -14
- package/dist/segmentPropertiesManager.d.ts.map +1 -1
- package/dist/segmentPropertiesManager.js +3 -17
- package/dist/segmentPropertiesManager.js.map +1 -1
- package/dist/snapshotLoader.d.ts.map +1 -1
- package/dist/snapshotLoader.js +62 -19
- package/dist/snapshotLoader.js.map +1 -1
- package/dist/snapshotV1.d.ts.map +1 -1
- package/dist/snapshotV1.js +55 -24
- package/dist/snapshotV1.js.map +1 -1
- package/dist/snapshotlegacy.d.ts.map +1 -1
- package/dist/snapshotlegacy.js +6 -9
- package/dist/snapshotlegacy.js.map +1 -1
- package/dist/stamps.d.ts +1 -1
- package/dist/stamps.js +1 -1
- package/dist/stamps.js.map +1 -1
- package/dist/test/Insertion.perf.spec.js +6 -51
- package/dist/test/Insertion.perf.spec.js.map +1 -1
- package/dist/test/PartialLengths.perf.spec.js +18 -25
- package/dist/test/PartialLengths.perf.spec.js.map +1 -1
- package/dist/test/Removal.perf.spec.js +13 -41
- package/dist/test/Removal.perf.spec.js.map +1 -1
- package/dist/test/beastTest.spec.d.ts.map +1 -1
- package/dist/test/beastTest.spec.js +41 -66
- package/dist/test/beastTest.spec.js.map +1 -1
- package/dist/test/client.annotateMarker.spec.js +1 -11
- package/dist/test/client.annotateMarker.spec.js.map +1 -1
- package/dist/test/client.applyMsg.spec.js +14 -14
- package/dist/test/client.applyMsg.spec.js.map +1 -1
- package/dist/test/client.getPosition.spec.js +1 -1
- package/dist/test/client.getPosition.spec.js.map +1 -1
- package/dist/test/client.localReference.spec.js +1 -1
- package/dist/test/client.localReference.spec.js.map +1 -1
- package/dist/test/client.rollback.spec.js +49 -58
- package/dist/test/client.rollback.spec.js.map +1 -1
- package/dist/test/client.rollbackFarm.spec.js +1 -1
- package/dist/test/client.rollbackFarm.spec.js.map +1 -1
- package/dist/test/client.searchForMarker.spec.js +4 -21
- package/dist/test/client.searchForMarker.spec.js.map +1 -1
- package/dist/test/index.d.ts +2 -2
- package/dist/test/index.d.ts.map +1 -1
- package/dist/test/index.js +2 -6
- package/dist/test/index.js.map +1 -1
- package/dist/test/mergeTree.annotate.deltaCallback.spec.js +14 -59
- package/dist/test/mergeTree.annotate.deltaCallback.spec.js.map +1 -1
- package/dist/test/mergeTree.annotate.spec.js +47 -63
- package/dist/test/mergeTree.annotate.spec.js.map +1 -1
- package/dist/test/mergeTree.insert.deltaCallback.spec.js +9 -62
- package/dist/test/mergeTree.insert.deltaCallback.spec.js.map +1 -1
- package/dist/test/mergeTree.insertingWalk.spec.js +59 -125
- package/dist/test/mergeTree.insertingWalk.spec.js.map +1 -1
- package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +12 -93
- package/dist/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -1
- package/dist/test/mergeTree.markRangeRemoved.spec.js +10 -7
- package/dist/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
- package/dist/test/mergeTree.walk.spec.js +2 -14
- package/dist/test/mergeTree.walk.spec.js.map +1 -1
- package/dist/test/mergeTreeOperationRunner.js +2 -2
- package/dist/test/mergeTreeOperationRunner.js.map +1 -1
- package/dist/test/obliterate.concurrent.spec.js +18 -23
- package/dist/test/obliterate.concurrent.spec.js.map +1 -1
- package/dist/test/obliterate.partialLength.spec.js +166 -136
- package/dist/test/obliterate.partialLength.spec.js.map +1 -1
- package/dist/test/obliterate.spec.js +16 -126
- package/dist/test/obliterate.spec.js.map +1 -1
- package/dist/test/partialLength.spec.js +28 -196
- package/dist/test/partialLength.spec.js.map +1 -1
- package/dist/test/perspective.spec.js +34 -0
- package/dist/test/perspective.spec.js.map +1 -1
- package/dist/test/propertyManager.spec.js +1 -1
- package/dist/test/propertyManager.spec.js.map +1 -1
- package/dist/test/resetPendingSegmentsToOp.spec.js +0 -2
- package/dist/test/resetPendingSegmentsToOp.spec.js.map +1 -1
- package/dist/test/segmentGroupCollection.spec.js +10 -4
- package/dist/test/segmentGroupCollection.spec.js.map +1 -1
- package/dist/test/testClient.d.ts +1 -0
- package/dist/test/testClient.d.ts.map +1 -1
- package/dist/test/testClient.js +16 -26
- package/dist/test/testClient.js.map +1 -1
- package/dist/test/testClientLogger.d.ts.map +1 -1
- package/dist/test/testClientLogger.js +3 -10
- package/dist/test/testClientLogger.js.map +1 -1
- package/dist/test/testServer.d.ts +2 -1
- package/dist/test/testServer.d.ts.map +1 -1
- package/dist/test/testServer.js +7 -5
- package/dist/test/testServer.js.map +1 -1
- package/dist/test/testUtils.d.ts +36 -56
- package/dist/test/testUtils.d.ts.map +1 -1
- package/dist/test/testUtils.js +68 -77
- package/dist/test/testUtils.js.map +1 -1
- package/dist/test/text.d.ts +2 -2
- package/dist/test/text.d.ts.map +1 -1
- package/dist/test/text.js +5 -2
- package/dist/test/text.js.map +1 -1
- package/dist/textSegment.d.ts +0 -6
- package/dist/textSegment.d.ts.map +1 -1
- package/dist/textSegment.js.map +1 -1
- package/dist/zamboni.d.ts.map +1 -1
- package/dist/zamboni.js +53 -26
- package/dist/zamboni.js.map +1 -1
- package/lib/MergeTreeTextHelper.d.ts +9 -3
- package/lib/MergeTreeTextHelper.d.ts.map +1 -1
- package/lib/MergeTreeTextHelper.js +5 -5
- package/lib/MergeTreeTextHelper.js.map +1 -1
- package/lib/client.d.ts +7 -13
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +117 -116
- package/lib/client.js.map +1 -1
- package/lib/endOfTreeSegment.d.ts +12 -8
- package/lib/endOfTreeSegment.d.ts.map +1 -1
- package/lib/endOfTreeSegment.js +2 -4
- package/lib/endOfTreeSegment.js.map +1 -1
- package/lib/index.d.ts +6 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/mergeTree.d.ts +37 -23
- package/lib/mergeTree.d.ts.map +1 -1
- package/lib/mergeTree.js +381 -488
- package/lib/mergeTree.js.map +1 -1
- package/lib/mergeTreeDeltaCallback.d.ts +4 -8
- package/lib/mergeTreeDeltaCallback.d.ts.map +1 -1
- package/lib/mergeTreeDeltaCallback.js.map +1 -1
- package/lib/mergeTreeNodes.d.ts +32 -10
- package/lib/mergeTreeNodes.d.ts.map +1 -1
- package/lib/mergeTreeNodes.js +42 -29
- package/lib/mergeTreeNodes.js.map +1 -1
- package/lib/partialLengths.d.ts +2 -2
- package/lib/partialLengths.d.ts.map +1 -1
- package/lib/partialLengths.js +160 -111
- package/lib/partialLengths.js.map +1 -1
- package/lib/perspective.d.ts +8 -27
- package/lib/perspective.d.ts.map +1 -1
- package/lib/perspective.js +8 -68
- package/lib/perspective.js.map +1 -1
- package/lib/revertibles.d.ts.map +1 -1
- package/lib/revertibles.js +2 -2
- package/lib/revertibles.js.map +1 -1
- package/lib/segmentInfos.d.ts +20 -106
- package/lib/segmentInfos.d.ts.map +1 -1
- package/lib/segmentInfos.js +26 -37
- package/lib/segmentInfos.js.map +1 -1
- package/lib/segmentPropertiesManager.d.ts +1 -14
- package/lib/segmentPropertiesManager.d.ts.map +1 -1
- package/lib/segmentPropertiesManager.js +2 -16
- package/lib/segmentPropertiesManager.js.map +1 -1
- package/lib/snapshotLoader.d.ts.map +1 -1
- package/lib/snapshotLoader.js +39 -19
- package/lib/snapshotLoader.js.map +1 -1
- package/lib/snapshotV1.d.ts.map +1 -1
- package/lib/snapshotV1.js +34 -26
- package/lib/snapshotV1.js.map +1 -1
- package/lib/snapshotlegacy.d.ts.map +1 -1
- package/lib/snapshotlegacy.js +7 -10
- package/lib/snapshotlegacy.js.map +1 -1
- package/lib/stamps.d.ts +1 -1
- package/lib/stamps.js +1 -1
- package/lib/stamps.js.map +1 -1
- package/lib/test/Insertion.perf.spec.js +6 -51
- package/lib/test/Insertion.perf.spec.js.map +1 -1
- package/lib/test/PartialLengths.perf.spec.js +18 -25
- package/lib/test/PartialLengths.perf.spec.js.map +1 -1
- package/lib/test/Removal.perf.spec.js +13 -41
- package/lib/test/Removal.perf.spec.js.map +1 -1
- package/lib/test/beastTest.spec.d.ts.map +1 -1
- package/lib/test/beastTest.spec.js +42 -67
- package/lib/test/beastTest.spec.js.map +1 -1
- package/lib/test/client.annotateMarker.spec.js +1 -11
- package/lib/test/client.annotateMarker.spec.js.map +1 -1
- package/lib/test/client.applyMsg.spec.js +14 -14
- package/lib/test/client.applyMsg.spec.js.map +1 -1
- package/lib/test/client.getPosition.spec.js +1 -1
- package/lib/test/client.getPosition.spec.js.map +1 -1
- package/lib/test/client.localReference.spec.js +1 -1
- package/lib/test/client.localReference.spec.js.map +1 -1
- package/lib/test/client.rollback.spec.js +50 -59
- package/lib/test/client.rollback.spec.js.map +1 -1
- package/lib/test/client.rollbackFarm.spec.js +1 -1
- package/lib/test/client.rollbackFarm.spec.js.map +1 -1
- package/lib/test/client.searchForMarker.spec.js +4 -21
- package/lib/test/client.searchForMarker.spec.js.map +1 -1
- package/lib/test/index.d.ts +2 -2
- package/lib/test/index.d.ts.map +1 -1
- package/lib/test/index.js +1 -1
- package/lib/test/index.js.map +1 -1
- package/lib/test/mergeTree.annotate.deltaCallback.spec.js +15 -60
- package/lib/test/mergeTree.annotate.deltaCallback.spec.js.map +1 -1
- package/lib/test/mergeTree.annotate.spec.js +48 -64
- package/lib/test/mergeTree.annotate.spec.js.map +1 -1
- package/lib/test/mergeTree.insert.deltaCallback.spec.js +10 -63
- package/lib/test/mergeTree.insert.deltaCallback.spec.js.map +1 -1
- package/lib/test/mergeTree.insertingWalk.spec.js +61 -127
- package/lib/test/mergeTree.insertingWalk.spec.js.map +1 -1
- package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.js +13 -94
- package/lib/test/mergeTree.markRangeRemoved.deltaCallback.spec.js.map +1 -1
- package/lib/test/mergeTree.markRangeRemoved.spec.js +10 -7
- package/lib/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
- package/lib/test/mergeTree.walk.spec.js +2 -14
- package/lib/test/mergeTree.walk.spec.js.map +1 -1
- package/lib/test/mergeTreeOperationRunner.js +3 -3
- package/lib/test/mergeTreeOperationRunner.js.map +1 -1
- package/lib/test/obliterate.concurrent.spec.js +18 -23
- package/lib/test/obliterate.concurrent.spec.js.map +1 -1
- package/lib/test/obliterate.partialLength.spec.js +167 -137
- package/lib/test/obliterate.partialLength.spec.js.map +1 -1
- package/lib/test/obliterate.spec.js +17 -127
- package/lib/test/obliterate.spec.js.map +1 -1
- package/lib/test/partialLength.spec.js +29 -197
- package/lib/test/partialLength.spec.js.map +1 -1
- package/lib/test/perspective.spec.js +34 -0
- package/lib/test/perspective.spec.js.map +1 -1
- package/lib/test/propertyManager.spec.js +2 -2
- package/lib/test/propertyManager.spec.js.map +1 -1
- package/lib/test/resetPendingSegmentsToOp.spec.js +0 -2
- package/lib/test/resetPendingSegmentsToOp.spec.js.map +1 -1
- package/lib/test/segmentGroupCollection.spec.js +10 -4
- package/lib/test/segmentGroupCollection.spec.js.map +1 -1
- package/lib/test/testClient.d.ts +1 -0
- package/lib/test/testClient.d.ts.map +1 -1
- package/lib/test/testClient.js +18 -28
- package/lib/test/testClient.js.map +1 -1
- package/lib/test/testClientLogger.d.ts.map +1 -1
- package/lib/test/testClientLogger.js +3 -10
- package/lib/test/testClientLogger.js.map +1 -1
- package/lib/test/testServer.d.ts +2 -1
- package/lib/test/testServer.d.ts.map +1 -1
- package/lib/test/testServer.js +7 -5
- package/lib/test/testServer.js.map +1 -1
- package/lib/test/testUtils.d.ts +36 -56
- package/lib/test/testUtils.d.ts.map +1 -1
- package/lib/test/testUtils.js +66 -48
- package/lib/test/testUtils.js.map +1 -1
- package/lib/test/text.d.ts +2 -2
- package/lib/test/text.d.ts.map +1 -1
- package/lib/test/text.js +6 -3
- package/lib/test/text.js.map +1 -1
- package/lib/textSegment.d.ts +0 -6
- package/lib/textSegment.d.ts.map +1 -1
- package/lib/textSegment.js.map +1 -1
- package/lib/tsdoc-metadata.json +1 -1
- package/lib/zamboni.d.ts.map +1 -1
- package/lib/zamboni.js +32 -28
- package/lib/zamboni.js.map +1 -1
- package/package.json +17 -20
- package/src/MergeTreeTextHelper.ts +17 -12
- package/src/client.ts +141 -197
- package/src/endOfTreeSegment.ts +11 -8
- package/src/index.ts +4 -3
- package/src/mergeTree.ts +482 -633
- package/src/mergeTreeDeltaCallback.ts +4 -8
- package/src/mergeTreeNodes.ts +66 -45
- package/src/partialLengths.ts +181 -137
- package/src/perspective.ts +17 -95
- package/src/revertibles.ts +2 -7
- package/src/segmentInfos.ts +48 -141
- package/src/segmentPropertiesManager.ts +2 -16
- package/src/snapshotLoader.ts +62 -30
- package/src/snapshotV1.ts +36 -28
- package/src/snapshotlegacy.ts +7 -16
- package/src/stamps.ts +1 -1
- package/src/textSegment.ts +0 -13
- package/src/zamboni.ts +38 -32
- package/tsconfig.json +1 -0
- package/prettier.config.cjs +0 -8
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { IIntegerRange } from "./client.js";
|
|
7
|
-
import { MergeTree } from "./mergeTree.js";
|
|
8
|
-
import { ISegmentPrivate } from "./mergeTreeNodes.js";
|
|
9
|
-
import {
|
|
6
|
+
import type { IIntegerRange } from "./client.js";
|
|
7
|
+
import type { MergeTree } from "./mergeTree.js";
|
|
8
|
+
import type { ISegmentPrivate } from "./mergeTreeNodes.js";
|
|
9
|
+
import type { Perspective } from "./perspective.js";
|
|
10
|
+
import { TextSegment } from "./textSegment.js";
|
|
10
11
|
|
|
11
12
|
interface ITextAccumulator {
|
|
12
13
|
textSegment: TextSegment;
|
|
@@ -14,24 +15,29 @@ interface ITextAccumulator {
|
|
|
14
15
|
parallelArrays?: boolean;
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
/**
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export interface IMergeTreeTextHelper {
|
|
22
|
+
getText(perspective: Perspective, placeholder: string, start?: number, end?: number): string;
|
|
23
|
+
}
|
|
24
|
+
|
|
17
25
|
export class MergeTreeTextHelper implements IMergeTreeTextHelper {
|
|
18
26
|
constructor(private readonly mergeTree: MergeTree) {}
|
|
19
27
|
|
|
20
28
|
public getText(
|
|
21
|
-
|
|
22
|
-
clientId: number,
|
|
29
|
+
perspective: Perspective,
|
|
23
30
|
placeholder = "",
|
|
24
31
|
start?: number,
|
|
25
32
|
end?: number,
|
|
26
33
|
): string {
|
|
27
|
-
const range = this.getValidRange(start, end,
|
|
34
|
+
const range = this.getValidRange(start, end, perspective);
|
|
28
35
|
|
|
29
36
|
const accum: ITextAccumulator = { textSegment: new TextSegment(""), placeholder };
|
|
30
37
|
|
|
31
38
|
this.mergeTree.mapRange<ITextAccumulator>(
|
|
32
39
|
gatherText,
|
|
33
|
-
|
|
34
|
-
clientId,
|
|
40
|
+
perspective,
|
|
35
41
|
accum,
|
|
36
42
|
range.start,
|
|
37
43
|
range.end,
|
|
@@ -42,11 +48,10 @@ export class MergeTreeTextHelper implements IMergeTreeTextHelper {
|
|
|
42
48
|
private getValidRange(
|
|
43
49
|
start: number | undefined,
|
|
44
50
|
end: number | undefined,
|
|
45
|
-
|
|
46
|
-
clientId: number,
|
|
51
|
+
perspective: Perspective,
|
|
47
52
|
): IIntegerRange {
|
|
48
53
|
const range: IIntegerRange = {
|
|
49
|
-
end: end ?? this.mergeTree.getLength(
|
|
54
|
+
end: end ?? this.mergeTree.getLength(perspective),
|
|
50
55
|
start: start ?? 0,
|
|
51
56
|
};
|
|
52
57
|
return range;
|
package/src/client.ts
CHANGED
|
@@ -25,21 +25,17 @@ import {
|
|
|
25
25
|
UsageError,
|
|
26
26
|
} from "@fluidframework/telemetry-utils/internal";
|
|
27
27
|
|
|
28
|
-
import { MergeTreeTextHelper } from "./MergeTreeTextHelper.js";
|
|
28
|
+
import { MergeTreeTextHelper, type IMergeTreeTextHelper } from "./MergeTreeTextHelper.js";
|
|
29
29
|
import { DoublyLinkedList, RedBlackTree } from "./collections/index.js";
|
|
30
|
-
import {
|
|
31
|
-
NonCollabClient,
|
|
32
|
-
UnassignedSequenceNumber,
|
|
33
|
-
UniversalSequenceNumber,
|
|
34
|
-
} from "./constants.js";
|
|
30
|
+
import { NonCollabClient, UniversalSequenceNumber } from "./constants.js";
|
|
35
31
|
import { LocalReferencePosition, SlidingPreference } from "./localReference.js";
|
|
36
32
|
import {
|
|
37
33
|
MergeTree,
|
|
38
34
|
errorIfOptionNotTrue,
|
|
35
|
+
isRemovedAndAcked,
|
|
39
36
|
type IMergeTreeOptionsInternal,
|
|
40
37
|
} from "./mergeTree.js";
|
|
41
38
|
import type {
|
|
42
|
-
IMergeTreeClientSequenceArgs,
|
|
43
39
|
IMergeTreeDeltaCallbackArgs,
|
|
44
40
|
IMergeTreeDeltaOpArgs,
|
|
45
41
|
IMergeTreeMaintenanceCallbackArgs,
|
|
@@ -59,7 +55,6 @@ import {
|
|
|
59
55
|
createAdjustRangeOp,
|
|
60
56
|
createAnnotateMarkerOp,
|
|
61
57
|
createAnnotateRangeOp,
|
|
62
|
-
// eslint-disable-next-line import/no-deprecated
|
|
63
58
|
createGroupOp,
|
|
64
59
|
createInsertSegmentOp,
|
|
65
60
|
createObliterateRangeOp,
|
|
@@ -84,21 +79,26 @@ import {
|
|
|
84
79
|
type IMergeTreeAnnotateAdjustMsg,
|
|
85
80
|
type IMergeTreeObliterateSidedMsg,
|
|
86
81
|
} from "./ops.js";
|
|
82
|
+
import {
|
|
83
|
+
LocalReconnectingPerspective,
|
|
84
|
+
PriorPerspective,
|
|
85
|
+
type Perspective,
|
|
86
|
+
} from "./perspective.js";
|
|
87
87
|
import { PropertySet, type MapLike } from "./properties.js";
|
|
88
88
|
import { DetachedReferencePosition, ReferencePosition } from "./referencePositions.js";
|
|
89
89
|
import {
|
|
90
90
|
isInserted,
|
|
91
|
-
isMoved,
|
|
92
91
|
isRemoved,
|
|
93
92
|
overwriteInfo,
|
|
94
|
-
|
|
95
|
-
type
|
|
93
|
+
toRemovalInfo,
|
|
94
|
+
type IHasInsertionInfo,
|
|
96
95
|
} from "./segmentInfos.js";
|
|
97
96
|
import { Side, type InteriorSequencePlace } from "./sequencePlace.js";
|
|
98
97
|
import { SnapshotLoader } from "./snapshotLoader.js";
|
|
99
98
|
import { SnapshotV1 } from "./snapshotV1.js";
|
|
100
99
|
import { SnapshotLegacy } from "./snapshotlegacy.js";
|
|
101
|
-
import {
|
|
100
|
+
import type { OperationStamp } from "./stamps.js";
|
|
101
|
+
import * as opstampUtils from "./stamps.js";
|
|
102
102
|
|
|
103
103
|
type IMergeTreeDeltaRemoteOpArgs = Omit<IMergeTreeDeltaOpArgs, "sequencedMessage"> &
|
|
104
104
|
Required<Pick<IMergeTreeDeltaOpArgs, "sequencedMessage">>;
|
|
@@ -371,8 +371,7 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
371
371
|
): void {
|
|
372
372
|
this._mergeTree.mapRange(
|
|
373
373
|
handler,
|
|
374
|
-
this.
|
|
375
|
-
this.getClientId(),
|
|
374
|
+
this._mergeTree.localPerspective,
|
|
376
375
|
accum,
|
|
377
376
|
start,
|
|
378
377
|
end,
|
|
@@ -401,12 +400,17 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
401
400
|
): void {
|
|
402
401
|
let localInserts = 0;
|
|
403
402
|
let localRemoves = 0;
|
|
403
|
+
let localObliterates = 0;
|
|
404
404
|
walkAllChildSegments(this._mergeTree.root, (seg: ISegmentPrivate) => {
|
|
405
|
-
if (isInserted(seg) && seg.
|
|
405
|
+
if (isInserted(seg) && opstampUtils.isLocal(seg.insert)) {
|
|
406
406
|
localInserts++;
|
|
407
407
|
}
|
|
408
|
-
if (isRemoved(seg) && seg.
|
|
409
|
-
|
|
408
|
+
if (isRemoved(seg) && opstampUtils.isLocal(seg.removes[seg.removes.length - 1])) {
|
|
409
|
+
if (seg.removes[seg.removes.length - 1].type === "setRemove") {
|
|
410
|
+
localRemoves++;
|
|
411
|
+
} else {
|
|
412
|
+
localObliterates++;
|
|
413
|
+
}
|
|
410
414
|
}
|
|
411
415
|
// Only serialize segments that have not been removed.
|
|
412
416
|
if (!isRemoved(seg)) {
|
|
@@ -420,6 +424,7 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
420
424
|
eventName: "LocalEditsInProcessGCData",
|
|
421
425
|
localInserts,
|
|
422
426
|
localRemoves,
|
|
427
|
+
localObliterates,
|
|
423
428
|
});
|
|
424
429
|
}
|
|
425
430
|
}
|
|
@@ -437,12 +442,12 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
437
442
|
if (!isSegmentLeaf(segment)) {
|
|
438
443
|
return -1;
|
|
439
444
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
);
|
|
445
|
+
|
|
446
|
+
const perspective =
|
|
447
|
+
localSeq === undefined
|
|
448
|
+
? this._mergeTree.localPerspective
|
|
449
|
+
: new LocalReconnectingPerspective(this.getCurrentSeq(), this.getClientId(), localSeq);
|
|
450
|
+
return this._mergeTree.getPosition(segment, perspective);
|
|
446
451
|
}
|
|
447
452
|
|
|
448
453
|
/**
|
|
@@ -504,7 +509,7 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
504
509
|
* @param relativePos - Id of marker (may be indirect) and whether position is before or after marker.
|
|
505
510
|
*/
|
|
506
511
|
public posFromRelativePos(relativePos: IRelativePosition): number {
|
|
507
|
-
return this._mergeTree.posFromRelativePos(relativePos);
|
|
512
|
+
return this._mergeTree.posFromRelativePos(relativePos, this._mergeTree.localPerspective);
|
|
508
513
|
}
|
|
509
514
|
|
|
510
515
|
public getMarkerFromId(id: string): ISegment | undefined {
|
|
@@ -514,66 +519,78 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
514
519
|
/**
|
|
515
520
|
* Revert an op
|
|
516
521
|
*/
|
|
517
|
-
public rollback
|
|
522
|
+
public rollback(op: unknown, localOpMetadata: unknown): void {
|
|
518
523
|
this._mergeTree.rollback(op as IMergeTreeDeltaOp, localOpMetadata as SegmentGroup);
|
|
519
524
|
}
|
|
520
525
|
|
|
521
526
|
private applyObliterateRangeOp(opArgs: IMergeTreeDeltaOpArgs): void {
|
|
527
|
+
const { op, sequencedMessage } = opArgs;
|
|
522
528
|
assert(
|
|
523
|
-
|
|
524
|
-
|
|
529
|
+
op.type === MergeTreeDeltaType.OBLITERATE ||
|
|
530
|
+
op.type === MergeTreeDeltaType.OBLITERATE_SIDED,
|
|
525
531
|
0x866 /* Unexpected op type on range obliterate! */,
|
|
526
532
|
);
|
|
527
|
-
const
|
|
528
|
-
const
|
|
533
|
+
const perspective = this.getOperationPerspective(sequencedMessage);
|
|
534
|
+
const stamp = this.getOperationStamp(sequencedMessage);
|
|
535
|
+
|
|
529
536
|
if (this._mergeTree.options?.mergeTreeEnableSidedObliterate) {
|
|
530
|
-
const { start, end } = this.getValidSidedRange(op,
|
|
531
|
-
this._mergeTree.obliterateRange(
|
|
532
|
-
start,
|
|
533
|
-
end,
|
|
534
|
-
clientArgs.referenceSequenceNumber,
|
|
535
|
-
clientArgs.clientId,
|
|
536
|
-
clientArgs.sequenceNumber,
|
|
537
|
-
opArgs,
|
|
538
|
-
);
|
|
537
|
+
const { start, end } = this.getValidSidedRange(op, perspective);
|
|
538
|
+
this._mergeTree.obliterateRange(start, end, perspective, stamp, opArgs);
|
|
539
539
|
} else {
|
|
540
540
|
assert(
|
|
541
541
|
op.type === MergeTreeDeltaType.OBLITERATE,
|
|
542
542
|
0xa43 /* Unexpected sided obliterate while mergeTreeEnableSidedObliterate is disabled */,
|
|
543
543
|
);
|
|
544
|
-
const
|
|
545
|
-
this._mergeTree.obliterateRange(
|
|
546
|
-
range.start,
|
|
547
|
-
range.end,
|
|
548
|
-
clientArgs.referenceSequenceNumber,
|
|
549
|
-
clientArgs.clientId,
|
|
550
|
-
clientArgs.sequenceNumber,
|
|
551
|
-
opArgs,
|
|
552
|
-
);
|
|
544
|
+
const { start, end } = this.getValidOpRange(op, perspective);
|
|
545
|
+
this._mergeTree.obliterateRange(start, end, perspective, stamp, opArgs);
|
|
553
546
|
}
|
|
554
547
|
}
|
|
555
548
|
|
|
549
|
+
private getOperationPerspective(
|
|
550
|
+
sequencedMessage: ISequencedDocumentMessage | undefined,
|
|
551
|
+
): Perspective {
|
|
552
|
+
if (!sequencedMessage) {
|
|
553
|
+
return this._mergeTree.localPerspective;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
const clientId = this.getOrAddShortClientIdFromMessage(sequencedMessage);
|
|
557
|
+
const { referenceSequenceNumber: refSeq } = sequencedMessage;
|
|
558
|
+
return new PriorPerspective(refSeq, clientId);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Returns the operation stamp to apply for a change, minting a new one local one if necessary.
|
|
563
|
+
*/
|
|
564
|
+
private getOperationStamp(
|
|
565
|
+
sequencedMessage: ISequencedDocumentMessage | undefined,
|
|
566
|
+
): OperationStamp {
|
|
567
|
+
if (!sequencedMessage) {
|
|
568
|
+
return this.getCollabWindow().mintNextLocalOperationStamp();
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
const { sequenceNumber: seq } = sequencedMessage;
|
|
572
|
+
const clientId = this.getOrAddShortClientIdFromMessage(sequencedMessage);
|
|
573
|
+
return {
|
|
574
|
+
seq,
|
|
575
|
+
clientId,
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
|
|
556
579
|
/**
|
|
557
580
|
* Performs the remove based on the provided op
|
|
558
581
|
* @param opArgs - The ops args for the op
|
|
559
582
|
*/
|
|
560
583
|
private applyRemoveRangeOp(opArgs: IMergeTreeDeltaOpArgs): void {
|
|
584
|
+
const { op, sequencedMessage } = opArgs;
|
|
561
585
|
assert(
|
|
562
|
-
|
|
586
|
+
op.type === MergeTreeDeltaType.REMOVE,
|
|
563
587
|
0x02d /* "Unexpected op type on range remove!" */,
|
|
564
588
|
);
|
|
565
|
-
const
|
|
566
|
-
const
|
|
567
|
-
const range = this.getValidOpRange(op,
|
|
568
|
-
|
|
569
|
-
this._mergeTree.markRangeRemoved(
|
|
570
|
-
range.start,
|
|
571
|
-
range.end,
|
|
572
|
-
clientArgs.referenceSequenceNumber,
|
|
573
|
-
clientArgs.clientId,
|
|
574
|
-
clientArgs.sequenceNumber,
|
|
575
|
-
opArgs,
|
|
576
|
-
);
|
|
589
|
+
const perspective = this.getOperationPerspective(sequencedMessage);
|
|
590
|
+
const stamp = this.getOperationStamp(sequencedMessage);
|
|
591
|
+
const range = this.getValidOpRange(op, perspective);
|
|
592
|
+
|
|
593
|
+
this._mergeTree.markRangeRemoved(range.start, range.end, perspective, stamp, opArgs);
|
|
577
594
|
}
|
|
578
595
|
|
|
579
596
|
/**
|
|
@@ -581,23 +598,16 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
581
598
|
* @param opArgs - The ops args for the op
|
|
582
599
|
*/
|
|
583
600
|
private applyAnnotateRangeOp(opArgs: IMergeTreeDeltaOpArgs): void {
|
|
601
|
+
const { op, sequencedMessage } = opArgs;
|
|
584
602
|
assert(
|
|
585
|
-
|
|
603
|
+
op.type === MergeTreeDeltaType.ANNOTATE,
|
|
586
604
|
0x02e /* "Unexpected op type on range annotate!" */,
|
|
587
605
|
);
|
|
588
|
-
const
|
|
589
|
-
const
|
|
590
|
-
const range = this.getValidOpRange(op,
|
|
591
|
-
|
|
592
|
-
this._mergeTree.annotateRange(
|
|
593
|
-
range.start,
|
|
594
|
-
range.end,
|
|
595
|
-
op,
|
|
596
|
-
clientArgs.referenceSequenceNumber,
|
|
597
|
-
clientArgs.clientId,
|
|
598
|
-
clientArgs.sequenceNumber,
|
|
599
|
-
opArgs,
|
|
600
|
-
);
|
|
606
|
+
const perspective = this.getOperationPerspective(sequencedMessage);
|
|
607
|
+
const stamp = this.getOperationStamp(sequencedMessage);
|
|
608
|
+
const range = this.getValidOpRange(op, perspective);
|
|
609
|
+
|
|
610
|
+
this._mergeTree.annotateRange(range.start, range.end, op, perspective, stamp, opArgs);
|
|
601
611
|
}
|
|
602
612
|
|
|
603
613
|
/**
|
|
@@ -606,25 +616,19 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
606
616
|
* @returns True if the insert was applied. False if it could not be.
|
|
607
617
|
*/
|
|
608
618
|
private applyInsertOp(opArgs: IMergeTreeDeltaOpArgs): void {
|
|
619
|
+
const { op, sequencedMessage } = opArgs;
|
|
609
620
|
assert(
|
|
610
|
-
|
|
621
|
+
op.type === MergeTreeDeltaType.INSERT,
|
|
611
622
|
0x02f /* "Unexpected op type on range insert!" */,
|
|
612
623
|
);
|
|
613
|
-
const
|
|
614
|
-
const
|
|
615
|
-
const range = this.getValidOpRange(op,
|
|
624
|
+
const perspective = this.getOperationPerspective(sequencedMessage);
|
|
625
|
+
const stamp = this.getOperationStamp(sequencedMessage);
|
|
626
|
+
const range = this.getValidOpRange(op, perspective);
|
|
616
627
|
|
|
617
628
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
618
629
|
const segments = [this.specToSegment(op.seg)];
|
|
619
630
|
|
|
620
|
-
this._mergeTree.insertSegments(
|
|
621
|
-
range.start,
|
|
622
|
-
segments,
|
|
623
|
-
clientArgs.referenceSequenceNumber,
|
|
624
|
-
clientArgs.clientId,
|
|
625
|
-
clientArgs.sequenceNumber,
|
|
626
|
-
opArgs,
|
|
627
|
-
);
|
|
631
|
+
this._mergeTree.insertSegments(range.start, segments, perspective, stamp, opArgs);
|
|
628
632
|
}
|
|
629
633
|
|
|
630
634
|
/**
|
|
@@ -636,7 +640,7 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
636
640
|
private getValidSidedRange(
|
|
637
641
|
// eslint-disable-next-line import/no-deprecated
|
|
638
642
|
op: IMergeTreeObliterateSidedMsg | IMergeTreeObliterateMsg,
|
|
639
|
-
|
|
643
|
+
perspective: Perspective,
|
|
640
644
|
): {
|
|
641
645
|
start: InteriorSequencePlace;
|
|
642
646
|
end: InteriorSequencePlace;
|
|
@@ -662,11 +666,8 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
662
666
|
}
|
|
663
667
|
|
|
664
668
|
// Validate if local op
|
|
665
|
-
if (
|
|
666
|
-
const length = this._mergeTree.getLength(
|
|
667
|
-
this.getCollabWindow().currentSeq,
|
|
668
|
-
this.getClientId(),
|
|
669
|
-
);
|
|
669
|
+
if (perspective.clientId === this.getClientId()) {
|
|
670
|
+
const length = this._mergeTree.getLength(this._mergeTree.localPerspective);
|
|
670
671
|
if (start !== undefined && (start.pos >= length || start.pos < 0)) {
|
|
671
672
|
// start out of bounds
|
|
672
673
|
invalidPositions.push("start");
|
|
@@ -719,28 +720,20 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
719
720
|
| IMergeTreeRemoveMsg
|
|
720
721
|
// eslint-disable-next-line import/no-deprecated
|
|
721
722
|
| IMergeTreeObliterateMsg,
|
|
722
|
-
|
|
723
|
+
perspective: Perspective,
|
|
723
724
|
): IIntegerRange {
|
|
724
725
|
let start: number | undefined = op.pos1;
|
|
725
726
|
if (start === undefined && op.relativePos1) {
|
|
726
|
-
start = this._mergeTree.posFromRelativePos(
|
|
727
|
-
op.relativePos1,
|
|
728
|
-
clientArgs.referenceSequenceNumber,
|
|
729
|
-
clientArgs.clientId,
|
|
730
|
-
);
|
|
727
|
+
start = this._mergeTree.posFromRelativePos(op.relativePos1, perspective);
|
|
731
728
|
}
|
|
732
729
|
|
|
733
730
|
let end: number | undefined = op.pos2;
|
|
734
731
|
if (end === undefined && op.relativePos2) {
|
|
735
|
-
end = this._mergeTree.posFromRelativePos(
|
|
736
|
-
op.relativePos2,
|
|
737
|
-
clientArgs.referenceSequenceNumber,
|
|
738
|
-
clientArgs.clientId,
|
|
739
|
-
);
|
|
732
|
+
end = this._mergeTree.posFromRelativePos(op.relativePos2, perspective);
|
|
740
733
|
}
|
|
741
734
|
|
|
742
735
|
// Validate if local op
|
|
743
|
-
if (
|
|
736
|
+
if (perspective.clientId === this.getClientId()) {
|
|
744
737
|
const length = this.getLength();
|
|
745
738
|
|
|
746
739
|
const invalidPositions: string[] = [];
|
|
@@ -787,45 +780,6 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
787
780
|
return { start: start!, end: end! };
|
|
788
781
|
}
|
|
789
782
|
|
|
790
|
-
/**
|
|
791
|
-
* Gets the client args from the op if remote, otherwise uses the local clients info
|
|
792
|
-
* @param sequencedMessage - The sequencedMessage to get the client sequence args for
|
|
793
|
-
*/
|
|
794
|
-
private getClientSequenceArgsForMessage(
|
|
795
|
-
sequencedMessage:
|
|
796
|
-
| ISequencedDocumentMessage
|
|
797
|
-
| Pick<ISequencedDocumentMessage, "referenceSequenceNumber" | "clientId">
|
|
798
|
-
| undefined,
|
|
799
|
-
): IMergeTreeClientSequenceArgs {
|
|
800
|
-
// If there this no sequenced message, then the op is local
|
|
801
|
-
// and unacked, so use this clients sequenced args
|
|
802
|
-
//
|
|
803
|
-
if (sequencedMessage) {
|
|
804
|
-
return {
|
|
805
|
-
clientId: this.getOrAddShortClientIdFromMessage(sequencedMessage),
|
|
806
|
-
referenceSequenceNumber: sequencedMessage.referenceSequenceNumber,
|
|
807
|
-
// Note: return value satisfies overload signatures despite the cast, as if input argument doesn't contain sequenceNumber,
|
|
808
|
-
// return value isn't expected to have it either.
|
|
809
|
-
sequenceNumber: (sequencedMessage as ISequencedDocumentMessage).sequenceNumber,
|
|
810
|
-
};
|
|
811
|
-
} else {
|
|
812
|
-
const segWindow = this.getCollabWindow();
|
|
813
|
-
return {
|
|
814
|
-
clientId: segWindow.clientId,
|
|
815
|
-
referenceSequenceNumber: segWindow.currentSeq,
|
|
816
|
-
sequenceNumber: this.getLocalSequenceNumber(),
|
|
817
|
-
};
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
/**
|
|
822
|
-
* Gets the client args from the op if remote, otherwise uses the local clients info
|
|
823
|
-
* @param opArgs - The op arg to get the client sequence args for
|
|
824
|
-
*/
|
|
825
|
-
private getClientSequenceArgs(opArgs: IMergeTreeDeltaOpArgs): IMergeTreeClientSequenceArgs {
|
|
826
|
-
return this.getClientSequenceArgsForMessage(opArgs.sequencedMessage);
|
|
827
|
-
}
|
|
828
|
-
|
|
829
783
|
private ackPendingSegment(opArgs: IMergeTreeDeltaRemoteOpArgs): void {
|
|
830
784
|
if (opArgs.op.type === MergeTreeDeltaType.GROUP) {
|
|
831
785
|
for (const memberOp of opArgs.op.ops) {
|
|
@@ -884,7 +838,8 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
884
838
|
if (!isSegmentLeaf(segment)) {
|
|
885
839
|
throw new UsageError(UNBOUND_SEGMENT_ERROR);
|
|
886
840
|
}
|
|
887
|
-
|
|
841
|
+
const perspective = new LocalReconnectingPerspective(currentSeq, clientId, localSeq);
|
|
842
|
+
return this._mergeTree.getPosition(segment, perspective);
|
|
888
843
|
}
|
|
889
844
|
|
|
890
845
|
private resetPendingDeltaToOps(
|
|
@@ -942,14 +897,7 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
942
897
|
// if the segment has been removed or obliterated, there's no need to send the annotate op
|
|
943
898
|
// unless the remove was local, in which case the annotate must have come
|
|
944
899
|
// before the remove
|
|
945
|
-
if (
|
|
946
|
-
(!isRemoved(segment) ||
|
|
947
|
-
(segment.localRemovedSeq !== undefined &&
|
|
948
|
-
segment.removedSeq === UnassignedSequenceNumber)) &&
|
|
949
|
-
(!isMoved(segment) ||
|
|
950
|
-
(segment.localMovedSeq !== undefined &&
|
|
951
|
-
segment.movedSeq === UnassignedSequenceNumber))
|
|
952
|
-
) {
|
|
900
|
+
if (!isRemovedAndAcked(segment)) {
|
|
953
901
|
newOp =
|
|
954
902
|
resetOp.props === undefined
|
|
955
903
|
? createAdjustRangeOp(
|
|
@@ -968,28 +916,33 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
968
916
|
|
|
969
917
|
case MergeTreeDeltaType.INSERT: {
|
|
970
918
|
assert(
|
|
971
|
-
isInserted(segment) && segment.
|
|
919
|
+
isInserted(segment) && opstampUtils.isLocal(segment.insert),
|
|
972
920
|
0x037 /* "Segment already has assigned sequence number" */,
|
|
973
921
|
);
|
|
974
|
-
const
|
|
922
|
+
const removeInfo = toRemovalInfo(segment);
|
|
975
923
|
|
|
976
|
-
if (
|
|
924
|
+
if (removeInfo !== undefined && opstampUtils.isAcked(removeInfo.removes[0])) {
|
|
925
|
+
assert(
|
|
926
|
+
removeInfo.removes[0].type === "sliceRemove",
|
|
927
|
+
0xb5c /* Remove on insertion must be caused by obliterate. */,
|
|
928
|
+
);
|
|
977
929
|
errorIfOptionNotTrue(
|
|
978
930
|
this._mergeTree.options,
|
|
979
931
|
"mergeTreeEnableObliterateReconnect",
|
|
980
932
|
);
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
933
|
+
// the segment was remotely obliterated, so is considered removed
|
|
934
|
+
// we set the seq to the universal seq and remove the local seq,
|
|
935
|
+
// so its length is not considered for subsequent local changes
|
|
936
|
+
// this allows us to not send the op as even the local client will ignore the segment
|
|
937
|
+
overwriteInfo<IHasInsertionInfo>(segment, {
|
|
938
|
+
insert: {
|
|
939
|
+
type: "insert",
|
|
987
940
|
seq: UniversalSequenceNumber,
|
|
988
941
|
localSeq: undefined,
|
|
989
942
|
clientId: NonCollabClient,
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
|
|
943
|
+
},
|
|
944
|
+
});
|
|
945
|
+
break;
|
|
993
946
|
}
|
|
994
947
|
|
|
995
948
|
const segInsertOp: ISegment = segment.clone();
|
|
@@ -1003,14 +956,9 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
1003
956
|
}
|
|
1004
957
|
|
|
1005
958
|
case MergeTreeDeltaType.REMOVE: {
|
|
1006
|
-
if
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
segment.removedSeq === UnassignedSequenceNumber &&
|
|
1010
|
-
(!isMoved(segment) ||
|
|
1011
|
-
(segment.localMovedSeq !== undefined &&
|
|
1012
|
-
segment.movedSeq === UnassignedSequenceNumber))
|
|
1013
|
-
) {
|
|
959
|
+
// Only bother resubmitting if nobody else has removed it in the meantime.
|
|
960
|
+
// When that happens, the first removal will have been acked.
|
|
961
|
+
if (isRemoved(segment) && opstampUtils.isLocal(segment.removes[0])) {
|
|
1014
962
|
newOp = createRemoveRangeOp(
|
|
1015
963
|
segmentPosition,
|
|
1016
964
|
segmentPosition + segment.cachedLength,
|
|
@@ -1020,14 +968,9 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
1020
968
|
}
|
|
1021
969
|
case MergeTreeDeltaType.OBLITERATE: {
|
|
1022
970
|
errorIfOptionNotTrue(this._mergeTree.options, "mergeTreeEnableObliterateReconnect");
|
|
1023
|
-
if
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
segment.movedSeq === UnassignedSequenceNumber &&
|
|
1027
|
-
(!isRemoved(segment) ||
|
|
1028
|
-
(segment.localRemovedSeq !== undefined &&
|
|
1029
|
-
segment.removedSeq === UnassignedSequenceNumber))
|
|
1030
|
-
) {
|
|
971
|
+
// Only bother resubmitting if nobody else has removed it in the meantime.
|
|
972
|
+
// When that happens, the first removal will have been acked.
|
|
973
|
+
if (isRemoved(segment) && opstampUtils.isLocal(segment.removes[0])) {
|
|
1031
974
|
newOp = createObliterateRangeOp(
|
|
1032
975
|
segmentPosition,
|
|
1033
976
|
segmentPosition + segment.cachedLength,
|
|
@@ -1219,7 +1162,7 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
1219
1162
|
if (Array.isArray(segmentGroup)) {
|
|
1220
1163
|
if (segmentGroup.length === 0) {
|
|
1221
1164
|
// sometimes we rebase to an empty op
|
|
1222
|
-
|
|
1165
|
+
|
|
1223
1166
|
return createGroupOp();
|
|
1224
1167
|
}
|
|
1225
1168
|
firstGroup = segmentGroup[0];
|
|
@@ -1274,7 +1217,7 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
1274
1217
|
);
|
|
1275
1218
|
opList.push(...this.resetPendingDeltaToOps(resetOp, segmentGroup));
|
|
1276
1219
|
}
|
|
1277
|
-
|
|
1220
|
+
|
|
1278
1221
|
return opList.length === 1 ? opList[0] : createGroupOp(...opList);
|
|
1279
1222
|
}
|
|
1280
1223
|
|
|
@@ -1333,11 +1276,6 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
1333
1276
|
return loader.initialize(storage);
|
|
1334
1277
|
}
|
|
1335
1278
|
|
|
1336
|
-
private getLocalSequenceNumber(): number {
|
|
1337
|
-
const segWindow = this.getCollabWindow();
|
|
1338
|
-
return segWindow.collaborating ? UnassignedSequenceNumber : UniversalSequenceNumber;
|
|
1339
|
-
}
|
|
1340
|
-
|
|
1341
1279
|
// eslint-disable-next-line import/no-deprecated
|
|
1342
1280
|
localTransaction(groupOp: IMergeTreeGroupMsg): void {
|
|
1343
1281
|
for (const op of groupOp.ops) {
|
|
@@ -1382,14 +1320,21 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
1382
1320
|
segment: T | undefined;
|
|
1383
1321
|
offset: number | undefined;
|
|
1384
1322
|
} {
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1323
|
+
let perspective: Perspective;
|
|
1324
|
+
const clientId =
|
|
1325
|
+
sequenceArgs === undefined
|
|
1326
|
+
? this.getClientId()
|
|
1327
|
+
: this.getOrAddShortClientIdFromMessage(sequenceArgs);
|
|
1328
|
+
const refSeq = sequenceArgs?.referenceSequenceNumber ?? this.getCollabWindow().currentSeq;
|
|
1329
|
+
if (localSeq !== undefined) {
|
|
1330
|
+
perspective = new LocalReconnectingPerspective(refSeq, clientId, localSeq);
|
|
1331
|
+
} else if (sequenceArgs === undefined) {
|
|
1332
|
+
perspective = this._mergeTree.localPerspective;
|
|
1333
|
+
} else {
|
|
1334
|
+
perspective = new PriorPerspective(refSeq, clientId);
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
return this._mergeTree.getContainingSegment(pos, perspective) as {
|
|
1393
1338
|
segment: T | undefined;
|
|
1394
1339
|
offset: number | undefined;
|
|
1395
1340
|
};
|
|
@@ -1472,7 +1417,6 @@ export class Client extends TypedEventEmitter<IClientEvents> {
|
|
|
1472
1417
|
* @param forwards - Whether the desired marker comes before (false) or after (true) `startPos`
|
|
1473
1418
|
*/
|
|
1474
1419
|
searchForMarker(startPos: number, markerLabel: string, forwards = true): Marker | undefined {
|
|
1475
|
-
|
|
1476
|
-
return this._mergeTree.searchForMarker(startPos, clientId, markerLabel, forwards);
|
|
1420
|
+
return this._mergeTree.searchForMarker(startPos, markerLabel, forwards);
|
|
1477
1421
|
}
|
|
1478
1422
|
}
|