@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
|
@@ -3,55 +3,17 @@
|
|
|
3
3
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
7
|
-
var t = {};
|
|
8
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
9
|
-
t[p] = s[p];
|
|
10
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
11
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
12
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
13
|
-
t[p[i]] = s[p[i]];
|
|
14
|
-
}
|
|
15
|
-
return t;
|
|
16
|
-
};
|
|
17
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.intervalLocatorFromEndpoint = exports.IntervalCollection = exports.makeOpsMap = exports.IntervalCollectionValueType = exports.SequenceIntervalCollectionValueType = exports.
|
|
7
|
+
exports.intervalLocatorFromEndpoint = exports.IntervalCollection = exports.makeOpsMap = exports.IntervalCollectionValueType = exports.SequenceIntervalCollectionValueType = exports.LocalIntervalCollection = exports.createIntervalIndex = void 0;
|
|
19
8
|
/* eslint-disable no-bitwise */
|
|
20
|
-
const
|
|
21
|
-
const
|
|
9
|
+
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
10
|
+
const core_utils_1 = require("@fluidframework/core-utils");
|
|
22
11
|
const merge_tree_1 = require("@fluidframework/merge-tree");
|
|
23
12
|
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
24
13
|
const uuid_1 = require("uuid");
|
|
14
|
+
const intervals_1 = require("./intervals");
|
|
25
15
|
const intervalIndex_1 = require("./intervalIndex");
|
|
26
16
|
const reservedIntervalIdKey = "intervalId";
|
|
27
|
-
/**
|
|
28
|
-
* Values are used in persisted formats (ops) and revertibles.
|
|
29
|
-
* @alpha
|
|
30
|
-
*/
|
|
31
|
-
exports.IntervalOpType = {
|
|
32
|
-
ADD: "add",
|
|
33
|
-
DELETE: "delete",
|
|
34
|
-
CHANGE: "change",
|
|
35
|
-
PROPERTY_CHANGED: "propertyChanged",
|
|
36
|
-
POSITION_REMOVE: "positionRemove",
|
|
37
|
-
};
|
|
38
|
-
var IntervalType;
|
|
39
|
-
(function (IntervalType) {
|
|
40
|
-
IntervalType[IntervalType["Simple"] = 0] = "Simple";
|
|
41
|
-
IntervalType[IntervalType["Nest"] = 1] = "Nest";
|
|
42
|
-
/**
|
|
43
|
-
* SlideOnRemove indicates that the ends of the interval will slide if the segment
|
|
44
|
-
* they reference is removed and acked.
|
|
45
|
-
* See `packages\dds\merge-tree\docs\REFERENCEPOSITIONS.md` for details
|
|
46
|
-
* SlideOnRemove is the default interval behavior and does not need to be specified.
|
|
47
|
-
*/
|
|
48
|
-
IntervalType[IntervalType["SlideOnRemove"] = 2] = "SlideOnRemove";
|
|
49
|
-
/**
|
|
50
|
-
* A temporary interval, used internally
|
|
51
|
-
* @internal
|
|
52
|
-
*/
|
|
53
|
-
IntervalType[IntervalType["Transient"] = 4] = "Transient";
|
|
54
|
-
})(IntervalType = exports.IntervalType || (exports.IntervalType = {}));
|
|
55
17
|
/**
|
|
56
18
|
* Decompress an interval after loading a summary from JSON. The exact format
|
|
57
19
|
* of this compression is unspecified and subject to change
|
|
@@ -62,7 +24,7 @@ function decompressInterval(interval, label) {
|
|
|
62
24
|
end: interval[1],
|
|
63
25
|
sequenceNumber: interval[2],
|
|
64
26
|
intervalType: interval[3],
|
|
65
|
-
properties:
|
|
27
|
+
properties: { ...interval[4], [merge_tree_1.reservedRangeLabelsKey]: [label] },
|
|
66
28
|
stickiness: interval[5],
|
|
67
29
|
};
|
|
68
30
|
}
|
|
@@ -77,679 +39,24 @@ function compressInterval(interval) {
|
|
|
77
39
|
end,
|
|
78
40
|
sequenceNumber,
|
|
79
41
|
intervalType,
|
|
80
|
-
|
|
42
|
+
// remove the `referenceRangeLabels` property as it is already stored
|
|
43
|
+
// in the `label` field of the summary
|
|
44
|
+
{ ...properties, [merge_tree_1.reservedRangeLabelsKey]: undefined },
|
|
81
45
|
];
|
|
82
|
-
if (interval.stickiness !== undefined && interval.stickiness !==
|
|
46
|
+
if (interval.stickiness !== undefined && interval.stickiness !== intervals_1.IntervalStickiness.END) {
|
|
83
47
|
base.push(interval.stickiness);
|
|
84
48
|
}
|
|
85
49
|
return base;
|
|
86
50
|
}
|
|
87
|
-
function startReferenceSlidingPreference(stickiness) {
|
|
88
|
-
// if any start stickiness, prefer sliding backwards
|
|
89
|
-
return (stickiness & exports.IntervalStickiness.START) !== 0
|
|
90
|
-
? merge_tree_1.SlidingPreference.BACKWARD
|
|
91
|
-
: merge_tree_1.SlidingPreference.FORWARD;
|
|
92
|
-
}
|
|
93
|
-
function endReferenceSlidingPreference(stickiness) {
|
|
94
|
-
// if any end stickiness, prefer sliding forwards
|
|
95
|
-
return (stickiness & exports.IntervalStickiness.END) !== 0
|
|
96
|
-
? merge_tree_1.SlidingPreference.FORWARD
|
|
97
|
-
: merge_tree_1.SlidingPreference.BACKWARD;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Determines how an interval should expand when segments are inserted adjacent
|
|
101
|
-
* to the range it spans
|
|
102
|
-
*
|
|
103
|
-
* Note that interval stickiness is currently an experimental feature and must
|
|
104
|
-
* be explicitly enabled with the `intervalStickinessEnabled` flag
|
|
105
|
-
*/
|
|
106
|
-
exports.IntervalStickiness = {
|
|
107
|
-
/**
|
|
108
|
-
* Interval does not expand to include adjacent segments
|
|
109
|
-
*/
|
|
110
|
-
NONE: 0b00,
|
|
111
|
-
/**
|
|
112
|
-
* Interval expands to include segments inserted adjacent to the start
|
|
113
|
-
*/
|
|
114
|
-
START: 0b01,
|
|
115
|
-
/**
|
|
116
|
-
* Interval expands to include segments inserted adjacent to the end
|
|
117
|
-
*
|
|
118
|
-
* This is the default stickiness
|
|
119
|
-
*/
|
|
120
|
-
END: 0b10,
|
|
121
|
-
/**
|
|
122
|
-
* Interval expands to include all segments inserted adjacent to it
|
|
123
|
-
*/
|
|
124
|
-
FULL: 0b11,
|
|
125
|
-
};
|
|
126
|
-
/**
|
|
127
|
-
* Serializable interval whose endpoints are plain-old numbers.
|
|
128
|
-
*/
|
|
129
|
-
class Interval {
|
|
130
|
-
constructor(start, end, props) {
|
|
131
|
-
this.start = start;
|
|
132
|
-
this.end = end;
|
|
133
|
-
this.propertyManager = new merge_tree_1.PropertiesManager();
|
|
134
|
-
this.properties = {};
|
|
135
|
-
if (props) {
|
|
136
|
-
this.addProperties(props);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* {@inheritDoc ISerializableInterval.getIntervalId}
|
|
141
|
-
*/
|
|
142
|
-
getIntervalId() {
|
|
143
|
-
var _a;
|
|
144
|
-
const id = (_a = this.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
|
|
145
|
-
(0, common_utils_1.assert)(id !== undefined, 0x5e1 /* interval ID should not be undefined */);
|
|
146
|
-
return `${id}`;
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* @returns an array containing any auxiliary property sets added with `addPropertySet`.
|
|
150
|
-
*/
|
|
151
|
-
getAdditionalPropertySets() {
|
|
152
|
-
var _a;
|
|
153
|
-
return (_a = this.auxProps) !== null && _a !== void 0 ? _a : [];
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Adds an auxiliary set of properties to this interval.
|
|
157
|
-
* These properties can be recovered using `getAdditionalPropertySets`
|
|
158
|
-
* @param props - set of properties to add
|
|
159
|
-
* @remarks - This gets called as part of the default conflict resolver for `IIntervalCollection<Interval>`
|
|
160
|
-
* (i.e. non-sequence-based interval collections). However, the additional properties don't get serialized.
|
|
161
|
-
* This functionality seems half-baked.
|
|
162
|
-
*/
|
|
163
|
-
addPropertySet(props) {
|
|
164
|
-
if (this.auxProps === undefined) {
|
|
165
|
-
this.auxProps = [];
|
|
166
|
-
}
|
|
167
|
-
this.auxProps.push(props);
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* {@inheritDoc ISerializableInterval.serialize}
|
|
171
|
-
* @internal
|
|
172
|
-
*/
|
|
173
|
-
serialize() {
|
|
174
|
-
const serializedInterval = {
|
|
175
|
-
end: this.end,
|
|
176
|
-
intervalType: 0,
|
|
177
|
-
sequenceNumber: 0,
|
|
178
|
-
start: this.start,
|
|
179
|
-
};
|
|
180
|
-
if (this.properties) {
|
|
181
|
-
serializedInterval.properties = this.properties;
|
|
182
|
-
}
|
|
183
|
-
return serializedInterval;
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* {@inheritDoc IInterval.clone}
|
|
187
|
-
*/
|
|
188
|
-
clone() {
|
|
189
|
-
return new Interval(this.start, this.end, this.properties);
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* {@inheritDoc IInterval.compare}
|
|
193
|
-
*/
|
|
194
|
-
compare(b) {
|
|
195
|
-
const startResult = this.compareStart(b);
|
|
196
|
-
if (startResult === 0) {
|
|
197
|
-
const endResult = this.compareEnd(b);
|
|
198
|
-
if (endResult === 0) {
|
|
199
|
-
const thisId = this.getIntervalId();
|
|
200
|
-
if (thisId) {
|
|
201
|
-
const bId = b.getIntervalId();
|
|
202
|
-
if (bId) {
|
|
203
|
-
return thisId > bId ? 1 : thisId < bId ? -1 : 0;
|
|
204
|
-
}
|
|
205
|
-
return 0;
|
|
206
|
-
}
|
|
207
|
-
return 0;
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
return endResult;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
return startResult;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* {@inheritDoc IInterval.compareStart}
|
|
219
|
-
*/
|
|
220
|
-
compareStart(b) {
|
|
221
|
-
return this.start - b.start;
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* {@inheritDoc IInterval.compareEnd}
|
|
225
|
-
*/
|
|
226
|
-
compareEnd(b) {
|
|
227
|
-
return this.end - b.end;
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* {@inheritDoc IInterval.overlaps}
|
|
231
|
-
*/
|
|
232
|
-
overlaps(b) {
|
|
233
|
-
const result = this.start <= b.end && this.end >= b.start;
|
|
234
|
-
return result;
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* {@inheritDoc IInterval.union}
|
|
238
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
239
|
-
*/
|
|
240
|
-
union(b) {
|
|
241
|
-
return new Interval(Math.min(this.start, b.start), Math.max(this.end, b.end), this.properties);
|
|
242
|
-
}
|
|
243
|
-
getProperties() {
|
|
244
|
-
return this.properties;
|
|
245
|
-
}
|
|
246
|
-
/**
|
|
247
|
-
* {@inheritDoc ISerializableInterval.addProperties}
|
|
248
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
249
|
-
*/
|
|
250
|
-
addProperties(newProps, collaborating = false, seq, op) {
|
|
251
|
-
if (newProps) {
|
|
252
|
-
this.initializeProperties();
|
|
253
|
-
return this.propertyManager.addProperties(this.properties, newProps, op, seq, collaborating);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* {@inheritDoc IInterval.modify}
|
|
258
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
259
|
-
*/
|
|
260
|
-
modify(label, start, end, op) {
|
|
261
|
-
const startPos = start !== null && start !== void 0 ? start : this.start;
|
|
262
|
-
const endPos = end !== null && end !== void 0 ? end : this.end;
|
|
263
|
-
if (this.start === startPos && this.end === endPos) {
|
|
264
|
-
// Return undefined to indicate that no change is necessary.
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
const newInterval = new Interval(startPos, endPos);
|
|
268
|
-
if (this.properties) {
|
|
269
|
-
newInterval.initializeProperties();
|
|
270
|
-
this.propertyManager.copyTo(this.properties, newInterval.properties, newInterval.propertyManager);
|
|
271
|
-
}
|
|
272
|
-
return newInterval;
|
|
273
|
-
}
|
|
274
|
-
initializeProperties() {
|
|
275
|
-
if (!this.propertyManager) {
|
|
276
|
-
this.propertyManager = new merge_tree_1.PropertiesManager();
|
|
277
|
-
}
|
|
278
|
-
if (!this.properties) {
|
|
279
|
-
this.properties = (0, merge_tree_1.createMap)();
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
exports.Interval = Interval;
|
|
284
|
-
/**
|
|
285
|
-
* Interval implementation whose ends are associated with positions in a mutatable sequence.
|
|
286
|
-
* As such, when content is inserted into the middle of the interval, the interval expands to
|
|
287
|
-
* include that content.
|
|
288
|
-
*
|
|
289
|
-
* @remarks - The endpoint's position should be treated exclusively to get reasonable behavior--i.e.
|
|
290
|
-
* an interval referring to "hello" in "hello world" should have a start position of 0 and an end
|
|
291
|
-
* position of 5.
|
|
292
|
-
*
|
|
293
|
-
* To see why, consider what happens if "llo wor" is removed from the string to make "held".
|
|
294
|
-
* The interval's startpoint remains on the "h" (it isn't altered), but the interval's endpoint
|
|
295
|
-
* slides forward to the next unremoved position, which is the "l" in "held".
|
|
296
|
-
* Users would generally expect the interval to now refer to "he" (as it is the subset of content
|
|
297
|
-
* remaining after the removal), hence the "l" should be excluded.
|
|
298
|
-
* If the interval endpoint was treated inclusively, the interval would now refer to "hel", which
|
|
299
|
-
* is undesirable.
|
|
300
|
-
*
|
|
301
|
-
* Since the end of an interval is treated exclusively but cannot be greater than or equal to the
|
|
302
|
-
* length of the associated sequence, application models which leverage interval collections should
|
|
303
|
-
* consider inserting a marker at the end of the sequence to represent the end of the content.
|
|
304
|
-
*/
|
|
305
|
-
class SequenceInterval {
|
|
306
|
-
constructor(client,
|
|
307
|
-
/**
|
|
308
|
-
* Start endpoint of this interval.
|
|
309
|
-
* @remarks - This endpoint can be resolved into a character position using the SharedString it's a part of.
|
|
310
|
-
*/
|
|
311
|
-
start,
|
|
312
|
-
/**
|
|
313
|
-
* End endpoint of this interval.
|
|
314
|
-
* @remarks - This endpoint can be resolved into a character position using the SharedString it's a part of.
|
|
315
|
-
*/
|
|
316
|
-
end, intervalType, props, stickiness = exports.IntervalStickiness.END) {
|
|
317
|
-
this.client = client;
|
|
318
|
-
this.start = start;
|
|
319
|
-
this.end = end;
|
|
320
|
-
this.intervalType = intervalType;
|
|
321
|
-
this.stickiness = stickiness;
|
|
322
|
-
this.propertyManager = new merge_tree_1.PropertiesManager();
|
|
323
|
-
this.properties = {};
|
|
324
|
-
if (props) {
|
|
325
|
-
this.addProperties(props);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* Subscribes to position change events on this interval if there are no current listeners.
|
|
330
|
-
* @internal
|
|
331
|
-
*/
|
|
332
|
-
addPositionChangeListeners(beforePositionChange, afterPositionChange) {
|
|
333
|
-
var _a, _b;
|
|
334
|
-
var _c, _d;
|
|
335
|
-
if (this.callbacks === undefined) {
|
|
336
|
-
this.callbacks = {
|
|
337
|
-
beforePositionChange,
|
|
338
|
-
afterPositionChange,
|
|
339
|
-
};
|
|
340
|
-
const startCbs = ((_a = (_c = this.start).callbacks) !== null && _a !== void 0 ? _a : (_c.callbacks = {}));
|
|
341
|
-
const endCbs = ((_b = (_d = this.end).callbacks) !== null && _b !== void 0 ? _b : (_d.callbacks = {}));
|
|
342
|
-
startCbs.beforeSlide = endCbs.beforeSlide = beforePositionChange;
|
|
343
|
-
startCbs.afterSlide = endCbs.afterSlide = afterPositionChange;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* Removes the currently subscribed position change listeners.
|
|
348
|
-
* @internal
|
|
349
|
-
*/
|
|
350
|
-
removePositionChangeListeners() {
|
|
351
|
-
if (this.callbacks) {
|
|
352
|
-
this.callbacks = undefined;
|
|
353
|
-
this.start.callbacks = undefined;
|
|
354
|
-
this.end.callbacks = undefined;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
/**
|
|
358
|
-
* {@inheritDoc ISerializableInterval.serialize}
|
|
359
|
-
* @internal
|
|
360
|
-
*/
|
|
361
|
-
serialize() {
|
|
362
|
-
const startPosition = this.client.localReferencePositionToPosition(this.start);
|
|
363
|
-
const endPosition = this.client.localReferencePositionToPosition(this.end);
|
|
364
|
-
const serializedInterval = {
|
|
365
|
-
end: endPosition,
|
|
366
|
-
intervalType: this.intervalType,
|
|
367
|
-
sequenceNumber: this.client.getCurrentSeq(),
|
|
368
|
-
start: startPosition,
|
|
369
|
-
};
|
|
370
|
-
if (this.properties) {
|
|
371
|
-
serializedInterval.properties = this.properties;
|
|
372
|
-
}
|
|
373
|
-
if (this.stickiness !== exports.IntervalStickiness.END) {
|
|
374
|
-
serializedInterval.stickiness = this.stickiness;
|
|
375
|
-
}
|
|
376
|
-
return serializedInterval;
|
|
377
|
-
}
|
|
378
|
-
/**
|
|
379
|
-
* {@inheritDoc IInterval.clone}
|
|
380
|
-
*/
|
|
381
|
-
clone() {
|
|
382
|
-
return new SequenceInterval(this.client, this.start, this.end, this.intervalType, this.properties, this.stickiness);
|
|
383
|
-
}
|
|
384
|
-
/**
|
|
385
|
-
* {@inheritDoc IInterval.compare}
|
|
386
|
-
*/
|
|
387
|
-
compare(b) {
|
|
388
|
-
const startResult = this.compareStart(b);
|
|
389
|
-
if (startResult === 0) {
|
|
390
|
-
const endResult = this.compareEnd(b);
|
|
391
|
-
if (endResult === 0) {
|
|
392
|
-
const thisId = this.getIntervalId();
|
|
393
|
-
if (thisId) {
|
|
394
|
-
const bId = b.getIntervalId();
|
|
395
|
-
if (bId) {
|
|
396
|
-
return thisId > bId ? 1 : thisId < bId ? -1 : 0;
|
|
397
|
-
}
|
|
398
|
-
return 0;
|
|
399
|
-
}
|
|
400
|
-
return 0;
|
|
401
|
-
}
|
|
402
|
-
else {
|
|
403
|
-
return endResult;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
else {
|
|
407
|
-
return startResult;
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
/**
|
|
411
|
-
* {@inheritDoc IInterval.compareStart}
|
|
412
|
-
*/
|
|
413
|
-
compareStart(b) {
|
|
414
|
-
return (0, merge_tree_1.compareReferencePositions)(this.start, b.start);
|
|
415
|
-
}
|
|
416
|
-
/**
|
|
417
|
-
* {@inheritDoc IInterval.compareEnd}
|
|
418
|
-
*/
|
|
419
|
-
compareEnd(b) {
|
|
420
|
-
return (0, merge_tree_1.compareReferencePositions)(this.end, b.end);
|
|
421
|
-
}
|
|
422
|
-
/**
|
|
423
|
-
* {@inheritDoc IInterval.overlaps}
|
|
424
|
-
*/
|
|
425
|
-
overlaps(b) {
|
|
426
|
-
const result = (0, merge_tree_1.compareReferencePositions)(this.start, b.end) <= 0 &&
|
|
427
|
-
(0, merge_tree_1.compareReferencePositions)(this.end, b.start) >= 0;
|
|
428
|
-
return result;
|
|
429
|
-
}
|
|
430
|
-
/**
|
|
431
|
-
* {@inheritDoc ISerializableInterval.getIntervalId}
|
|
432
|
-
*/
|
|
433
|
-
getIntervalId() {
|
|
434
|
-
var _a;
|
|
435
|
-
const id = (_a = this.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
|
|
436
|
-
(0, common_utils_1.assert)(id !== undefined, 0x5e2 /* interval ID should not be undefined */);
|
|
437
|
-
return `${id}`;
|
|
438
|
-
}
|
|
439
|
-
/**
|
|
440
|
-
* {@inheritDoc IInterval.union}
|
|
441
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
442
|
-
*/
|
|
443
|
-
union(b) {
|
|
444
|
-
return new SequenceInterval(this.client, (0, merge_tree_1.minReferencePosition)(this.start, b.start), (0, merge_tree_1.maxReferencePosition)(this.end, b.end), this.intervalType);
|
|
445
|
-
}
|
|
446
|
-
/**
|
|
447
|
-
* {@inheritDoc ISerializableInterval.addProperties}
|
|
448
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
449
|
-
*/
|
|
450
|
-
addProperties(newProps, collab = false, seq, op) {
|
|
451
|
-
this.initializeProperties();
|
|
452
|
-
return this.propertyManager.addProperties(this.properties, newProps, op, seq, collab);
|
|
453
|
-
}
|
|
454
|
-
/**
|
|
455
|
-
* @returns whether this interval overlaps two numerical positions.
|
|
456
|
-
*/
|
|
457
|
-
overlapsPos(bstart, bend) {
|
|
458
|
-
const startPos = this.client.localReferencePositionToPosition(this.start);
|
|
459
|
-
const endPos = this.client.localReferencePositionToPosition(this.end);
|
|
460
|
-
return endPos > bstart && startPos < bend;
|
|
461
|
-
}
|
|
462
|
-
/**
|
|
463
|
-
* {@inheritDoc IInterval.modify}
|
|
464
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
465
|
-
*/
|
|
466
|
-
modify(label, start, end, op, localSeq, stickiness = exports.IntervalStickiness.END) {
|
|
467
|
-
const getRefType = (baseType) => {
|
|
468
|
-
let refType = baseType;
|
|
469
|
-
if (op === undefined) {
|
|
470
|
-
refType &= ~merge_tree_1.ReferenceType.SlideOnRemove;
|
|
471
|
-
refType |= merge_tree_1.ReferenceType.StayOnRemove;
|
|
472
|
-
}
|
|
473
|
-
return refType;
|
|
474
|
-
};
|
|
475
|
-
let startRef = this.start;
|
|
476
|
-
if (start !== undefined) {
|
|
477
|
-
startRef = createPositionReference(this.client, start, getRefType(this.start.refType), op, undefined, localSeq, startReferenceSlidingPreference(stickiness));
|
|
478
|
-
if (this.start.properties) {
|
|
479
|
-
startRef.addProperties(this.start.properties);
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
let endRef = this.end;
|
|
483
|
-
if (end !== undefined) {
|
|
484
|
-
endRef = createPositionReference(this.client, end, getRefType(this.end.refType), op, undefined, localSeq, endReferenceSlidingPreference(stickiness));
|
|
485
|
-
if (this.end.properties) {
|
|
486
|
-
endRef.addProperties(this.end.properties);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
const newInterval = new SequenceInterval(this.client, startRef, endRef, this.intervalType);
|
|
490
|
-
if (this.properties) {
|
|
491
|
-
newInterval.initializeProperties();
|
|
492
|
-
this.propertyManager.copyTo(this.properties, newInterval.properties, newInterval.propertyManager);
|
|
493
|
-
}
|
|
494
|
-
return newInterval;
|
|
495
|
-
}
|
|
496
|
-
initializeProperties() {
|
|
497
|
-
if (!this.propertyManager) {
|
|
498
|
-
this.propertyManager = new merge_tree_1.PropertiesManager();
|
|
499
|
-
}
|
|
500
|
-
if (!this.properties) {
|
|
501
|
-
this.properties = (0, merge_tree_1.createMap)();
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
exports.SequenceInterval = SequenceInterval;
|
|
506
|
-
function createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot, slidingPreference) {
|
|
507
|
-
if (segoff.segment) {
|
|
508
|
-
const ref = client.createLocalReferencePosition(segoff.segment, segoff.offset, refType, undefined, slidingPreference);
|
|
509
|
-
return ref;
|
|
510
|
-
}
|
|
511
|
-
// Creating references on detached segments is allowed for:
|
|
512
|
-
// - Transient segments
|
|
513
|
-
// - References coming from a remote client (location may have been concurrently removed)
|
|
514
|
-
// - References being rebased to a new sequence number
|
|
515
|
-
// (segment they originally referred to may have been removed with no suitable replacement)
|
|
516
|
-
if (!op &&
|
|
517
|
-
!localSeq &&
|
|
518
|
-
!fromSnapshot &&
|
|
519
|
-
!(0, merge_tree_1.refTypeIncludesFlag)(refType, merge_tree_1.ReferenceType.Transient)) {
|
|
520
|
-
throw new container_utils_1.UsageError("Non-transient references need segment");
|
|
521
|
-
}
|
|
522
|
-
return (0, merge_tree_1.createDetachedLocalReferencePosition)(refType);
|
|
523
|
-
}
|
|
524
|
-
exports.createPositionReferenceFromSegoff = createPositionReferenceFromSegoff;
|
|
525
|
-
function createPositionReference(client, pos, refType, op, fromSnapshot, localSeq, slidingPreference) {
|
|
526
|
-
let segoff;
|
|
527
|
-
if (op) {
|
|
528
|
-
(0, common_utils_1.assert)((refType & merge_tree_1.ReferenceType.SlideOnRemove) !== 0, 0x2f5 /* op create references must be SlideOnRemove */);
|
|
529
|
-
segoff = client.getContainingSegment(pos, {
|
|
530
|
-
referenceSequenceNumber: op.referenceSequenceNumber,
|
|
531
|
-
clientId: op.clientId,
|
|
532
|
-
});
|
|
533
|
-
segoff = (0, merge_tree_1.getSlideToSegoff)(segoff);
|
|
534
|
-
}
|
|
535
|
-
else {
|
|
536
|
-
(0, common_utils_1.assert)((refType & merge_tree_1.ReferenceType.SlideOnRemove) === 0 || !!fromSnapshot, 0x2f6 /* SlideOnRemove references must be op created */);
|
|
537
|
-
segoff = client.getContainingSegment(pos, undefined, localSeq);
|
|
538
|
-
}
|
|
539
|
-
return createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot, slidingPreference);
|
|
540
|
-
}
|
|
541
|
-
function createSequenceInterval(label, start, end, client, intervalType, op, fromSnapshot, stickiness = exports.IntervalStickiness.END) {
|
|
542
|
-
let beginRefType = merge_tree_1.ReferenceType.RangeBegin;
|
|
543
|
-
let endRefType = merge_tree_1.ReferenceType.RangeEnd;
|
|
544
|
-
if (intervalType === IntervalType.Transient) {
|
|
545
|
-
beginRefType = merge_tree_1.ReferenceType.Transient;
|
|
546
|
-
endRefType = merge_tree_1.ReferenceType.Transient;
|
|
547
|
-
}
|
|
548
|
-
else {
|
|
549
|
-
if (intervalType === IntervalType.Nest) {
|
|
550
|
-
beginRefType = merge_tree_1.ReferenceType.NestBegin;
|
|
551
|
-
endRefType = merge_tree_1.ReferenceType.NestEnd;
|
|
552
|
-
}
|
|
553
|
-
// All non-transient interval references must eventually be SlideOnRemove
|
|
554
|
-
// To ensure eventual consistency, they must start as StayOnRemove when
|
|
555
|
-
// pending (created locally and creation op is not acked)
|
|
556
|
-
if (op || fromSnapshot) {
|
|
557
|
-
beginRefType |= merge_tree_1.ReferenceType.SlideOnRemove;
|
|
558
|
-
endRefType |= merge_tree_1.ReferenceType.SlideOnRemove;
|
|
559
|
-
}
|
|
560
|
-
else {
|
|
561
|
-
beginRefType |= merge_tree_1.ReferenceType.StayOnRemove;
|
|
562
|
-
endRefType |= merge_tree_1.ReferenceType.StayOnRemove;
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
const startLref = createPositionReference(client, start, beginRefType, op, fromSnapshot, undefined, startReferenceSlidingPreference(stickiness));
|
|
566
|
-
const endLref = createPositionReference(client, end, endRefType, op, fromSnapshot, undefined, endReferenceSlidingPreference(stickiness));
|
|
567
|
-
const rangeProp = {
|
|
568
|
-
[merge_tree_1.reservedRangeLabelsKey]: [label],
|
|
569
|
-
};
|
|
570
|
-
startLref.addProperties(rangeProp);
|
|
571
|
-
endLref.addProperties(rangeProp);
|
|
572
|
-
const ival = new SequenceInterval(client, startLref, endLref, intervalType, rangeProp, stickiness);
|
|
573
|
-
return ival;
|
|
574
|
-
}
|
|
575
|
-
exports.createSequenceInterval = createSequenceInterval;
|
|
576
51
|
function createIntervalIndex() {
|
|
577
52
|
const helpers = {
|
|
578
|
-
compareEnds:
|
|
579
|
-
create: createInterval,
|
|
53
|
+
compareEnds: (a, b) => a.end - b.end,
|
|
54
|
+
create: intervals_1.createInterval,
|
|
580
55
|
};
|
|
581
56
|
const lc = new LocalIntervalCollection(undefined, "", helpers);
|
|
582
57
|
return lc;
|
|
583
58
|
}
|
|
584
59
|
exports.createIntervalIndex = createIntervalIndex;
|
|
585
|
-
class IdIntervalIndex {
|
|
586
|
-
constructor() {
|
|
587
|
-
this.intervalIdMap = new Map();
|
|
588
|
-
}
|
|
589
|
-
add(interval) {
|
|
590
|
-
const id = interval.getIntervalId();
|
|
591
|
-
(0, common_utils_1.assert)(id !== undefined, 0x2c0 /* "ID must be created before adding interval to collection" */);
|
|
592
|
-
// Make the ID immutable.
|
|
593
|
-
Object.defineProperty(interval.properties, reservedIntervalIdKey, {
|
|
594
|
-
configurable: false,
|
|
595
|
-
enumerable: true,
|
|
596
|
-
writable: false,
|
|
597
|
-
});
|
|
598
|
-
this.intervalIdMap.set(id, interval);
|
|
599
|
-
}
|
|
600
|
-
remove(interval) {
|
|
601
|
-
const id = interval.getIntervalId();
|
|
602
|
-
(0, common_utils_1.assert)(id !== undefined, 0x311 /* expected id to exist on interval */);
|
|
603
|
-
this.intervalIdMap.delete(id);
|
|
604
|
-
}
|
|
605
|
-
getIntervalById(id) {
|
|
606
|
-
return this.intervalIdMap.get(id);
|
|
607
|
-
}
|
|
608
|
-
[Symbol.iterator]() {
|
|
609
|
-
return this.intervalIdMap.values();
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
class EndpointIndex {
|
|
613
|
-
constructor(client, helpers) {
|
|
614
|
-
this.client = client;
|
|
615
|
-
this.helpers = helpers;
|
|
616
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
617
|
-
this.endIntervalTree = new merge_tree_1.RedBlackTree(helpers.compareEnds);
|
|
618
|
-
}
|
|
619
|
-
previousInterval(pos) {
|
|
620
|
-
const transientInterval = this.helpers.create("transient", pos, pos, this.client, IntervalType.Transient);
|
|
621
|
-
const rbNode = this.endIntervalTree.floor(transientInterval);
|
|
622
|
-
if (rbNode) {
|
|
623
|
-
return rbNode.data;
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
nextInterval(pos) {
|
|
627
|
-
const transientInterval = this.helpers.create("transient", pos, pos, this.client, IntervalType.Transient);
|
|
628
|
-
const rbNode = this.endIntervalTree.ceil(transientInterval);
|
|
629
|
-
if (rbNode) {
|
|
630
|
-
return rbNode.data;
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
add(interval) {
|
|
634
|
-
this.endIntervalTree.put(interval, interval);
|
|
635
|
-
}
|
|
636
|
-
remove(interval) {
|
|
637
|
-
this.endIntervalTree.remove(interval);
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
/**
|
|
641
|
-
* Interface for intervals that have comparison override properties.
|
|
642
|
-
*/
|
|
643
|
-
const forceCompare = Symbol();
|
|
644
|
-
/**
|
|
645
|
-
* Compares two objects based on their comparison override properties.
|
|
646
|
-
* @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).
|
|
647
|
-
*/
|
|
648
|
-
function compareOverrideables(a, b) {
|
|
649
|
-
var _a, _b;
|
|
650
|
-
const forceCompareA = (_a = a[forceCompare]) !== null && _a !== void 0 ? _a : 0;
|
|
651
|
-
const forceCompareB = (_b = b[forceCompare]) !== null && _b !== void 0 ? _b : 0;
|
|
652
|
-
return forceCompareA - forceCompareB;
|
|
653
|
-
}
|
|
654
|
-
class EndpointInRangeIndex {
|
|
655
|
-
constructor(helpers, client) {
|
|
656
|
-
this.helpers = helpers;
|
|
657
|
-
this.client = client;
|
|
658
|
-
this.intervalTree = new merge_tree_1.RedBlackTree((a, b) => {
|
|
659
|
-
const compareEndsResult = helpers.compareEnds(a, b);
|
|
660
|
-
if (compareEndsResult !== 0) {
|
|
661
|
-
return compareEndsResult;
|
|
662
|
-
}
|
|
663
|
-
const overrideablesComparison = compareOverrideables(a, b);
|
|
664
|
-
if (overrideablesComparison !== 0) {
|
|
665
|
-
return overrideablesComparison;
|
|
666
|
-
}
|
|
667
|
-
const aId = a.getIntervalId();
|
|
668
|
-
const bId = b.getIntervalId();
|
|
669
|
-
if (aId !== undefined && bId !== undefined) {
|
|
670
|
-
return aId.localeCompare(bId);
|
|
671
|
-
}
|
|
672
|
-
return 0;
|
|
673
|
-
});
|
|
674
|
-
}
|
|
675
|
-
add(interval) {
|
|
676
|
-
this.intervalTree.put(interval, interval);
|
|
677
|
-
}
|
|
678
|
-
remove(interval) {
|
|
679
|
-
this.intervalTree.remove(interval);
|
|
680
|
-
}
|
|
681
|
-
findIntervalsWithEndpointInRange(start, end) {
|
|
682
|
-
if (start <= 0 || start > end || this.intervalTree.isEmpty()) {
|
|
683
|
-
return [];
|
|
684
|
-
}
|
|
685
|
-
const results = [];
|
|
686
|
-
const action = (node) => {
|
|
687
|
-
results.push(node.data);
|
|
688
|
-
return true;
|
|
689
|
-
};
|
|
690
|
-
const transientStartInterval = this.helpers.create("transient", start, start, this.client, IntervalType.Transient);
|
|
691
|
-
const transientEndInterval = this.helpers.create("transient", end, end, this.client, IntervalType.Transient);
|
|
692
|
-
// Add comparison overrides to the transient intervals
|
|
693
|
-
transientStartInterval[forceCompare] = -1;
|
|
694
|
-
transientEndInterval[forceCompare] = 1;
|
|
695
|
-
this.intervalTree.mapRange(action, results, transientStartInterval, transientEndInterval);
|
|
696
|
-
return results;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
class StartpointInRangeIndex {
|
|
700
|
-
constructor(helpers, client) {
|
|
701
|
-
this.helpers = helpers;
|
|
702
|
-
this.client = client;
|
|
703
|
-
this.intervalTree = new merge_tree_1.RedBlackTree((a, b) => {
|
|
704
|
-
(0, common_utils_1.assert)(typeof helpers.compareStarts === "function", 0x6d1 /* compareStarts does not exist in the helpers */);
|
|
705
|
-
const compareStartsResult = helpers.compareStarts(a, b);
|
|
706
|
-
if (compareStartsResult !== 0) {
|
|
707
|
-
return compareStartsResult;
|
|
708
|
-
}
|
|
709
|
-
const overrideablesComparison = compareOverrideables(a, b);
|
|
710
|
-
if (overrideablesComparison !== 0) {
|
|
711
|
-
return overrideablesComparison;
|
|
712
|
-
}
|
|
713
|
-
const aId = a.getIntervalId();
|
|
714
|
-
const bId = b.getIntervalId();
|
|
715
|
-
if (aId !== undefined && bId !== undefined) {
|
|
716
|
-
return aId.localeCompare(bId);
|
|
717
|
-
}
|
|
718
|
-
return 0;
|
|
719
|
-
});
|
|
720
|
-
}
|
|
721
|
-
add(interval) {
|
|
722
|
-
this.intervalTree.put(interval, interval);
|
|
723
|
-
}
|
|
724
|
-
remove(interval) {
|
|
725
|
-
this.intervalTree.remove(interval);
|
|
726
|
-
}
|
|
727
|
-
findIntervalsWithStartpointInRange(start, end) {
|
|
728
|
-
if (start <= 0 || start > end || this.intervalTree.isEmpty()) {
|
|
729
|
-
return [];
|
|
730
|
-
}
|
|
731
|
-
const results = [];
|
|
732
|
-
const action = (node) => {
|
|
733
|
-
results.push(node.data);
|
|
734
|
-
return true;
|
|
735
|
-
};
|
|
736
|
-
const transientStartInterval = this.helpers.create("transient", start, start, this.client, IntervalType.Transient);
|
|
737
|
-
const transientEndInterval = this.helpers.create("transient", end, end, this.client, IntervalType.Transient);
|
|
738
|
-
// Add comparison overrides to the transient intervals
|
|
739
|
-
transientStartInterval[forceCompare] = -1;
|
|
740
|
-
transientEndInterval[forceCompare] = 1;
|
|
741
|
-
this.intervalTree.mapRange(action, results, transientStartInterval, transientEndInterval);
|
|
742
|
-
return results;
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
function createEndpointInRangeIndex(helpers, client) {
|
|
746
|
-
return new EndpointInRangeIndex(helpers, client);
|
|
747
|
-
}
|
|
748
|
-
exports.createEndpointInRangeIndex = createEndpointInRangeIndex;
|
|
749
|
-
function createStartpointInRangeIndex(helpers, client) {
|
|
750
|
-
return new StartpointInRangeIndex(helpers, client);
|
|
751
|
-
}
|
|
752
|
-
exports.createStartpointInRangeIndex = createStartpointInRangeIndex;
|
|
753
60
|
class LocalIntervalCollection {
|
|
754
61
|
constructor(client, label, helpers,
|
|
755
62
|
/** Callback invoked each time one of the endpoints of an interval slides. */
|
|
@@ -759,8 +66,8 @@ class LocalIntervalCollection {
|
|
|
759
66
|
this.helpers = helpers;
|
|
760
67
|
this.onPositionChange = onPositionChange;
|
|
761
68
|
this.overlappingIntervalsIndex = (0, intervalIndex_1.createOverlappingIntervalsIndex)(client, helpers);
|
|
762
|
-
this.idIntervalIndex =
|
|
763
|
-
this.endIntervalIndex =
|
|
69
|
+
this.idIntervalIndex = (0, intervalIndex_1.createIdIntervalIndex)();
|
|
70
|
+
this.endIntervalIndex = (0, intervalIndex_1.createEndpointIndex)(client, helpers);
|
|
764
71
|
this.indexes = new Set([
|
|
765
72
|
this.overlappingIntervalsIndex,
|
|
766
73
|
this.idIntervalIndex,
|
|
@@ -780,8 +87,7 @@ class LocalIntervalCollection {
|
|
|
780
87
|
* @returns The interval's existing or newly created id
|
|
781
88
|
*/
|
|
782
89
|
ensureSerializedId(serializedInterval) {
|
|
783
|
-
|
|
784
|
-
let id = (_a = serializedInterval.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
|
|
90
|
+
let id = serializedInterval.properties?.[reservedIntervalIdKey];
|
|
785
91
|
if (id === undefined) {
|
|
786
92
|
// Back-compat: 0.39 and earlier did not have IDs on intervals. If an interval from such a client
|
|
787
93
|
// comes over the wire, create a non-unique one based on start/end.
|
|
@@ -815,12 +121,11 @@ class LocalIntervalCollection {
|
|
|
815
121
|
this.removeIntervalFromIndexes(interval);
|
|
816
122
|
this.removeIntervalListeners(interval);
|
|
817
123
|
}
|
|
818
|
-
createInterval(start, end, intervalType, op, stickiness =
|
|
124
|
+
createInterval(start, end, intervalType, op, stickiness = intervals_1.IntervalStickiness.END) {
|
|
819
125
|
return this.helpers.create(this.label, start, end, this.client, intervalType, op, undefined, stickiness);
|
|
820
126
|
}
|
|
821
|
-
addInterval(start, end, intervalType, props, op, stickiness =
|
|
127
|
+
addInterval(start, end, intervalType, props, op, stickiness = intervals_1.IntervalStickiness.END) {
|
|
822
128
|
var _a;
|
|
823
|
-
var _b;
|
|
824
129
|
const interval = this.createInterval(start, end, intervalType, op, stickiness);
|
|
825
130
|
if (interval) {
|
|
826
131
|
if (!interval.properties) {
|
|
@@ -836,13 +141,13 @@ class LocalIntervalCollection {
|
|
|
836
141
|
}
|
|
837
142
|
interval.addProperties(props);
|
|
838
143
|
}
|
|
839
|
-
(_a =
|
|
144
|
+
(_a = interval.properties)[reservedIntervalIdKey] ?? (_a[reservedIntervalIdKey] = (0, uuid_1.v4)());
|
|
840
145
|
this.add(interval);
|
|
841
146
|
}
|
|
842
147
|
return interval;
|
|
843
148
|
}
|
|
844
149
|
linkEndpointsToInterval(interval) {
|
|
845
|
-
if (interval instanceof SequenceInterval) {
|
|
150
|
+
if (interval instanceof intervals_1.SequenceInterval) {
|
|
846
151
|
interval.start.addProperties({ interval });
|
|
847
152
|
interval.end.addProperties({ interval });
|
|
848
153
|
}
|
|
@@ -883,7 +188,7 @@ class LocalIntervalCollection {
|
|
|
883
188
|
}
|
|
884
189
|
return this.client.createLocalReferencePosition(segment, ref.getOffset(), merge_tree_1.ReferenceType.Transient, ref.properties, ref.slidingPreference);
|
|
885
190
|
};
|
|
886
|
-
if (interval instanceof SequenceInterval) {
|
|
191
|
+
if (interval instanceof intervals_1.SequenceInterval) {
|
|
887
192
|
let previousInterval;
|
|
888
193
|
let pendingChanges = 0;
|
|
889
194
|
interval.addPositionChangeListeners(() => {
|
|
@@ -896,42 +201,27 @@ class LocalIntervalCollection {
|
|
|
896
201
|
this.removeIntervalFromIndexes(interval);
|
|
897
202
|
}
|
|
898
203
|
}, () => {
|
|
899
|
-
|
|
900
|
-
(0, common_utils_1.assert)(previousInterval !== undefined, 0x3fa /* Invalid interleaving of before/after slide */);
|
|
204
|
+
(0, core_utils_1.assert)(previousInterval !== undefined, 0x3fa /* Invalid interleaving of before/after slide */);
|
|
901
205
|
pendingChanges--;
|
|
902
206
|
if (pendingChanges === 0) {
|
|
903
207
|
this.addIntervalToIndexes(interval);
|
|
904
|
-
|
|
208
|
+
this.onPositionChange?.(interval, previousInterval);
|
|
905
209
|
previousInterval = undefined;
|
|
906
210
|
}
|
|
907
211
|
});
|
|
908
212
|
}
|
|
909
213
|
}
|
|
910
214
|
removeIntervalListeners(interval) {
|
|
911
|
-
if (interval instanceof SequenceInterval) {
|
|
215
|
+
if (interval instanceof intervals_1.SequenceInterval) {
|
|
912
216
|
interval.removePositionChangeListeners();
|
|
913
217
|
}
|
|
914
218
|
}
|
|
915
219
|
}
|
|
916
220
|
exports.LocalIntervalCollection = LocalIntervalCollection;
|
|
917
221
|
LocalIntervalCollection.legacyIdPrefix = "legacy";
|
|
918
|
-
const compareSequenceIntervalEnds = (a, b) => (0, merge_tree_1.compareReferencePositions)(a.end, b.end);
|
|
919
|
-
exports.compareSequenceIntervalEnds = compareSequenceIntervalEnds;
|
|
920
|
-
const compareSequenceIntervalStarts = (a, b) => (0, merge_tree_1.compareReferencePositions)(a.start, b.start);
|
|
921
|
-
exports.compareSequenceIntervalStarts = compareSequenceIntervalStarts;
|
|
922
|
-
exports.sequenceIntervalHelpers = {
|
|
923
|
-
compareEnds: exports.compareSequenceIntervalEnds,
|
|
924
|
-
compareStarts: exports.compareSequenceIntervalStarts,
|
|
925
|
-
create: createSequenceInterval,
|
|
926
|
-
};
|
|
927
|
-
exports.intervalHelpers = {
|
|
928
|
-
compareEnds: (a, b) => a.end - b.end,
|
|
929
|
-
compareStarts: (a, b) => a.start - b.start,
|
|
930
|
-
create: createInterval,
|
|
931
|
-
};
|
|
932
222
|
class SequenceIntervalCollectionFactory {
|
|
933
223
|
load(emitter, raw = [], options) {
|
|
934
|
-
return new IntervalCollection(
|
|
224
|
+
return new IntervalCollection(intervals_1.sequenceIntervalHelpers, true, emitter, raw, options);
|
|
935
225
|
}
|
|
936
226
|
store(value) {
|
|
937
227
|
return value.serializeInternal();
|
|
@@ -952,19 +242,11 @@ exports.SequenceIntervalCollectionValueType = SequenceIntervalCollectionValueTyp
|
|
|
952
242
|
SequenceIntervalCollectionValueType.Name = "sharedStringIntervalCollection";
|
|
953
243
|
SequenceIntervalCollectionValueType._factory = new SequenceIntervalCollectionFactory();
|
|
954
244
|
SequenceIntervalCollectionValueType._ops = makeOpsMap();
|
|
955
|
-
const compareIntervalEnds = (a, b) => a.end - b.end;
|
|
956
|
-
function createInterval(label, start, end, client, intervalType, op, fromSnapshot) {
|
|
957
|
-
const rangeProp = {};
|
|
958
|
-
if (label && label.length > 0) {
|
|
959
|
-
rangeProp[merge_tree_1.reservedRangeLabelsKey] = [label];
|
|
960
|
-
}
|
|
961
|
-
return new Interval(start, end, rangeProp);
|
|
962
|
-
}
|
|
963
245
|
class IntervalCollectionFactory {
|
|
964
246
|
load(emitter, raw = [], options) {
|
|
965
247
|
const helpers = {
|
|
966
|
-
compareEnds:
|
|
967
|
-
create: createInterval,
|
|
248
|
+
compareEnds: (a, b) => a.end - b.end,
|
|
249
|
+
create: intervals_1.createInterval,
|
|
968
250
|
};
|
|
969
251
|
const collection = new IntervalCollection(helpers, false, emitter, raw, options);
|
|
970
252
|
collection.attachGraph(undefined, "");
|
|
@@ -993,12 +275,12 @@ function makeOpsMap() {
|
|
|
993
275
|
const rebase = (collection, op, localOpMetadata) => {
|
|
994
276
|
const { localSeq } = localOpMetadata;
|
|
995
277
|
const rebasedValue = collection.rebaseLocalInterval(op.opName, op.value, localSeq);
|
|
996
|
-
const rebasedOp =
|
|
278
|
+
const rebasedOp = { ...op, value: rebasedValue };
|
|
997
279
|
return { rebasedOp, rebasedLocalOpMetadata: localOpMetadata };
|
|
998
280
|
};
|
|
999
281
|
return new Map([
|
|
1000
282
|
[
|
|
1001
|
-
|
|
283
|
+
intervals_1.IntervalOpType.ADD,
|
|
1002
284
|
{
|
|
1003
285
|
process: (collection, params, local, op, localOpMetadata) => {
|
|
1004
286
|
// if params is undefined, the interval was deleted during
|
|
@@ -1006,17 +288,17 @@ function makeOpsMap() {
|
|
|
1006
288
|
if (!params) {
|
|
1007
289
|
return;
|
|
1008
290
|
}
|
|
1009
|
-
(0,
|
|
291
|
+
(0, core_utils_1.assert)(op !== undefined, 0x3fb /* op should exist here */);
|
|
1010
292
|
collection.ackAdd(params, local, op, localOpMetadata);
|
|
1011
293
|
},
|
|
1012
294
|
rebase,
|
|
1013
295
|
},
|
|
1014
296
|
],
|
|
1015
297
|
[
|
|
1016
|
-
|
|
298
|
+
intervals_1.IntervalOpType.DELETE,
|
|
1017
299
|
{
|
|
1018
300
|
process: (collection, params, local, op) => {
|
|
1019
|
-
(0,
|
|
301
|
+
(0, core_utils_1.assert)(op !== undefined, 0x3fc /* op should exist here */);
|
|
1020
302
|
collection.ackDelete(params, local, op);
|
|
1021
303
|
},
|
|
1022
304
|
rebase: (collection, op, localOpMetadata) => {
|
|
@@ -1026,7 +308,7 @@ function makeOpsMap() {
|
|
|
1026
308
|
},
|
|
1027
309
|
],
|
|
1028
310
|
[
|
|
1029
|
-
|
|
311
|
+
intervals_1.IntervalOpType.CHANGE,
|
|
1030
312
|
{
|
|
1031
313
|
process: (collection, params, local, op, localOpMetadata) => {
|
|
1032
314
|
// if params is undefined, the interval was deleted during
|
|
@@ -1034,7 +316,7 @@ function makeOpsMap() {
|
|
|
1034
316
|
if (!params) {
|
|
1035
317
|
return;
|
|
1036
318
|
}
|
|
1037
|
-
(0,
|
|
319
|
+
(0, core_utils_1.assert)(op !== undefined, 0x3fd /* op should exist here */);
|
|
1038
320
|
collection.ackChange(params, local, op, localOpMetadata);
|
|
1039
321
|
},
|
|
1040
322
|
rebase,
|
|
@@ -1065,7 +347,7 @@ class IntervalCollectionIterator {
|
|
|
1065
347
|
/**
|
|
1066
348
|
* {@inheritdoc IIntervalCollection}
|
|
1067
349
|
*/
|
|
1068
|
-
class IntervalCollection extends
|
|
350
|
+
class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
1069
351
|
/** @internal */
|
|
1070
352
|
constructor(helpers, requiresClient, emitter, serializedIntervals, options = {}) {
|
|
1071
353
|
super();
|
|
@@ -1088,25 +370,23 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1088
370
|
* {@inheritdoc IIntervalCollection.attachIndex}
|
|
1089
371
|
*/
|
|
1090
372
|
attachIndex(index) {
|
|
1091
|
-
var _a;
|
|
1092
373
|
if (!this.attached) {
|
|
1093
374
|
throw new telemetry_utils_1.LoggingError("The local interval collection must exist");
|
|
1094
375
|
}
|
|
1095
376
|
for (const interval of this) {
|
|
1096
377
|
index.add(interval);
|
|
1097
378
|
}
|
|
1098
|
-
|
|
379
|
+
this.localCollection?.appendIndex(index);
|
|
1099
380
|
}
|
|
1100
381
|
/**
|
|
1101
382
|
* {@inheritdoc IIntervalCollection.detachIndex}
|
|
1102
383
|
*/
|
|
1103
384
|
detachIndex(index) {
|
|
1104
|
-
var _a;
|
|
1105
385
|
if (!this.attached) {
|
|
1106
386
|
throw new telemetry_utils_1.LoggingError("The local interval collection must exist");
|
|
1107
387
|
}
|
|
1108
388
|
// Avoid removing intervals if the index does not exist
|
|
1109
|
-
if (!
|
|
389
|
+
if (!this.localCollection?.removeIndex(index)) {
|
|
1110
390
|
return false;
|
|
1111
391
|
}
|
|
1112
392
|
for (const interval of this) {
|
|
@@ -1115,7 +395,6 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1115
395
|
return true;
|
|
1116
396
|
}
|
|
1117
397
|
rebasePositionWithSegmentSlide(pos, seqNumberFrom, localSeq) {
|
|
1118
|
-
var _a;
|
|
1119
398
|
if (!this.client) {
|
|
1120
399
|
throw new telemetry_utils_1.LoggingError("mergeTree client must exist");
|
|
1121
400
|
}
|
|
@@ -1125,20 +404,20 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1125
404
|
clientId: this.client.getLongClientId(clientId),
|
|
1126
405
|
}, localSeq);
|
|
1127
406
|
// if segment is undefined, it slid off the string
|
|
1128
|
-
(0,
|
|
1129
|
-
const segoff = (
|
|
407
|
+
(0, core_utils_1.assert)(segment !== undefined, 0x54e /* No segment found */);
|
|
408
|
+
const segoff = (0, merge_tree_1.getSlideToSegoff)({ segment, offset }) ?? segment;
|
|
1130
409
|
// case happens when rebasing op, but concurrently entire string has been deleted
|
|
1131
410
|
if (segoff.segment === undefined || segoff.offset === undefined) {
|
|
1132
411
|
return merge_tree_1.DetachedReferencePosition;
|
|
1133
412
|
}
|
|
1134
|
-
(0,
|
|
413
|
+
(0, core_utils_1.assert)(offset !== undefined && 0 <= offset && offset < segment.cachedLength, 0x54f /* Invalid offset */);
|
|
1135
414
|
return this.client.findReconnectionPosition(segoff.segment, localSeq) + segoff.offset;
|
|
1136
415
|
}
|
|
1137
416
|
computeRebasedPositions(localSeq) {
|
|
1138
|
-
(0,
|
|
417
|
+
(0, core_utils_1.assert)(this.client !== undefined, 0x550 /* Client should be defined when computing rebased position */);
|
|
1139
418
|
const original = this.localSeqToSerializedInterval.get(localSeq);
|
|
1140
|
-
(0,
|
|
1141
|
-
const rebased =
|
|
419
|
+
(0, core_utils_1.assert)(original !== undefined, 0x551 /* Failed to store pending serialized interval info for this localSeq. */);
|
|
420
|
+
const rebased = { ...original };
|
|
1142
421
|
const { start, end, sequenceNumber } = original;
|
|
1143
422
|
if (start !== undefined) {
|
|
1144
423
|
rebased.start = this.rebasePositionWithSegmentSlide(start, sequenceNumber, localSeq);
|
|
@@ -1194,7 +473,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1194
473
|
// is restored as single-endpoint changes re-use previous references.
|
|
1195
474
|
let startRefType;
|
|
1196
475
|
let endRefType;
|
|
1197
|
-
if (previousInterval instanceof SequenceInterval) {
|
|
476
|
+
if (previousInterval instanceof intervals_1.SequenceInterval) {
|
|
1198
477
|
startRefType = previousInterval.start.refType;
|
|
1199
478
|
endRefType = previousInterval.end.refType;
|
|
1200
479
|
previousInterval.start.refType = merge_tree_1.ReferenceType.Transient;
|
|
@@ -1219,16 +498,15 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1219
498
|
/**
|
|
1220
499
|
* {@inheritdoc IIntervalCollection.add}
|
|
1221
500
|
*/
|
|
1222
|
-
add(start, end, intervalType, props, stickiness =
|
|
1223
|
-
var _a, _b;
|
|
501
|
+
add(start, end, intervalType, props, stickiness = intervals_1.IntervalStickiness.END) {
|
|
1224
502
|
if (!this.localCollection) {
|
|
1225
503
|
throw new telemetry_utils_1.LoggingError("attach must be called prior to adding intervals");
|
|
1226
504
|
}
|
|
1227
|
-
if (intervalType & IntervalType.Transient) {
|
|
505
|
+
if (intervalType & intervals_1.IntervalType.Transient) {
|
|
1228
506
|
throw new telemetry_utils_1.LoggingError("Can not add transient intervals");
|
|
1229
507
|
}
|
|
1230
|
-
if (stickiness !==
|
|
1231
|
-
throw new
|
|
508
|
+
if (stickiness !== intervals_1.IntervalStickiness.END && !this.options.intervalStickinessEnabled) {
|
|
509
|
+
throw new telemetry_utils_1.UsageError("attempted to set interval stickiness without enabling `intervalStickinessEnabled` feature flag");
|
|
1232
510
|
}
|
|
1233
511
|
const interval = this.localCollection.addInterval(start, end, intervalType, props, undefined, stickiness);
|
|
1234
512
|
if (interval) {
|
|
@@ -1236,7 +514,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1236
514
|
end,
|
|
1237
515
|
intervalType,
|
|
1238
516
|
properties: interval.properties,
|
|
1239
|
-
sequenceNumber:
|
|
517
|
+
sequenceNumber: this.client?.getCurrentSeq() ?? 0,
|
|
1240
518
|
start,
|
|
1241
519
|
stickiness,
|
|
1242
520
|
};
|
|
@@ -1368,9 +646,8 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1368
646
|
entries.push(serializedInterval);
|
|
1369
647
|
}
|
|
1370
648
|
removePendingChange(serializedInterval) {
|
|
1371
|
-
var _a;
|
|
1372
649
|
// Change ops always have an ID.
|
|
1373
|
-
const id =
|
|
650
|
+
const id = serializedInterval.properties?.[reservedIntervalIdKey];
|
|
1374
651
|
if (serializedInterval.start !== undefined) {
|
|
1375
652
|
this.removePendingChangeHelper(id, this.pendingChangesStart, serializedInterval);
|
|
1376
653
|
}
|
|
@@ -1385,8 +662,8 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1385
662
|
if (entries.length === 0) {
|
|
1386
663
|
pendingChanges.delete(id);
|
|
1387
664
|
}
|
|
1388
|
-
if (
|
|
1389
|
-
|
|
665
|
+
if (pendingChange?.start !== serializedInterval.start ||
|
|
666
|
+
pendingChange?.end !== serializedInterval.end) {
|
|
1390
667
|
throw new telemetry_utils_1.LoggingError("Mismatch in pending changes");
|
|
1391
668
|
}
|
|
1392
669
|
}
|
|
@@ -1401,21 +678,20 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1401
678
|
}
|
|
1402
679
|
/** @internal */
|
|
1403
680
|
ackChange(serializedInterval, local, op, localOpMetadata) {
|
|
1404
|
-
var _a, _b, _c, _d;
|
|
1405
681
|
if (!this.localCollection) {
|
|
1406
682
|
throw new telemetry_utils_1.LoggingError("Attach must be called before accessing intervals");
|
|
1407
683
|
}
|
|
1408
684
|
if (local) {
|
|
1409
|
-
(0,
|
|
1410
|
-
this.localSeqToSerializedInterval.delete(localOpMetadata
|
|
685
|
+
(0, core_utils_1.assert)(localOpMetadata !== undefined, 0x552 /* op metadata should be defined for local op */);
|
|
686
|
+
this.localSeqToSerializedInterval.delete(localOpMetadata?.localSeq);
|
|
1411
687
|
// This is an ack from the server. Remove the pending change.
|
|
1412
688
|
this.removePendingChange(serializedInterval);
|
|
1413
689
|
}
|
|
1414
690
|
// Note that the ID is in the property bag only to allow us to find the interval.
|
|
1415
691
|
// This API cannot change the ID, and writing to the ID property will result in an exception. So we
|
|
1416
692
|
// strip it out of the properties here.
|
|
1417
|
-
const
|
|
1418
|
-
(0,
|
|
693
|
+
const { [reservedIntervalIdKey]: id, ...newProps } = serializedInterval.properties ?? {};
|
|
694
|
+
(0, core_utils_1.assert)(id !== undefined, 0x3fe /* id must exist on the interval */);
|
|
1419
695
|
const interval = this.getIntervalById(id);
|
|
1420
696
|
if (!interval) {
|
|
1421
697
|
// The interval has been removed locally; no-op.
|
|
@@ -1423,9 +699,9 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1423
699
|
}
|
|
1424
700
|
if (local) {
|
|
1425
701
|
// Let the propertyManager prune its pending change-properties set.
|
|
1426
|
-
|
|
702
|
+
interval.propertyManager?.ackPendingProperties({
|
|
1427
703
|
type: merge_tree_1.MergeTreeDeltaType.ANNOTATE,
|
|
1428
|
-
props:
|
|
704
|
+
props: serializedInterval.properties ?? {},
|
|
1429
705
|
});
|
|
1430
706
|
this.ackInterval(interval, op);
|
|
1431
707
|
}
|
|
@@ -1446,7 +722,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1446
722
|
// If changeInterval gives us a new interval, work with that one. Otherwise keep working with
|
|
1447
723
|
// the one we originally found in the tree.
|
|
1448
724
|
newInterval =
|
|
1449
|
-
|
|
725
|
+
this.localCollection.changeInterval(interval, start, end, op) ?? interval;
|
|
1450
726
|
}
|
|
1451
727
|
const deltaProps = newInterval.addProperties(newProps, true, op.sequenceNumber);
|
|
1452
728
|
if (this.onDeserialize) {
|
|
@@ -1461,18 +737,6 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1461
737
|
}
|
|
1462
738
|
}
|
|
1463
739
|
}
|
|
1464
|
-
/**
|
|
1465
|
-
* @deprecated - This functionality was useful when adding two intervals at the same start/end positions resulted
|
|
1466
|
-
* in a conflict. This is no longer the case (as of PR#6407), as interval collections support multiple intervals
|
|
1467
|
-
* at the same location and gives each interval a unique id.
|
|
1468
|
-
*
|
|
1469
|
-
* As such, the conflict resolver is never invoked and unnecessary. This API will be removed in an upcoming release.
|
|
1470
|
-
*/
|
|
1471
|
-
addConflictResolver(_) {
|
|
1472
|
-
if (!this.localCollection) {
|
|
1473
|
-
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
1474
|
-
}
|
|
1475
|
-
}
|
|
1476
740
|
/**
|
|
1477
741
|
* {@inheritdoc IIntervalCollection.attachDeserializer}
|
|
1478
742
|
*/
|
|
@@ -1496,7 +760,6 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1496
760
|
* @internal
|
|
1497
761
|
*/
|
|
1498
762
|
rebaseLocalInterval(opName, serializedInterval, localSeq) {
|
|
1499
|
-
var _a, _b, _c, _d, _e, _f;
|
|
1500
763
|
if (!this.client) {
|
|
1501
764
|
// If there's no associated mergeTree client, the originally submitted op is still correct.
|
|
1502
765
|
return serializedInterval;
|
|
@@ -1505,14 +768,14 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1505
768
|
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
1506
769
|
}
|
|
1507
770
|
const { intervalType, properties } = serializedInterval;
|
|
1508
|
-
const { start: startRebased, end: endRebased } =
|
|
1509
|
-
const intervalId = properties
|
|
1510
|
-
const localInterval =
|
|
771
|
+
const { start: startRebased, end: endRebased } = this.localSeqToRebasedInterval.get(localSeq) ?? this.computeRebasedPositions(localSeq);
|
|
772
|
+
const intervalId = properties?.[reservedIntervalIdKey];
|
|
773
|
+
const localInterval = this.localCollection?.idIntervalIndex.getIntervalById(intervalId);
|
|
1511
774
|
const rebased = {
|
|
1512
775
|
start: startRebased,
|
|
1513
776
|
end: endRebased,
|
|
1514
777
|
intervalType,
|
|
1515
|
-
sequenceNumber:
|
|
778
|
+
sequenceNumber: this.client?.getCurrentSeq() ?? 0,
|
|
1516
779
|
properties,
|
|
1517
780
|
};
|
|
1518
781
|
if (opName === "change" &&
|
|
@@ -1524,26 +787,25 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1524
787
|
if (startRebased === merge_tree_1.DetachedReferencePosition ||
|
|
1525
788
|
endRebased === merge_tree_1.DetachedReferencePosition) {
|
|
1526
789
|
if (localInterval) {
|
|
1527
|
-
|
|
790
|
+
this.localCollection?.removeExistingInterval(localInterval);
|
|
1528
791
|
}
|
|
1529
792
|
return undefined;
|
|
1530
793
|
}
|
|
1531
794
|
if (localInterval !== undefined) {
|
|
1532
795
|
// we know we must be using `SequenceInterval` because `this.client` exists
|
|
1533
|
-
(0,
|
|
796
|
+
(0, core_utils_1.assert)(localInterval instanceof intervals_1.SequenceInterval, 0x3a0 /* localInterval must be `SequenceInterval` when used with client */);
|
|
1534
797
|
// The rebased op may place this interval's endpoints on different segments. Calling `changeInterval` here
|
|
1535
798
|
// updates the local client's state to be consistent with the emitted op.
|
|
1536
|
-
|
|
799
|
+
this.localCollection?.changeInterval(localInterval, startRebased, endRebased, undefined, localSeq);
|
|
1537
800
|
}
|
|
1538
801
|
return rebased;
|
|
1539
802
|
}
|
|
1540
803
|
getSlideToSegment(lref) {
|
|
1541
|
-
var _a, _b;
|
|
1542
804
|
if (!this.client) {
|
|
1543
805
|
throw new telemetry_utils_1.LoggingError("client does not exist");
|
|
1544
806
|
}
|
|
1545
807
|
const segoff = { segment: lref.getSegment(), offset: lref.getOffset() };
|
|
1546
|
-
if (
|
|
808
|
+
if (segoff.segment?.localRefs?.has(lref) !== true) {
|
|
1547
809
|
return undefined;
|
|
1548
810
|
}
|
|
1549
811
|
const newSegoff = (0, merge_tree_1.getSlideToSegoff)(segoff);
|
|
@@ -1559,9 +821,8 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1559
821
|
lref.refType = refType;
|
|
1560
822
|
}
|
|
1561
823
|
ackInterval(interval, op) {
|
|
1562
|
-
var _a, _b;
|
|
1563
824
|
// Only SequenceIntervals need potential sliding
|
|
1564
|
-
if (!(interval instanceof SequenceInterval)) {
|
|
825
|
+
if (!(interval instanceof intervals_1.SequenceInterval)) {
|
|
1565
826
|
return;
|
|
1566
827
|
}
|
|
1567
828
|
if (!(0, merge_tree_1.refTypeIncludesFlag)(interval.start, merge_tree_1.ReferenceType.StayOnRemove) &&
|
|
@@ -1596,7 +857,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1596
857
|
}
|
|
1597
858
|
if (needsStartUpdate) {
|
|
1598
859
|
const props = interval.start.properties;
|
|
1599
|
-
interval.start = createPositionReferenceFromSegoff(this.client, newStart, interval.start.refType, op, startReferenceSlidingPreference(interval.stickiness));
|
|
860
|
+
interval.start = (0, intervals_1.createPositionReferenceFromSegoff)(this.client, newStart, interval.start.refType, op, (0, intervals_1.startReferenceSlidingPreference)(interval.stickiness));
|
|
1600
861
|
if (props) {
|
|
1601
862
|
interval.start.addProperties(props);
|
|
1602
863
|
}
|
|
@@ -1604,11 +865,11 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1604
865
|
// remove and rebuild start interval as transient for event
|
|
1605
866
|
this.client.removeLocalReferencePosition(oldInterval.start);
|
|
1606
867
|
oldInterval.start.refType = merge_tree_1.ReferenceType.Transient;
|
|
1607
|
-
|
|
868
|
+
oldSeg?.localRefs?.addLocalRef(oldInterval.start, oldInterval.start.getOffset());
|
|
1608
869
|
}
|
|
1609
870
|
if (needsEndUpdate) {
|
|
1610
871
|
const props = interval.end.properties;
|
|
1611
|
-
interval.end = createPositionReferenceFromSegoff(this.client, newEnd, interval.end.refType, op, endReferenceSlidingPreference(interval.stickiness));
|
|
872
|
+
interval.end = (0, intervals_1.createPositionReferenceFromSegoff)(this.client, newEnd, interval.end.refType, op, (0, intervals_1.endReferenceSlidingPreference)(interval.stickiness));
|
|
1612
873
|
if (props) {
|
|
1613
874
|
interval.end.addProperties(props);
|
|
1614
875
|
}
|
|
@@ -1616,7 +877,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1616
877
|
const oldSeg = oldInterval.end.getSegment();
|
|
1617
878
|
this.client.removeLocalReferencePosition(oldInterval.end);
|
|
1618
879
|
oldInterval.end.refType = merge_tree_1.ReferenceType.Transient;
|
|
1619
|
-
|
|
880
|
+
oldSeg?.localRefs?.addLocalRef(oldInterval.end, oldInterval.end.getOffset());
|
|
1620
881
|
}
|
|
1621
882
|
this.localCollection.add(interval);
|
|
1622
883
|
this.emitChange(interval, oldInterval, true, true, op);
|
|
@@ -1624,11 +885,10 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1624
885
|
}
|
|
1625
886
|
/** @internal */
|
|
1626
887
|
ackAdd(serializedInterval, local, op, localOpMetadata) {
|
|
1627
|
-
var _a;
|
|
1628
888
|
if (local) {
|
|
1629
|
-
(0,
|
|
889
|
+
(0, core_utils_1.assert)(localOpMetadata !== undefined, 0x553 /* op metadata should be defined for local op */);
|
|
1630
890
|
this.localSeqToSerializedInterval.delete(localOpMetadata.localSeq);
|
|
1631
|
-
const id =
|
|
891
|
+
const id = serializedInterval.properties?.[reservedIntervalIdKey];
|
|
1632
892
|
const localInterval = this.getIntervalById(id);
|
|
1633
893
|
if (localInterval) {
|
|
1634
894
|
this.ackInterval(localInterval, op);
|
|
@@ -1765,9 +1025,8 @@ exports.IntervalCollection = IntervalCollection;
|
|
|
1765
1025
|
* endpoint is a part of.
|
|
1766
1026
|
*/
|
|
1767
1027
|
function intervalLocatorFromEndpoint(potentialEndpoint) {
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
return interval && (collectionNameArray === null || collectionNameArray === void 0 ? void 0 : collectionNameArray.length) === 1
|
|
1028
|
+
const { interval, [merge_tree_1.reservedRangeLabelsKey]: collectionNameArray } = potentialEndpoint.properties ?? {};
|
|
1029
|
+
return interval && collectionNameArray?.length === 1
|
|
1771
1030
|
? { label: collectionNameArray[0], interval }
|
|
1772
1031
|
: undefined;
|
|
1773
1032
|
}
|