@fluidframework/sequence 2.0.0-dev.5.3.2.178189 → 2.0.0-dev.6.4.0.191457
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 +114 -0
- package/README.md +4 -3
- package/dist/defaultMap.d.ts +1 -1
- package/dist/defaultMap.d.ts.map +1 -1
- package/dist/defaultMap.js +9 -10
- package/dist/defaultMap.js.map +1 -1
- package/dist/defaultMapInterfaces.d.ts +1 -1
- package/dist/defaultMapInterfaces.d.ts.map +1 -1
- package/dist/defaultMapInterfaces.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -9
- package/dist/index.js.map +1 -1
- package/dist/intervalCollection.d.ts +11 -424
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalCollection.js +74 -815
- package/dist/intervalCollection.js.map +1 -1
- package/dist/intervalIndex/endpointInRangeIndex.d.ts +20 -0
- package/dist/intervalIndex/endpointInRangeIndex.d.ts.map +1 -0
- package/dist/intervalIndex/endpointInRangeIndex.js +60 -0
- package/dist/intervalIndex/endpointInRangeIndex.js.map +1 -0
- package/dist/intervalIndex/endpointIndex.d.ts +21 -0
- package/dist/intervalIndex/endpointIndex.d.ts.map +1 -0
- package/dist/intervalIndex/endpointIndex.js +42 -0
- package/dist/intervalIndex/endpointIndex.js.map +1 -0
- package/dist/intervalIndex/idIntervalIndex.d.ts +12 -0
- package/dist/intervalIndex/idIntervalIndex.d.ts.map +1 -0
- package/dist/intervalIndex/idIntervalIndex.js +41 -0
- package/dist/intervalIndex/idIntervalIndex.js.map +1 -0
- package/dist/intervalIndex/index.d.ts +5 -0
- package/dist/intervalIndex/index.d.ts.map +1 -1
- package/dist/intervalIndex/index.js +9 -1
- package/dist/intervalIndex/index.js.map +1 -1
- package/dist/intervalIndex/intervalIndex.d.ts +29 -0
- package/dist/intervalIndex/intervalIndex.d.ts.map +1 -0
- package/dist/intervalIndex/intervalIndex.js +7 -0
- package/dist/intervalIndex/intervalIndex.js.map +1 -0
- package/dist/intervalIndex/intervalIndexUtils.d.ts +17 -0
- package/dist/intervalIndex/intervalIndexUtils.d.ts.map +1 -0
- package/dist/intervalIndex/intervalIndexUtils.js +22 -0
- package/dist/intervalIndex/intervalIndexUtils.js.map +1 -0
- package/dist/intervalIndex/overlappingIntervalsIndex.d.ts +2 -1
- package/dist/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -1
- package/dist/intervalIndex/overlappingIntervalsIndex.js +3 -3
- package/dist/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js +5 -5
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js.map +1 -1
- package/dist/intervalIndex/sequenceIntervalIndexes.d.ts +1 -1
- package/dist/intervalIndex/sequenceIntervalIndexes.d.ts.map +1 -1
- package/dist/intervalIndex/sequenceIntervalIndexes.js.map +1 -1
- package/dist/intervalIndex/startpointInRangeIndex.d.ts +20 -0
- package/dist/intervalIndex/startpointInRangeIndex.d.ts.map +1 -0
- package/dist/intervalIndex/startpointInRangeIndex.js +62 -0
- package/dist/intervalIndex/startpointInRangeIndex.js.map +1 -0
- package/dist/intervalTree.d.ts +2 -56
- package/dist/intervalTree.d.ts.map +1 -1
- package/dist/intervalTree.js +2 -11
- package/dist/intervalTree.js.map +1 -1
- package/dist/intervals/index.d.ts +8 -0
- package/dist/intervals/index.d.ts.map +1 -0
- package/dist/intervals/index.js +23 -0
- package/dist/intervals/index.js.map +1 -0
- package/dist/intervals/interval.d.ts +88 -0
- package/dist/intervals/interval.d.ts.map +1 -0
- package/dist/intervals/interval.js +180 -0
- package/dist/intervals/interval.js.map +1 -0
- package/dist/intervals/intervalUtils.d.ts +200 -0
- package/dist/intervals/intervalUtils.d.ts.map +1 -0
- package/dist/intervals/intervalUtils.js +79 -0
- package/dist/intervals/intervalUtils.js.map +1 -0
- package/dist/intervals/sequenceInterval.d.ts +132 -0
- package/dist/intervals/sequenceInterval.d.ts.map +1 -0
- package/dist/intervals/sequenceInterval.js +313 -0
- package/dist/intervals/sequenceInterval.js.map +1 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/revertibles.d.ts +1 -1
- package/dist/revertibles.d.ts.map +1 -1
- package/dist/revertibles.js +45 -52
- package/dist/revertibles.js.map +1 -1
- package/dist/sequence.d.ts +33 -4
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +91 -47
- package/dist/sequence.js.map +1 -1
- package/dist/sequenceDeltaEvent.d.ts +8 -3
- package/dist/sequenceDeltaEvent.d.ts.map +1 -1
- package/dist/sequenceDeltaEvent.js +3 -4
- package/dist/sequenceDeltaEvent.js.map +1 -1
- package/dist/sharedIntervalCollection.d.ts +2 -1
- package/dist/sharedIntervalCollection.d.ts.map +1 -1
- package/dist/sharedIntervalCollection.js +2 -2
- package/dist/sharedIntervalCollection.js.map +1 -1
- package/dist/sharedSequence.d.ts +9 -0
- package/dist/sharedSequence.d.ts.map +1 -1
- package/dist/sharedSequence.js +9 -6
- package/dist/sharedSequence.js.map +1 -1
- package/dist/sharedString.d.ts.map +1 -1
- package/dist/sharedString.js +9 -29
- package/dist/sharedString.js.map +1 -1
- package/lib/defaultMap.d.ts +1 -1
- package/lib/defaultMap.d.ts.map +1 -1
- package/lib/defaultMap.js +5 -6
- package/lib/defaultMap.js.map +1 -1
- package/lib/defaultMapInterfaces.d.ts +1 -1
- package/lib/defaultMapInterfaces.d.ts.map +1 -1
- package/lib/defaultMapInterfaces.js.map +1 -1
- package/lib/index.d.ts +3 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -2
- package/lib/index.js.map +1 -1
- package/lib/intervalCollection.d.ts +11 -424
- package/lib/intervalCollection.d.ts.map +1 -1
- package/lib/intervalCollection.js +43 -776
- package/lib/intervalCollection.js.map +1 -1
- package/lib/intervalIndex/endpointInRangeIndex.d.ts +20 -0
- package/lib/intervalIndex/endpointInRangeIndex.d.ts.map +1 -0
- package/lib/intervalIndex/endpointInRangeIndex.js +56 -0
- package/lib/intervalIndex/endpointInRangeIndex.js.map +1 -0
- package/lib/intervalIndex/endpointIndex.d.ts +21 -0
- package/lib/intervalIndex/endpointIndex.d.ts.map +1 -0
- package/lib/intervalIndex/endpointIndex.js +38 -0
- package/lib/intervalIndex/endpointIndex.js.map +1 -0
- package/lib/intervalIndex/idIntervalIndex.d.ts +12 -0
- package/lib/intervalIndex/idIntervalIndex.d.ts.map +1 -0
- package/lib/intervalIndex/idIntervalIndex.js +37 -0
- package/lib/intervalIndex/idIntervalIndex.js.map +1 -0
- package/lib/intervalIndex/index.d.ts +5 -0
- package/lib/intervalIndex/index.d.ts.map +1 -1
- package/lib/intervalIndex/index.js +4 -0
- package/lib/intervalIndex/index.js.map +1 -1
- package/lib/intervalIndex/intervalIndex.d.ts +29 -0
- package/lib/intervalIndex/intervalIndex.d.ts.map +1 -0
- package/lib/intervalIndex/intervalIndex.js +6 -0
- package/lib/intervalIndex/intervalIndex.js.map +1 -0
- package/lib/intervalIndex/intervalIndexUtils.d.ts +17 -0
- package/lib/intervalIndex/intervalIndexUtils.d.ts.map +1 -0
- package/lib/intervalIndex/intervalIndexUtils.js +18 -0
- package/lib/intervalIndex/intervalIndexUtils.js.map +1 -0
- package/lib/intervalIndex/overlappingIntervalsIndex.d.ts +2 -1
- package/lib/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -1
- package/lib/intervalIndex/overlappingIntervalsIndex.js +1 -1
- package/lib/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js +1 -1
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js.map +1 -1
- package/lib/intervalIndex/sequenceIntervalIndexes.d.ts +1 -1
- package/lib/intervalIndex/sequenceIntervalIndexes.d.ts.map +1 -1
- package/lib/intervalIndex/sequenceIntervalIndexes.js.map +1 -1
- package/lib/intervalIndex/startpointInRangeIndex.d.ts +20 -0
- package/lib/intervalIndex/startpointInRangeIndex.d.ts.map +1 -0
- package/lib/intervalIndex/startpointInRangeIndex.js +58 -0
- package/lib/intervalIndex/startpointInRangeIndex.js.map +1 -0
- package/lib/intervalTree.d.ts +2 -56
- package/lib/intervalTree.d.ts.map +1 -1
- package/lib/intervalTree.js +2 -11
- package/lib/intervalTree.js.map +1 -1
- package/lib/intervals/index.d.ts +8 -0
- package/lib/intervals/index.d.ts.map +1 -0
- package/lib/intervals/index.js +8 -0
- package/lib/intervals/index.js.map +1 -0
- package/lib/intervals/interval.d.ts +88 -0
- package/lib/intervals/interval.d.ts.map +1 -0
- package/lib/intervals/interval.js +175 -0
- package/lib/intervals/interval.js.map +1 -0
- package/lib/intervals/intervalUtils.d.ts +200 -0
- package/lib/intervals/intervalUtils.d.ts.map +1 -0
- package/lib/intervals/intervalUtils.js +74 -0
- package/lib/intervals/intervalUtils.js.map +1 -0
- package/lib/intervals/sequenceInterval.d.ts +132 -0
- package/lib/intervals/sequenceInterval.d.ts.map +1 -0
- package/lib/intervals/sequenceInterval.js +305 -0
- package/lib/intervals/sequenceInterval.js.map +1 -0
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/revertibles.d.ts +1 -1
- package/lib/revertibles.d.ts.map +1 -1
- package/lib/revertibles.js +28 -35
- package/lib/revertibles.js.map +1 -1
- package/lib/sequence.d.ts +33 -4
- package/lib/sequence.d.ts.map +1 -1
- package/lib/sequence.js +86 -41
- package/lib/sequence.js.map +1 -1
- package/lib/sequenceDeltaEvent.d.ts +8 -3
- package/lib/sequenceDeltaEvent.d.ts.map +1 -1
- package/lib/sequenceDeltaEvent.js +2 -3
- package/lib/sequenceDeltaEvent.js.map +1 -1
- package/lib/sharedIntervalCollection.d.ts +2 -1
- package/lib/sharedIntervalCollection.d.ts.map +1 -1
- package/lib/sharedIntervalCollection.js +1 -1
- package/lib/sharedIntervalCollection.js.map +1 -1
- package/lib/sharedSequence.d.ts +9 -0
- package/lib/sharedSequence.d.ts.map +1 -1
- package/lib/sharedSequence.js +8 -5
- package/lib/sharedSequence.js.map +1 -1
- package/lib/sharedString.d.ts.map +1 -1
- package/lib/sharedString.js +9 -29
- package/lib/sharedString.js.map +1 -1
- package/package.json +29 -32
- package/src/defaultMap.ts +2 -1
- package/src/defaultMapInterfaces.ts +1 -1
- package/src/index.ts +18 -12
- package/src/intervalCollection.ts +42 -1225
- package/src/intervalIndex/endpointInRangeIndex.ts +104 -0
- package/src/intervalIndex/endpointIndex.ts +78 -0
- package/src/intervalIndex/idIntervalIndex.ts +58 -0
- package/src/intervalIndex/index.ts +5 -0
- package/src/intervalIndex/intervalIndex.ts +31 -0
- package/src/intervalIndex/intervalIndexUtils.ts +27 -0
- package/src/intervalIndex/overlappingIntervalsIndex.ts +2 -6
- package/src/intervalIndex/overlappingSequenceIntervalsIndex.ts +1 -1
- package/src/intervalIndex/sequenceIntervalIndexes.ts +1 -1
- package/src/intervalIndex/startpointInRangeIndex.ts +109 -0
- package/src/intervalTree.ts +3 -75
- package/src/intervals/index.ts +25 -0
- package/src/intervals/interval.ts +230 -0
- package/src/intervals/intervalUtils.ts +256 -0
- package/src/intervals/sequenceInterval.ts +494 -0
- package/src/packageVersion.ts +1 -1
- package/src/revertibles.ts +24 -13
- package/src/sequence.ts +100 -35
- package/src/sequenceDeltaEvent.ts +12 -4
- package/src/sharedIntervalCollection.ts +2 -3
- package/src/sharedSequence.ts +11 -5
- package/src/sharedString.ts +8 -25
|
@@ -2,53 +2,15 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
6
|
-
var t = {};
|
|
7
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
8
|
-
t[p] = s[p];
|
|
9
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
10
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
11
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
12
|
-
t[p[i]] = s[p[i]];
|
|
13
|
-
}
|
|
14
|
-
return t;
|
|
15
|
-
};
|
|
16
5
|
/* eslint-disable no-bitwise */
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import { addProperties,
|
|
20
|
-
import { LoggingError } from "@fluidframework/telemetry-utils";
|
|
6
|
+
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
7
|
+
import { assert } from "@fluidframework/core-utils";
|
|
8
|
+
import { addProperties, createMap, getSlideToSegoff, MergeTreeDeltaType, ReferenceType, refTypeIncludesFlag, reservedRangeLabelsKey, UnassignedSequenceNumber, DetachedReferencePosition, } from "@fluidframework/merge-tree";
|
|
9
|
+
import { LoggingError, UsageError } from "@fluidframework/telemetry-utils";
|
|
21
10
|
import { v4 as uuid } from "uuid";
|
|
22
|
-
import {
|
|
11
|
+
import { IntervalOpType, IntervalStickiness, IntervalType, SequenceInterval, createPositionReferenceFromSegoff, endReferenceSlidingPreference, startReferenceSlidingPreference, sequenceIntervalHelpers, createInterval, } from "./intervals";
|
|
12
|
+
import { createEndpointIndex, createIdIntervalIndex, createOverlappingIntervalsIndex, } from "./intervalIndex";
|
|
23
13
|
const reservedIntervalIdKey = "intervalId";
|
|
24
|
-
/**
|
|
25
|
-
* Values are used in persisted formats (ops) and revertibles.
|
|
26
|
-
* @alpha
|
|
27
|
-
*/
|
|
28
|
-
export const IntervalOpType = {
|
|
29
|
-
ADD: "add",
|
|
30
|
-
DELETE: "delete",
|
|
31
|
-
CHANGE: "change",
|
|
32
|
-
PROPERTY_CHANGED: "propertyChanged",
|
|
33
|
-
POSITION_REMOVE: "positionRemove",
|
|
34
|
-
};
|
|
35
|
-
export var IntervalType;
|
|
36
|
-
(function (IntervalType) {
|
|
37
|
-
IntervalType[IntervalType["Simple"] = 0] = "Simple";
|
|
38
|
-
IntervalType[IntervalType["Nest"] = 1] = "Nest";
|
|
39
|
-
/**
|
|
40
|
-
* SlideOnRemove indicates that the ends of the interval will slide if the segment
|
|
41
|
-
* they reference is removed and acked.
|
|
42
|
-
* See `packages\dds\merge-tree\docs\REFERENCEPOSITIONS.md` for details
|
|
43
|
-
* SlideOnRemove is the default interval behavior and does not need to be specified.
|
|
44
|
-
*/
|
|
45
|
-
IntervalType[IntervalType["SlideOnRemove"] = 2] = "SlideOnRemove";
|
|
46
|
-
/**
|
|
47
|
-
* A temporary interval, used internally
|
|
48
|
-
* @internal
|
|
49
|
-
*/
|
|
50
|
-
IntervalType[IntervalType["Transient"] = 4] = "Transient";
|
|
51
|
-
})(IntervalType || (IntervalType = {}));
|
|
52
14
|
/**
|
|
53
15
|
* Decompress an interval after loading a summary from JSON. The exact format
|
|
54
16
|
* of this compression is unspecified and subject to change
|
|
@@ -59,7 +21,7 @@ function decompressInterval(interval, label) {
|
|
|
59
21
|
end: interval[1],
|
|
60
22
|
sequenceNumber: interval[2],
|
|
61
23
|
intervalType: interval[3],
|
|
62
|
-
properties:
|
|
24
|
+
properties: { ...interval[4], [reservedRangeLabelsKey]: [label] },
|
|
63
25
|
stickiness: interval[5],
|
|
64
26
|
};
|
|
65
27
|
}
|
|
@@ -74,672 +36,23 @@ function compressInterval(interval) {
|
|
|
74
36
|
end,
|
|
75
37
|
sequenceNumber,
|
|
76
38
|
intervalType,
|
|
77
|
-
|
|
39
|
+
// remove the `referenceRangeLabels` property as it is already stored
|
|
40
|
+
// in the `label` field of the summary
|
|
41
|
+
{ ...properties, [reservedRangeLabelsKey]: undefined },
|
|
78
42
|
];
|
|
79
43
|
if (interval.stickiness !== undefined && interval.stickiness !== IntervalStickiness.END) {
|
|
80
44
|
base.push(interval.stickiness);
|
|
81
45
|
}
|
|
82
46
|
return base;
|
|
83
47
|
}
|
|
84
|
-
function startReferenceSlidingPreference(stickiness) {
|
|
85
|
-
// if any start stickiness, prefer sliding backwards
|
|
86
|
-
return (stickiness & IntervalStickiness.START) !== 0
|
|
87
|
-
? SlidingPreference.BACKWARD
|
|
88
|
-
: SlidingPreference.FORWARD;
|
|
89
|
-
}
|
|
90
|
-
function endReferenceSlidingPreference(stickiness) {
|
|
91
|
-
// if any end stickiness, prefer sliding forwards
|
|
92
|
-
return (stickiness & IntervalStickiness.END) !== 0
|
|
93
|
-
? SlidingPreference.FORWARD
|
|
94
|
-
: SlidingPreference.BACKWARD;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Determines how an interval should expand when segments are inserted adjacent
|
|
98
|
-
* to the range it spans
|
|
99
|
-
*
|
|
100
|
-
* Note that interval stickiness is currently an experimental feature and must
|
|
101
|
-
* be explicitly enabled with the `intervalStickinessEnabled` flag
|
|
102
|
-
*/
|
|
103
|
-
export const IntervalStickiness = {
|
|
104
|
-
/**
|
|
105
|
-
* Interval does not expand to include adjacent segments
|
|
106
|
-
*/
|
|
107
|
-
NONE: 0b00,
|
|
108
|
-
/**
|
|
109
|
-
* Interval expands to include segments inserted adjacent to the start
|
|
110
|
-
*/
|
|
111
|
-
START: 0b01,
|
|
112
|
-
/**
|
|
113
|
-
* Interval expands to include segments inserted adjacent to the end
|
|
114
|
-
*
|
|
115
|
-
* This is the default stickiness
|
|
116
|
-
*/
|
|
117
|
-
END: 0b10,
|
|
118
|
-
/**
|
|
119
|
-
* Interval expands to include all segments inserted adjacent to it
|
|
120
|
-
*/
|
|
121
|
-
FULL: 0b11,
|
|
122
|
-
};
|
|
123
|
-
/**
|
|
124
|
-
* Serializable interval whose endpoints are plain-old numbers.
|
|
125
|
-
*/
|
|
126
|
-
export class Interval {
|
|
127
|
-
constructor(start, end, props) {
|
|
128
|
-
this.start = start;
|
|
129
|
-
this.end = end;
|
|
130
|
-
this.propertyManager = new PropertiesManager();
|
|
131
|
-
this.properties = {};
|
|
132
|
-
if (props) {
|
|
133
|
-
this.addProperties(props);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* {@inheritDoc ISerializableInterval.getIntervalId}
|
|
138
|
-
*/
|
|
139
|
-
getIntervalId() {
|
|
140
|
-
var _a;
|
|
141
|
-
const id = (_a = this.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
|
|
142
|
-
assert(id !== undefined, 0x5e1 /* interval ID should not be undefined */);
|
|
143
|
-
return `${id}`;
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* @returns an array containing any auxiliary property sets added with `addPropertySet`.
|
|
147
|
-
*/
|
|
148
|
-
getAdditionalPropertySets() {
|
|
149
|
-
var _a;
|
|
150
|
-
return (_a = this.auxProps) !== null && _a !== void 0 ? _a : [];
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Adds an auxiliary set of properties to this interval.
|
|
154
|
-
* These properties can be recovered using `getAdditionalPropertySets`
|
|
155
|
-
* @param props - set of properties to add
|
|
156
|
-
* @remarks - This gets called as part of the default conflict resolver for `IIntervalCollection<Interval>`
|
|
157
|
-
* (i.e. non-sequence-based interval collections). However, the additional properties don't get serialized.
|
|
158
|
-
* This functionality seems half-baked.
|
|
159
|
-
*/
|
|
160
|
-
addPropertySet(props) {
|
|
161
|
-
if (this.auxProps === undefined) {
|
|
162
|
-
this.auxProps = [];
|
|
163
|
-
}
|
|
164
|
-
this.auxProps.push(props);
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* {@inheritDoc ISerializableInterval.serialize}
|
|
168
|
-
* @internal
|
|
169
|
-
*/
|
|
170
|
-
serialize() {
|
|
171
|
-
const serializedInterval = {
|
|
172
|
-
end: this.end,
|
|
173
|
-
intervalType: 0,
|
|
174
|
-
sequenceNumber: 0,
|
|
175
|
-
start: this.start,
|
|
176
|
-
};
|
|
177
|
-
if (this.properties) {
|
|
178
|
-
serializedInterval.properties = this.properties;
|
|
179
|
-
}
|
|
180
|
-
return serializedInterval;
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* {@inheritDoc IInterval.clone}
|
|
184
|
-
*/
|
|
185
|
-
clone() {
|
|
186
|
-
return new Interval(this.start, this.end, this.properties);
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* {@inheritDoc IInterval.compare}
|
|
190
|
-
*/
|
|
191
|
-
compare(b) {
|
|
192
|
-
const startResult = this.compareStart(b);
|
|
193
|
-
if (startResult === 0) {
|
|
194
|
-
const endResult = this.compareEnd(b);
|
|
195
|
-
if (endResult === 0) {
|
|
196
|
-
const thisId = this.getIntervalId();
|
|
197
|
-
if (thisId) {
|
|
198
|
-
const bId = b.getIntervalId();
|
|
199
|
-
if (bId) {
|
|
200
|
-
return thisId > bId ? 1 : thisId < bId ? -1 : 0;
|
|
201
|
-
}
|
|
202
|
-
return 0;
|
|
203
|
-
}
|
|
204
|
-
return 0;
|
|
205
|
-
}
|
|
206
|
-
else {
|
|
207
|
-
return endResult;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
else {
|
|
211
|
-
return startResult;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* {@inheritDoc IInterval.compareStart}
|
|
216
|
-
*/
|
|
217
|
-
compareStart(b) {
|
|
218
|
-
return this.start - b.start;
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* {@inheritDoc IInterval.compareEnd}
|
|
222
|
-
*/
|
|
223
|
-
compareEnd(b) {
|
|
224
|
-
return this.end - b.end;
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* {@inheritDoc IInterval.overlaps}
|
|
228
|
-
*/
|
|
229
|
-
overlaps(b) {
|
|
230
|
-
const result = this.start <= b.end && this.end >= b.start;
|
|
231
|
-
return result;
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* {@inheritDoc IInterval.union}
|
|
235
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
236
|
-
*/
|
|
237
|
-
union(b) {
|
|
238
|
-
return new Interval(Math.min(this.start, b.start), Math.max(this.end, b.end), this.properties);
|
|
239
|
-
}
|
|
240
|
-
getProperties() {
|
|
241
|
-
return this.properties;
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* {@inheritDoc ISerializableInterval.addProperties}
|
|
245
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
246
|
-
*/
|
|
247
|
-
addProperties(newProps, collaborating = false, seq, op) {
|
|
248
|
-
if (newProps) {
|
|
249
|
-
this.initializeProperties();
|
|
250
|
-
return this.propertyManager.addProperties(this.properties, newProps, op, seq, collaborating);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* {@inheritDoc IInterval.modify}
|
|
255
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
256
|
-
*/
|
|
257
|
-
modify(label, start, end, op) {
|
|
258
|
-
const startPos = start !== null && start !== void 0 ? start : this.start;
|
|
259
|
-
const endPos = end !== null && end !== void 0 ? end : this.end;
|
|
260
|
-
if (this.start === startPos && this.end === endPos) {
|
|
261
|
-
// Return undefined to indicate that no change is necessary.
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
264
|
-
const newInterval = new Interval(startPos, endPos);
|
|
265
|
-
if (this.properties) {
|
|
266
|
-
newInterval.initializeProperties();
|
|
267
|
-
this.propertyManager.copyTo(this.properties, newInterval.properties, newInterval.propertyManager);
|
|
268
|
-
}
|
|
269
|
-
return newInterval;
|
|
270
|
-
}
|
|
271
|
-
initializeProperties() {
|
|
272
|
-
if (!this.propertyManager) {
|
|
273
|
-
this.propertyManager = new PropertiesManager();
|
|
274
|
-
}
|
|
275
|
-
if (!this.properties) {
|
|
276
|
-
this.properties = createMap();
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Interval implementation whose ends are associated with positions in a mutatable sequence.
|
|
282
|
-
* As such, when content is inserted into the middle of the interval, the interval expands to
|
|
283
|
-
* include that content.
|
|
284
|
-
*
|
|
285
|
-
* @remarks - The endpoint's position should be treated exclusively to get reasonable behavior--i.e.
|
|
286
|
-
* an interval referring to "hello" in "hello world" should have a start position of 0 and an end
|
|
287
|
-
* position of 5.
|
|
288
|
-
*
|
|
289
|
-
* To see why, consider what happens if "llo wor" is removed from the string to make "held".
|
|
290
|
-
* The interval's startpoint remains on the "h" (it isn't altered), but the interval's endpoint
|
|
291
|
-
* slides forward to the next unremoved position, which is the "l" in "held".
|
|
292
|
-
* Users would generally expect the interval to now refer to "he" (as it is the subset of content
|
|
293
|
-
* remaining after the removal), hence the "l" should be excluded.
|
|
294
|
-
* If the interval endpoint was treated inclusively, the interval would now refer to "hel", which
|
|
295
|
-
* is undesirable.
|
|
296
|
-
*
|
|
297
|
-
* Since the end of an interval is treated exclusively but cannot be greater than or equal to the
|
|
298
|
-
* length of the associated sequence, application models which leverage interval collections should
|
|
299
|
-
* consider inserting a marker at the end of the sequence to represent the end of the content.
|
|
300
|
-
*/
|
|
301
|
-
export class SequenceInterval {
|
|
302
|
-
constructor(client,
|
|
303
|
-
/**
|
|
304
|
-
* Start endpoint of this interval.
|
|
305
|
-
* @remarks - This endpoint can be resolved into a character position using the SharedString it's a part of.
|
|
306
|
-
*/
|
|
307
|
-
start,
|
|
308
|
-
/**
|
|
309
|
-
* End endpoint of this interval.
|
|
310
|
-
* @remarks - This endpoint can be resolved into a character position using the SharedString it's a part of.
|
|
311
|
-
*/
|
|
312
|
-
end, intervalType, props, stickiness = IntervalStickiness.END) {
|
|
313
|
-
this.client = client;
|
|
314
|
-
this.start = start;
|
|
315
|
-
this.end = end;
|
|
316
|
-
this.intervalType = intervalType;
|
|
317
|
-
this.stickiness = stickiness;
|
|
318
|
-
this.propertyManager = new PropertiesManager();
|
|
319
|
-
this.properties = {};
|
|
320
|
-
if (props) {
|
|
321
|
-
this.addProperties(props);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* Subscribes to position change events on this interval if there are no current listeners.
|
|
326
|
-
* @internal
|
|
327
|
-
*/
|
|
328
|
-
addPositionChangeListeners(beforePositionChange, afterPositionChange) {
|
|
329
|
-
var _a, _b;
|
|
330
|
-
var _c, _d;
|
|
331
|
-
if (this.callbacks === undefined) {
|
|
332
|
-
this.callbacks = {
|
|
333
|
-
beforePositionChange,
|
|
334
|
-
afterPositionChange,
|
|
335
|
-
};
|
|
336
|
-
const startCbs = ((_a = (_c = this.start).callbacks) !== null && _a !== void 0 ? _a : (_c.callbacks = {}));
|
|
337
|
-
const endCbs = ((_b = (_d = this.end).callbacks) !== null && _b !== void 0 ? _b : (_d.callbacks = {}));
|
|
338
|
-
startCbs.beforeSlide = endCbs.beforeSlide = beforePositionChange;
|
|
339
|
-
startCbs.afterSlide = endCbs.afterSlide = afterPositionChange;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* Removes the currently subscribed position change listeners.
|
|
344
|
-
* @internal
|
|
345
|
-
*/
|
|
346
|
-
removePositionChangeListeners() {
|
|
347
|
-
if (this.callbacks) {
|
|
348
|
-
this.callbacks = undefined;
|
|
349
|
-
this.start.callbacks = undefined;
|
|
350
|
-
this.end.callbacks = undefined;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* {@inheritDoc ISerializableInterval.serialize}
|
|
355
|
-
* @internal
|
|
356
|
-
*/
|
|
357
|
-
serialize() {
|
|
358
|
-
const startPosition = this.client.localReferencePositionToPosition(this.start);
|
|
359
|
-
const endPosition = this.client.localReferencePositionToPosition(this.end);
|
|
360
|
-
const serializedInterval = {
|
|
361
|
-
end: endPosition,
|
|
362
|
-
intervalType: this.intervalType,
|
|
363
|
-
sequenceNumber: this.client.getCurrentSeq(),
|
|
364
|
-
start: startPosition,
|
|
365
|
-
};
|
|
366
|
-
if (this.properties) {
|
|
367
|
-
serializedInterval.properties = this.properties;
|
|
368
|
-
}
|
|
369
|
-
if (this.stickiness !== IntervalStickiness.END) {
|
|
370
|
-
serializedInterval.stickiness = this.stickiness;
|
|
371
|
-
}
|
|
372
|
-
return serializedInterval;
|
|
373
|
-
}
|
|
374
|
-
/**
|
|
375
|
-
* {@inheritDoc IInterval.clone}
|
|
376
|
-
*/
|
|
377
|
-
clone() {
|
|
378
|
-
return new SequenceInterval(this.client, this.start, this.end, this.intervalType, this.properties, this.stickiness);
|
|
379
|
-
}
|
|
380
|
-
/**
|
|
381
|
-
* {@inheritDoc IInterval.compare}
|
|
382
|
-
*/
|
|
383
|
-
compare(b) {
|
|
384
|
-
const startResult = this.compareStart(b);
|
|
385
|
-
if (startResult === 0) {
|
|
386
|
-
const endResult = this.compareEnd(b);
|
|
387
|
-
if (endResult === 0) {
|
|
388
|
-
const thisId = this.getIntervalId();
|
|
389
|
-
if (thisId) {
|
|
390
|
-
const bId = b.getIntervalId();
|
|
391
|
-
if (bId) {
|
|
392
|
-
return thisId > bId ? 1 : thisId < bId ? -1 : 0;
|
|
393
|
-
}
|
|
394
|
-
return 0;
|
|
395
|
-
}
|
|
396
|
-
return 0;
|
|
397
|
-
}
|
|
398
|
-
else {
|
|
399
|
-
return endResult;
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
else {
|
|
403
|
-
return startResult;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
/**
|
|
407
|
-
* {@inheritDoc IInterval.compareStart}
|
|
408
|
-
*/
|
|
409
|
-
compareStart(b) {
|
|
410
|
-
return compareReferencePositions(this.start, b.start);
|
|
411
|
-
}
|
|
412
|
-
/**
|
|
413
|
-
* {@inheritDoc IInterval.compareEnd}
|
|
414
|
-
*/
|
|
415
|
-
compareEnd(b) {
|
|
416
|
-
return compareReferencePositions(this.end, b.end);
|
|
417
|
-
}
|
|
418
|
-
/**
|
|
419
|
-
* {@inheritDoc IInterval.overlaps}
|
|
420
|
-
*/
|
|
421
|
-
overlaps(b) {
|
|
422
|
-
const result = compareReferencePositions(this.start, b.end) <= 0 &&
|
|
423
|
-
compareReferencePositions(this.end, b.start) >= 0;
|
|
424
|
-
return result;
|
|
425
|
-
}
|
|
426
|
-
/**
|
|
427
|
-
* {@inheritDoc ISerializableInterval.getIntervalId}
|
|
428
|
-
*/
|
|
429
|
-
getIntervalId() {
|
|
430
|
-
var _a;
|
|
431
|
-
const id = (_a = this.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
|
|
432
|
-
assert(id !== undefined, 0x5e2 /* interval ID should not be undefined */);
|
|
433
|
-
return `${id}`;
|
|
434
|
-
}
|
|
435
|
-
/**
|
|
436
|
-
* {@inheritDoc IInterval.union}
|
|
437
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
438
|
-
*/
|
|
439
|
-
union(b) {
|
|
440
|
-
return new SequenceInterval(this.client, minReferencePosition(this.start, b.start), maxReferencePosition(this.end, b.end), this.intervalType);
|
|
441
|
-
}
|
|
442
|
-
/**
|
|
443
|
-
* {@inheritDoc ISerializableInterval.addProperties}
|
|
444
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
445
|
-
*/
|
|
446
|
-
addProperties(newProps, collab = false, seq, op) {
|
|
447
|
-
this.initializeProperties();
|
|
448
|
-
return this.propertyManager.addProperties(this.properties, newProps, op, seq, collab);
|
|
449
|
-
}
|
|
450
|
-
/**
|
|
451
|
-
* @returns whether this interval overlaps two numerical positions.
|
|
452
|
-
*/
|
|
453
|
-
overlapsPos(bstart, bend) {
|
|
454
|
-
const startPos = this.client.localReferencePositionToPosition(this.start);
|
|
455
|
-
const endPos = this.client.localReferencePositionToPosition(this.end);
|
|
456
|
-
return endPos > bstart && startPos < bend;
|
|
457
|
-
}
|
|
458
|
-
/**
|
|
459
|
-
* {@inheritDoc IInterval.modify}
|
|
460
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
461
|
-
*/
|
|
462
|
-
modify(label, start, end, op, localSeq, stickiness = IntervalStickiness.END) {
|
|
463
|
-
const getRefType = (baseType) => {
|
|
464
|
-
let refType = baseType;
|
|
465
|
-
if (op === undefined) {
|
|
466
|
-
refType &= ~ReferenceType.SlideOnRemove;
|
|
467
|
-
refType |= ReferenceType.StayOnRemove;
|
|
468
|
-
}
|
|
469
|
-
return refType;
|
|
470
|
-
};
|
|
471
|
-
let startRef = this.start;
|
|
472
|
-
if (start !== undefined) {
|
|
473
|
-
startRef = createPositionReference(this.client, start, getRefType(this.start.refType), op, undefined, localSeq, startReferenceSlidingPreference(stickiness));
|
|
474
|
-
if (this.start.properties) {
|
|
475
|
-
startRef.addProperties(this.start.properties);
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
let endRef = this.end;
|
|
479
|
-
if (end !== undefined) {
|
|
480
|
-
endRef = createPositionReference(this.client, end, getRefType(this.end.refType), op, undefined, localSeq, endReferenceSlidingPreference(stickiness));
|
|
481
|
-
if (this.end.properties) {
|
|
482
|
-
endRef.addProperties(this.end.properties);
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
const newInterval = new SequenceInterval(this.client, startRef, endRef, this.intervalType);
|
|
486
|
-
if (this.properties) {
|
|
487
|
-
newInterval.initializeProperties();
|
|
488
|
-
this.propertyManager.copyTo(this.properties, newInterval.properties, newInterval.propertyManager);
|
|
489
|
-
}
|
|
490
|
-
return newInterval;
|
|
491
|
-
}
|
|
492
|
-
initializeProperties() {
|
|
493
|
-
if (!this.propertyManager) {
|
|
494
|
-
this.propertyManager = new PropertiesManager();
|
|
495
|
-
}
|
|
496
|
-
if (!this.properties) {
|
|
497
|
-
this.properties = createMap();
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
export function createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot, slidingPreference) {
|
|
502
|
-
if (segoff.segment) {
|
|
503
|
-
const ref = client.createLocalReferencePosition(segoff.segment, segoff.offset, refType, undefined, slidingPreference);
|
|
504
|
-
return ref;
|
|
505
|
-
}
|
|
506
|
-
// Creating references on detached segments is allowed for:
|
|
507
|
-
// - Transient segments
|
|
508
|
-
// - References coming from a remote client (location may have been concurrently removed)
|
|
509
|
-
// - References being rebased to a new sequence number
|
|
510
|
-
// (segment they originally referred to may have been removed with no suitable replacement)
|
|
511
|
-
if (!op &&
|
|
512
|
-
!localSeq &&
|
|
513
|
-
!fromSnapshot &&
|
|
514
|
-
!refTypeIncludesFlag(refType, ReferenceType.Transient)) {
|
|
515
|
-
throw new UsageError("Non-transient references need segment");
|
|
516
|
-
}
|
|
517
|
-
return createDetachedLocalReferencePosition(refType);
|
|
518
|
-
}
|
|
519
|
-
function createPositionReference(client, pos, refType, op, fromSnapshot, localSeq, slidingPreference) {
|
|
520
|
-
let segoff;
|
|
521
|
-
if (op) {
|
|
522
|
-
assert((refType & ReferenceType.SlideOnRemove) !== 0, 0x2f5 /* op create references must be SlideOnRemove */);
|
|
523
|
-
segoff = client.getContainingSegment(pos, {
|
|
524
|
-
referenceSequenceNumber: op.referenceSequenceNumber,
|
|
525
|
-
clientId: op.clientId,
|
|
526
|
-
});
|
|
527
|
-
segoff = getSlideToSegoff(segoff);
|
|
528
|
-
}
|
|
529
|
-
else {
|
|
530
|
-
assert((refType & ReferenceType.SlideOnRemove) === 0 || !!fromSnapshot, 0x2f6 /* SlideOnRemove references must be op created */);
|
|
531
|
-
segoff = client.getContainingSegment(pos, undefined, localSeq);
|
|
532
|
-
}
|
|
533
|
-
return createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot, slidingPreference);
|
|
534
|
-
}
|
|
535
|
-
export function createSequenceInterval(label, start, end, client, intervalType, op, fromSnapshot, stickiness = IntervalStickiness.END) {
|
|
536
|
-
let beginRefType = ReferenceType.RangeBegin;
|
|
537
|
-
let endRefType = ReferenceType.RangeEnd;
|
|
538
|
-
if (intervalType === IntervalType.Transient) {
|
|
539
|
-
beginRefType = ReferenceType.Transient;
|
|
540
|
-
endRefType = ReferenceType.Transient;
|
|
541
|
-
}
|
|
542
|
-
else {
|
|
543
|
-
if (intervalType === IntervalType.Nest) {
|
|
544
|
-
beginRefType = ReferenceType.NestBegin;
|
|
545
|
-
endRefType = ReferenceType.NestEnd;
|
|
546
|
-
}
|
|
547
|
-
// All non-transient interval references must eventually be SlideOnRemove
|
|
548
|
-
// To ensure eventual consistency, they must start as StayOnRemove when
|
|
549
|
-
// pending (created locally and creation op is not acked)
|
|
550
|
-
if (op || fromSnapshot) {
|
|
551
|
-
beginRefType |= ReferenceType.SlideOnRemove;
|
|
552
|
-
endRefType |= ReferenceType.SlideOnRemove;
|
|
553
|
-
}
|
|
554
|
-
else {
|
|
555
|
-
beginRefType |= ReferenceType.StayOnRemove;
|
|
556
|
-
endRefType |= ReferenceType.StayOnRemove;
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
const startLref = createPositionReference(client, start, beginRefType, op, fromSnapshot, undefined, startReferenceSlidingPreference(stickiness));
|
|
560
|
-
const endLref = createPositionReference(client, end, endRefType, op, fromSnapshot, undefined, endReferenceSlidingPreference(stickiness));
|
|
561
|
-
const rangeProp = {
|
|
562
|
-
[reservedRangeLabelsKey]: [label],
|
|
563
|
-
};
|
|
564
|
-
startLref.addProperties(rangeProp);
|
|
565
|
-
endLref.addProperties(rangeProp);
|
|
566
|
-
const ival = new SequenceInterval(client, startLref, endLref, intervalType, rangeProp, stickiness);
|
|
567
|
-
return ival;
|
|
568
|
-
}
|
|
569
48
|
export function createIntervalIndex() {
|
|
570
49
|
const helpers = {
|
|
571
|
-
compareEnds:
|
|
50
|
+
compareEnds: (a, b) => a.end - b.end,
|
|
572
51
|
create: createInterval,
|
|
573
52
|
};
|
|
574
53
|
const lc = new LocalIntervalCollection(undefined, "", helpers);
|
|
575
54
|
return lc;
|
|
576
55
|
}
|
|
577
|
-
class IdIntervalIndex {
|
|
578
|
-
constructor() {
|
|
579
|
-
this.intervalIdMap = new Map();
|
|
580
|
-
}
|
|
581
|
-
add(interval) {
|
|
582
|
-
const id = interval.getIntervalId();
|
|
583
|
-
assert(id !== undefined, 0x2c0 /* "ID must be created before adding interval to collection" */);
|
|
584
|
-
// Make the ID immutable.
|
|
585
|
-
Object.defineProperty(interval.properties, reservedIntervalIdKey, {
|
|
586
|
-
configurable: false,
|
|
587
|
-
enumerable: true,
|
|
588
|
-
writable: false,
|
|
589
|
-
});
|
|
590
|
-
this.intervalIdMap.set(id, interval);
|
|
591
|
-
}
|
|
592
|
-
remove(interval) {
|
|
593
|
-
const id = interval.getIntervalId();
|
|
594
|
-
assert(id !== undefined, 0x311 /* expected id to exist on interval */);
|
|
595
|
-
this.intervalIdMap.delete(id);
|
|
596
|
-
}
|
|
597
|
-
getIntervalById(id) {
|
|
598
|
-
return this.intervalIdMap.get(id);
|
|
599
|
-
}
|
|
600
|
-
[Symbol.iterator]() {
|
|
601
|
-
return this.intervalIdMap.values();
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
class EndpointIndex {
|
|
605
|
-
constructor(client, helpers) {
|
|
606
|
-
this.client = client;
|
|
607
|
-
this.helpers = helpers;
|
|
608
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
609
|
-
this.endIntervalTree = new RedBlackTree(helpers.compareEnds);
|
|
610
|
-
}
|
|
611
|
-
previousInterval(pos) {
|
|
612
|
-
const transientInterval = this.helpers.create("transient", pos, pos, this.client, IntervalType.Transient);
|
|
613
|
-
const rbNode = this.endIntervalTree.floor(transientInterval);
|
|
614
|
-
if (rbNode) {
|
|
615
|
-
return rbNode.data;
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
nextInterval(pos) {
|
|
619
|
-
const transientInterval = this.helpers.create("transient", pos, pos, this.client, IntervalType.Transient);
|
|
620
|
-
const rbNode = this.endIntervalTree.ceil(transientInterval);
|
|
621
|
-
if (rbNode) {
|
|
622
|
-
return rbNode.data;
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
add(interval) {
|
|
626
|
-
this.endIntervalTree.put(interval, interval);
|
|
627
|
-
}
|
|
628
|
-
remove(interval) {
|
|
629
|
-
this.endIntervalTree.remove(interval);
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
/**
|
|
633
|
-
* Interface for intervals that have comparison override properties.
|
|
634
|
-
*/
|
|
635
|
-
const forceCompare = Symbol();
|
|
636
|
-
/**
|
|
637
|
-
* Compares two objects based on their comparison override properties.
|
|
638
|
-
* @returns A number indicating the order of the intervals (negative for a is lower than b, 0 for tie, positive for a is greater than b).
|
|
639
|
-
*/
|
|
640
|
-
function compareOverrideables(a, b) {
|
|
641
|
-
var _a, _b;
|
|
642
|
-
const forceCompareA = (_a = a[forceCompare]) !== null && _a !== void 0 ? _a : 0;
|
|
643
|
-
const forceCompareB = (_b = b[forceCompare]) !== null && _b !== void 0 ? _b : 0;
|
|
644
|
-
return forceCompareA - forceCompareB;
|
|
645
|
-
}
|
|
646
|
-
class EndpointInRangeIndex {
|
|
647
|
-
constructor(helpers, client) {
|
|
648
|
-
this.helpers = helpers;
|
|
649
|
-
this.client = client;
|
|
650
|
-
this.intervalTree = new RedBlackTree((a, b) => {
|
|
651
|
-
const compareEndsResult = helpers.compareEnds(a, b);
|
|
652
|
-
if (compareEndsResult !== 0) {
|
|
653
|
-
return compareEndsResult;
|
|
654
|
-
}
|
|
655
|
-
const overrideablesComparison = compareOverrideables(a, b);
|
|
656
|
-
if (overrideablesComparison !== 0) {
|
|
657
|
-
return overrideablesComparison;
|
|
658
|
-
}
|
|
659
|
-
const aId = a.getIntervalId();
|
|
660
|
-
const bId = b.getIntervalId();
|
|
661
|
-
if (aId !== undefined && bId !== undefined) {
|
|
662
|
-
return aId.localeCompare(bId);
|
|
663
|
-
}
|
|
664
|
-
return 0;
|
|
665
|
-
});
|
|
666
|
-
}
|
|
667
|
-
add(interval) {
|
|
668
|
-
this.intervalTree.put(interval, interval);
|
|
669
|
-
}
|
|
670
|
-
remove(interval) {
|
|
671
|
-
this.intervalTree.remove(interval);
|
|
672
|
-
}
|
|
673
|
-
findIntervalsWithEndpointInRange(start, end) {
|
|
674
|
-
if (start <= 0 || start > end || this.intervalTree.isEmpty()) {
|
|
675
|
-
return [];
|
|
676
|
-
}
|
|
677
|
-
const results = [];
|
|
678
|
-
const action = (node) => {
|
|
679
|
-
results.push(node.data);
|
|
680
|
-
return true;
|
|
681
|
-
};
|
|
682
|
-
const transientStartInterval = this.helpers.create("transient", start, start, this.client, IntervalType.Transient);
|
|
683
|
-
const transientEndInterval = this.helpers.create("transient", end, end, this.client, IntervalType.Transient);
|
|
684
|
-
// Add comparison overrides to the transient intervals
|
|
685
|
-
transientStartInterval[forceCompare] = -1;
|
|
686
|
-
transientEndInterval[forceCompare] = 1;
|
|
687
|
-
this.intervalTree.mapRange(action, results, transientStartInterval, transientEndInterval);
|
|
688
|
-
return results;
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
class StartpointInRangeIndex {
|
|
692
|
-
constructor(helpers, client) {
|
|
693
|
-
this.helpers = helpers;
|
|
694
|
-
this.client = client;
|
|
695
|
-
this.intervalTree = new RedBlackTree((a, b) => {
|
|
696
|
-
assert(typeof helpers.compareStarts === "function", 0x6d1 /* compareStarts does not exist in the helpers */);
|
|
697
|
-
const compareStartsResult = helpers.compareStarts(a, b);
|
|
698
|
-
if (compareStartsResult !== 0) {
|
|
699
|
-
return compareStartsResult;
|
|
700
|
-
}
|
|
701
|
-
const overrideablesComparison = compareOverrideables(a, b);
|
|
702
|
-
if (overrideablesComparison !== 0) {
|
|
703
|
-
return overrideablesComparison;
|
|
704
|
-
}
|
|
705
|
-
const aId = a.getIntervalId();
|
|
706
|
-
const bId = b.getIntervalId();
|
|
707
|
-
if (aId !== undefined && bId !== undefined) {
|
|
708
|
-
return aId.localeCompare(bId);
|
|
709
|
-
}
|
|
710
|
-
return 0;
|
|
711
|
-
});
|
|
712
|
-
}
|
|
713
|
-
add(interval) {
|
|
714
|
-
this.intervalTree.put(interval, interval);
|
|
715
|
-
}
|
|
716
|
-
remove(interval) {
|
|
717
|
-
this.intervalTree.remove(interval);
|
|
718
|
-
}
|
|
719
|
-
findIntervalsWithStartpointInRange(start, end) {
|
|
720
|
-
if (start <= 0 || start > end || this.intervalTree.isEmpty()) {
|
|
721
|
-
return [];
|
|
722
|
-
}
|
|
723
|
-
const results = [];
|
|
724
|
-
const action = (node) => {
|
|
725
|
-
results.push(node.data);
|
|
726
|
-
return true;
|
|
727
|
-
};
|
|
728
|
-
const transientStartInterval = this.helpers.create("transient", start, start, this.client, IntervalType.Transient);
|
|
729
|
-
const transientEndInterval = this.helpers.create("transient", end, end, this.client, IntervalType.Transient);
|
|
730
|
-
// Add comparison overrides to the transient intervals
|
|
731
|
-
transientStartInterval[forceCompare] = -1;
|
|
732
|
-
transientEndInterval[forceCompare] = 1;
|
|
733
|
-
this.intervalTree.mapRange(action, results, transientStartInterval, transientEndInterval);
|
|
734
|
-
return results;
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
export function createEndpointInRangeIndex(helpers, client) {
|
|
738
|
-
return new EndpointInRangeIndex(helpers, client);
|
|
739
|
-
}
|
|
740
|
-
export function createStartpointInRangeIndex(helpers, client) {
|
|
741
|
-
return new StartpointInRangeIndex(helpers, client);
|
|
742
|
-
}
|
|
743
56
|
export class LocalIntervalCollection {
|
|
744
57
|
constructor(client, label, helpers,
|
|
745
58
|
/** Callback invoked each time one of the endpoints of an interval slides. */
|
|
@@ -749,8 +62,8 @@ export class LocalIntervalCollection {
|
|
|
749
62
|
this.helpers = helpers;
|
|
750
63
|
this.onPositionChange = onPositionChange;
|
|
751
64
|
this.overlappingIntervalsIndex = createOverlappingIntervalsIndex(client, helpers);
|
|
752
|
-
this.idIntervalIndex =
|
|
753
|
-
this.endIntervalIndex =
|
|
65
|
+
this.idIntervalIndex = createIdIntervalIndex();
|
|
66
|
+
this.endIntervalIndex = createEndpointIndex(client, helpers);
|
|
754
67
|
this.indexes = new Set([
|
|
755
68
|
this.overlappingIntervalsIndex,
|
|
756
69
|
this.idIntervalIndex,
|
|
@@ -770,8 +83,7 @@ export class LocalIntervalCollection {
|
|
|
770
83
|
* @returns The interval's existing or newly created id
|
|
771
84
|
*/
|
|
772
85
|
ensureSerializedId(serializedInterval) {
|
|
773
|
-
|
|
774
|
-
let id = (_a = serializedInterval.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
|
|
86
|
+
let id = serializedInterval.properties?.[reservedIntervalIdKey];
|
|
775
87
|
if (id === undefined) {
|
|
776
88
|
// Back-compat: 0.39 and earlier did not have IDs on intervals. If an interval from such a client
|
|
777
89
|
// comes over the wire, create a non-unique one based on start/end.
|
|
@@ -810,7 +122,6 @@ export class LocalIntervalCollection {
|
|
|
810
122
|
}
|
|
811
123
|
addInterval(start, end, intervalType, props, op, stickiness = IntervalStickiness.END) {
|
|
812
124
|
var _a;
|
|
813
|
-
var _b;
|
|
814
125
|
const interval = this.createInterval(start, end, intervalType, op, stickiness);
|
|
815
126
|
if (interval) {
|
|
816
127
|
if (!interval.properties) {
|
|
@@ -826,7 +137,7 @@ export class LocalIntervalCollection {
|
|
|
826
137
|
}
|
|
827
138
|
interval.addProperties(props);
|
|
828
139
|
}
|
|
829
|
-
(_a =
|
|
140
|
+
(_a = interval.properties)[reservedIntervalIdKey] ?? (_a[reservedIntervalIdKey] = uuid());
|
|
830
141
|
this.add(interval);
|
|
831
142
|
}
|
|
832
143
|
return interval;
|
|
@@ -886,12 +197,11 @@ export class LocalIntervalCollection {
|
|
|
886
197
|
this.removeIntervalFromIndexes(interval);
|
|
887
198
|
}
|
|
888
199
|
}, () => {
|
|
889
|
-
var _a;
|
|
890
200
|
assert(previousInterval !== undefined, 0x3fa /* Invalid interleaving of before/after slide */);
|
|
891
201
|
pendingChanges--;
|
|
892
202
|
if (pendingChanges === 0) {
|
|
893
203
|
this.addIntervalToIndexes(interval);
|
|
894
|
-
|
|
204
|
+
this.onPositionChange?.(interval, previousInterval);
|
|
895
205
|
previousInterval = undefined;
|
|
896
206
|
}
|
|
897
207
|
});
|
|
@@ -904,18 +214,6 @@ export class LocalIntervalCollection {
|
|
|
904
214
|
}
|
|
905
215
|
}
|
|
906
216
|
LocalIntervalCollection.legacyIdPrefix = "legacy";
|
|
907
|
-
export const compareSequenceIntervalEnds = (a, b) => compareReferencePositions(a.end, b.end);
|
|
908
|
-
export const compareSequenceIntervalStarts = (a, b) => compareReferencePositions(a.start, b.start);
|
|
909
|
-
export const sequenceIntervalHelpers = {
|
|
910
|
-
compareEnds: compareSequenceIntervalEnds,
|
|
911
|
-
compareStarts: compareSequenceIntervalStarts,
|
|
912
|
-
create: createSequenceInterval,
|
|
913
|
-
};
|
|
914
|
-
export const intervalHelpers = {
|
|
915
|
-
compareEnds: (a, b) => a.end - b.end,
|
|
916
|
-
compareStarts: (a, b) => a.start - b.start,
|
|
917
|
-
create: createInterval,
|
|
918
|
-
};
|
|
919
217
|
class SequenceIntervalCollectionFactory {
|
|
920
218
|
load(emitter, raw = [], options) {
|
|
921
219
|
return new IntervalCollection(sequenceIntervalHelpers, true, emitter, raw, options);
|
|
@@ -938,18 +236,10 @@ export class SequenceIntervalCollectionValueType {
|
|
|
938
236
|
SequenceIntervalCollectionValueType.Name = "sharedStringIntervalCollection";
|
|
939
237
|
SequenceIntervalCollectionValueType._factory = new SequenceIntervalCollectionFactory();
|
|
940
238
|
SequenceIntervalCollectionValueType._ops = makeOpsMap();
|
|
941
|
-
const compareIntervalEnds = (a, b) => a.end - b.end;
|
|
942
|
-
function createInterval(label, start, end, client, intervalType, op, fromSnapshot) {
|
|
943
|
-
const rangeProp = {};
|
|
944
|
-
if (label && label.length > 0) {
|
|
945
|
-
rangeProp[reservedRangeLabelsKey] = [label];
|
|
946
|
-
}
|
|
947
|
-
return new Interval(start, end, rangeProp);
|
|
948
|
-
}
|
|
949
239
|
class IntervalCollectionFactory {
|
|
950
240
|
load(emitter, raw = [], options) {
|
|
951
241
|
const helpers = {
|
|
952
|
-
compareEnds:
|
|
242
|
+
compareEnds: (a, b) => a.end - b.end,
|
|
953
243
|
create: createInterval,
|
|
954
244
|
};
|
|
955
245
|
const collection = new IntervalCollection(helpers, false, emitter, raw, options);
|
|
@@ -978,7 +268,7 @@ export function makeOpsMap() {
|
|
|
978
268
|
const rebase = (collection, op, localOpMetadata) => {
|
|
979
269
|
const { localSeq } = localOpMetadata;
|
|
980
270
|
const rebasedValue = collection.rebaseLocalInterval(op.opName, op.value, localSeq);
|
|
981
|
-
const rebasedOp =
|
|
271
|
+
const rebasedOp = { ...op, value: rebasedValue };
|
|
982
272
|
return { rebasedOp, rebasedLocalOpMetadata: localOpMetadata };
|
|
983
273
|
};
|
|
984
274
|
return new Map([
|
|
@@ -1072,25 +362,23 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1072
362
|
* {@inheritdoc IIntervalCollection.attachIndex}
|
|
1073
363
|
*/
|
|
1074
364
|
attachIndex(index) {
|
|
1075
|
-
var _a;
|
|
1076
365
|
if (!this.attached) {
|
|
1077
366
|
throw new LoggingError("The local interval collection must exist");
|
|
1078
367
|
}
|
|
1079
368
|
for (const interval of this) {
|
|
1080
369
|
index.add(interval);
|
|
1081
370
|
}
|
|
1082
|
-
|
|
371
|
+
this.localCollection?.appendIndex(index);
|
|
1083
372
|
}
|
|
1084
373
|
/**
|
|
1085
374
|
* {@inheritdoc IIntervalCollection.detachIndex}
|
|
1086
375
|
*/
|
|
1087
376
|
detachIndex(index) {
|
|
1088
|
-
var _a;
|
|
1089
377
|
if (!this.attached) {
|
|
1090
378
|
throw new LoggingError("The local interval collection must exist");
|
|
1091
379
|
}
|
|
1092
380
|
// Avoid removing intervals if the index does not exist
|
|
1093
|
-
if (!
|
|
381
|
+
if (!this.localCollection?.removeIndex(index)) {
|
|
1094
382
|
return false;
|
|
1095
383
|
}
|
|
1096
384
|
for (const interval of this) {
|
|
@@ -1099,7 +387,6 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1099
387
|
return true;
|
|
1100
388
|
}
|
|
1101
389
|
rebasePositionWithSegmentSlide(pos, seqNumberFrom, localSeq) {
|
|
1102
|
-
var _a;
|
|
1103
390
|
if (!this.client) {
|
|
1104
391
|
throw new LoggingError("mergeTree client must exist");
|
|
1105
392
|
}
|
|
@@ -1110,7 +397,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1110
397
|
}, localSeq);
|
|
1111
398
|
// if segment is undefined, it slid off the string
|
|
1112
399
|
assert(segment !== undefined, 0x54e /* No segment found */);
|
|
1113
|
-
const segoff =
|
|
400
|
+
const segoff = getSlideToSegoff({ segment, offset }) ?? segment;
|
|
1114
401
|
// case happens when rebasing op, but concurrently entire string has been deleted
|
|
1115
402
|
if (segoff.segment === undefined || segoff.offset === undefined) {
|
|
1116
403
|
return DetachedReferencePosition;
|
|
@@ -1122,7 +409,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1122
409
|
assert(this.client !== undefined, 0x550 /* Client should be defined when computing rebased position */);
|
|
1123
410
|
const original = this.localSeqToSerializedInterval.get(localSeq);
|
|
1124
411
|
assert(original !== undefined, 0x551 /* Failed to store pending serialized interval info for this localSeq. */);
|
|
1125
|
-
const rebased =
|
|
412
|
+
const rebased = { ...original };
|
|
1126
413
|
const { start, end, sequenceNumber } = original;
|
|
1127
414
|
if (start !== undefined) {
|
|
1128
415
|
rebased.start = this.rebasePositionWithSegmentSlide(start, sequenceNumber, localSeq);
|
|
@@ -1204,7 +491,6 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1204
491
|
* {@inheritdoc IIntervalCollection.add}
|
|
1205
492
|
*/
|
|
1206
493
|
add(start, end, intervalType, props, stickiness = IntervalStickiness.END) {
|
|
1207
|
-
var _a, _b;
|
|
1208
494
|
if (!this.localCollection) {
|
|
1209
495
|
throw new LoggingError("attach must be called prior to adding intervals");
|
|
1210
496
|
}
|
|
@@ -1220,7 +506,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1220
506
|
end,
|
|
1221
507
|
intervalType,
|
|
1222
508
|
properties: interval.properties,
|
|
1223
|
-
sequenceNumber:
|
|
509
|
+
sequenceNumber: this.client?.getCurrentSeq() ?? 0,
|
|
1224
510
|
start,
|
|
1225
511
|
stickiness,
|
|
1226
512
|
};
|
|
@@ -1352,9 +638,8 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1352
638
|
entries.push(serializedInterval);
|
|
1353
639
|
}
|
|
1354
640
|
removePendingChange(serializedInterval) {
|
|
1355
|
-
var _a;
|
|
1356
641
|
// Change ops always have an ID.
|
|
1357
|
-
const id =
|
|
642
|
+
const id = serializedInterval.properties?.[reservedIntervalIdKey];
|
|
1358
643
|
if (serializedInterval.start !== undefined) {
|
|
1359
644
|
this.removePendingChangeHelper(id, this.pendingChangesStart, serializedInterval);
|
|
1360
645
|
}
|
|
@@ -1369,8 +654,8 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1369
654
|
if (entries.length === 0) {
|
|
1370
655
|
pendingChanges.delete(id);
|
|
1371
656
|
}
|
|
1372
|
-
if (
|
|
1373
|
-
|
|
657
|
+
if (pendingChange?.start !== serializedInterval.start ||
|
|
658
|
+
pendingChange?.end !== serializedInterval.end) {
|
|
1374
659
|
throw new LoggingError("Mismatch in pending changes");
|
|
1375
660
|
}
|
|
1376
661
|
}
|
|
@@ -1385,20 +670,19 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1385
670
|
}
|
|
1386
671
|
/** @internal */
|
|
1387
672
|
ackChange(serializedInterval, local, op, localOpMetadata) {
|
|
1388
|
-
var _a, _b, _c, _d;
|
|
1389
673
|
if (!this.localCollection) {
|
|
1390
674
|
throw new LoggingError("Attach must be called before accessing intervals");
|
|
1391
675
|
}
|
|
1392
676
|
if (local) {
|
|
1393
677
|
assert(localOpMetadata !== undefined, 0x552 /* op metadata should be defined for local op */);
|
|
1394
|
-
this.localSeqToSerializedInterval.delete(localOpMetadata
|
|
678
|
+
this.localSeqToSerializedInterval.delete(localOpMetadata?.localSeq);
|
|
1395
679
|
// This is an ack from the server. Remove the pending change.
|
|
1396
680
|
this.removePendingChange(serializedInterval);
|
|
1397
681
|
}
|
|
1398
682
|
// Note that the ID is in the property bag only to allow us to find the interval.
|
|
1399
683
|
// This API cannot change the ID, and writing to the ID property will result in an exception. So we
|
|
1400
684
|
// strip it out of the properties here.
|
|
1401
|
-
const
|
|
685
|
+
const { [reservedIntervalIdKey]: id, ...newProps } = serializedInterval.properties ?? {};
|
|
1402
686
|
assert(id !== undefined, 0x3fe /* id must exist on the interval */);
|
|
1403
687
|
const interval = this.getIntervalById(id);
|
|
1404
688
|
if (!interval) {
|
|
@@ -1407,9 +691,9 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1407
691
|
}
|
|
1408
692
|
if (local) {
|
|
1409
693
|
// Let the propertyManager prune its pending change-properties set.
|
|
1410
|
-
|
|
694
|
+
interval.propertyManager?.ackPendingProperties({
|
|
1411
695
|
type: MergeTreeDeltaType.ANNOTATE,
|
|
1412
|
-
props:
|
|
696
|
+
props: serializedInterval.properties ?? {},
|
|
1413
697
|
});
|
|
1414
698
|
this.ackInterval(interval, op);
|
|
1415
699
|
}
|
|
@@ -1430,7 +714,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1430
714
|
// If changeInterval gives us a new interval, work with that one. Otherwise keep working with
|
|
1431
715
|
// the one we originally found in the tree.
|
|
1432
716
|
newInterval =
|
|
1433
|
-
|
|
717
|
+
this.localCollection.changeInterval(interval, start, end, op) ?? interval;
|
|
1434
718
|
}
|
|
1435
719
|
const deltaProps = newInterval.addProperties(newProps, true, op.sequenceNumber);
|
|
1436
720
|
if (this.onDeserialize) {
|
|
@@ -1445,18 +729,6 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1445
729
|
}
|
|
1446
730
|
}
|
|
1447
731
|
}
|
|
1448
|
-
/**
|
|
1449
|
-
* @deprecated - This functionality was useful when adding two intervals at the same start/end positions resulted
|
|
1450
|
-
* in a conflict. This is no longer the case (as of PR#6407), as interval collections support multiple intervals
|
|
1451
|
-
* at the same location and gives each interval a unique id.
|
|
1452
|
-
*
|
|
1453
|
-
* As such, the conflict resolver is never invoked and unnecessary. This API will be removed in an upcoming release.
|
|
1454
|
-
*/
|
|
1455
|
-
addConflictResolver(_) {
|
|
1456
|
-
if (!this.localCollection) {
|
|
1457
|
-
throw new LoggingError("attachSequence must be called");
|
|
1458
|
-
}
|
|
1459
|
-
}
|
|
1460
732
|
/**
|
|
1461
733
|
* {@inheritdoc IIntervalCollection.attachDeserializer}
|
|
1462
734
|
*/
|
|
@@ -1480,7 +752,6 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1480
752
|
* @internal
|
|
1481
753
|
*/
|
|
1482
754
|
rebaseLocalInterval(opName, serializedInterval, localSeq) {
|
|
1483
|
-
var _a, _b, _c, _d, _e, _f;
|
|
1484
755
|
if (!this.client) {
|
|
1485
756
|
// If there's no associated mergeTree client, the originally submitted op is still correct.
|
|
1486
757
|
return serializedInterval;
|
|
@@ -1489,14 +760,14 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1489
760
|
throw new LoggingError("attachSequence must be called");
|
|
1490
761
|
}
|
|
1491
762
|
const { intervalType, properties } = serializedInterval;
|
|
1492
|
-
const { start: startRebased, end: endRebased } =
|
|
1493
|
-
const intervalId = properties
|
|
1494
|
-
const localInterval =
|
|
763
|
+
const { start: startRebased, end: endRebased } = this.localSeqToRebasedInterval.get(localSeq) ?? this.computeRebasedPositions(localSeq);
|
|
764
|
+
const intervalId = properties?.[reservedIntervalIdKey];
|
|
765
|
+
const localInterval = this.localCollection?.idIntervalIndex.getIntervalById(intervalId);
|
|
1495
766
|
const rebased = {
|
|
1496
767
|
start: startRebased,
|
|
1497
768
|
end: endRebased,
|
|
1498
769
|
intervalType,
|
|
1499
|
-
sequenceNumber:
|
|
770
|
+
sequenceNumber: this.client?.getCurrentSeq() ?? 0,
|
|
1500
771
|
properties,
|
|
1501
772
|
};
|
|
1502
773
|
if (opName === "change" &&
|
|
@@ -1508,7 +779,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1508
779
|
if (startRebased === DetachedReferencePosition ||
|
|
1509
780
|
endRebased === DetachedReferencePosition) {
|
|
1510
781
|
if (localInterval) {
|
|
1511
|
-
|
|
782
|
+
this.localCollection?.removeExistingInterval(localInterval);
|
|
1512
783
|
}
|
|
1513
784
|
return undefined;
|
|
1514
785
|
}
|
|
@@ -1517,17 +788,16 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1517
788
|
assert(localInterval instanceof SequenceInterval, 0x3a0 /* localInterval must be `SequenceInterval` when used with client */);
|
|
1518
789
|
// The rebased op may place this interval's endpoints on different segments. Calling `changeInterval` here
|
|
1519
790
|
// updates the local client's state to be consistent with the emitted op.
|
|
1520
|
-
|
|
791
|
+
this.localCollection?.changeInterval(localInterval, startRebased, endRebased, undefined, localSeq);
|
|
1521
792
|
}
|
|
1522
793
|
return rebased;
|
|
1523
794
|
}
|
|
1524
795
|
getSlideToSegment(lref) {
|
|
1525
|
-
var _a, _b;
|
|
1526
796
|
if (!this.client) {
|
|
1527
797
|
throw new LoggingError("client does not exist");
|
|
1528
798
|
}
|
|
1529
799
|
const segoff = { segment: lref.getSegment(), offset: lref.getOffset() };
|
|
1530
|
-
if (
|
|
800
|
+
if (segoff.segment?.localRefs?.has(lref) !== true) {
|
|
1531
801
|
return undefined;
|
|
1532
802
|
}
|
|
1533
803
|
const newSegoff = getSlideToSegoff(segoff);
|
|
@@ -1543,7 +813,6 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1543
813
|
lref.refType = refType;
|
|
1544
814
|
}
|
|
1545
815
|
ackInterval(interval, op) {
|
|
1546
|
-
var _a, _b;
|
|
1547
816
|
// Only SequenceIntervals need potential sliding
|
|
1548
817
|
if (!(interval instanceof SequenceInterval)) {
|
|
1549
818
|
return;
|
|
@@ -1588,7 +857,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1588
857
|
// remove and rebuild start interval as transient for event
|
|
1589
858
|
this.client.removeLocalReferencePosition(oldInterval.start);
|
|
1590
859
|
oldInterval.start.refType = ReferenceType.Transient;
|
|
1591
|
-
|
|
860
|
+
oldSeg?.localRefs?.addLocalRef(oldInterval.start, oldInterval.start.getOffset());
|
|
1592
861
|
}
|
|
1593
862
|
if (needsEndUpdate) {
|
|
1594
863
|
const props = interval.end.properties;
|
|
@@ -1600,7 +869,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1600
869
|
const oldSeg = oldInterval.end.getSegment();
|
|
1601
870
|
this.client.removeLocalReferencePosition(oldInterval.end);
|
|
1602
871
|
oldInterval.end.refType = ReferenceType.Transient;
|
|
1603
|
-
|
|
872
|
+
oldSeg?.localRefs?.addLocalRef(oldInterval.end, oldInterval.end.getOffset());
|
|
1604
873
|
}
|
|
1605
874
|
this.localCollection.add(interval);
|
|
1606
875
|
this.emitChange(interval, oldInterval, true, true, op);
|
|
@@ -1608,11 +877,10 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1608
877
|
}
|
|
1609
878
|
/** @internal */
|
|
1610
879
|
ackAdd(serializedInterval, local, op, localOpMetadata) {
|
|
1611
|
-
var _a;
|
|
1612
880
|
if (local) {
|
|
1613
881
|
assert(localOpMetadata !== undefined, 0x553 /* op metadata should be defined for local op */);
|
|
1614
882
|
this.localSeqToSerializedInterval.delete(localOpMetadata.localSeq);
|
|
1615
|
-
const id =
|
|
883
|
+
const id = serializedInterval.properties?.[reservedIntervalIdKey];
|
|
1616
884
|
const localInterval = this.getIntervalById(id);
|
|
1617
885
|
if (localInterval) {
|
|
1618
886
|
this.ackInterval(localInterval, op);
|
|
@@ -1748,9 +1016,8 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1748
1016
|
* endpoint is a part of.
|
|
1749
1017
|
*/
|
|
1750
1018
|
export function intervalLocatorFromEndpoint(potentialEndpoint) {
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
return interval && (collectionNameArray === null || collectionNameArray === void 0 ? void 0 : collectionNameArray.length) === 1
|
|
1019
|
+
const { interval, [reservedRangeLabelsKey]: collectionNameArray } = potentialEndpoint.properties ?? {};
|
|
1020
|
+
return interval && collectionNameArray?.length === 1
|
|
1754
1021
|
? { label: collectionNameArray[0], interval }
|
|
1755
1022
|
: undefined;
|
|
1756
1023
|
}
|