@fluidframework/sequence 2.0.0-dev.5.2.0.169897 → 2.0.0-dev.6.4.0.191258
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 +142 -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 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -9
- package/dist/index.js.map +1 -1
- package/dist/intervalCollection.d.ts +14 -437
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalCollection.js +96 -916
- 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 +13 -0
- package/dist/intervalIndex/index.d.ts.map +1 -0
- package/dist/intervalIndex/index.js +20 -0
- package/dist/intervalIndex/index.js.map +1 -0
- 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 +33 -0
- package/dist/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -0
- package/dist/intervalIndex/overlappingIntervalsIndex.js +103 -0
- package/dist/intervalIndex/overlappingIntervalsIndex.js.map +1 -0
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.d.ts +8 -0
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.d.ts.map +1 -0
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js +33 -0
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js.map +1 -0
- package/dist/intervalIndex/sequenceIntervalIndexes.d.ts +33 -0
- package/dist/intervalIndex/sequenceIntervalIndexes.d.ts.map +1 -0
- package/dist/intervalIndex/sequenceIntervalIndexes.js +7 -0
- package/dist/intervalIndex/sequenceIntervalIndexes.js.map +1 -0
- 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 +85 -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 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -1
- package/lib/index.js.map +1 -1
- package/lib/intervalCollection.d.ts +14 -437
- package/lib/intervalCollection.d.ts.map +1 -1
- package/lib/intervalCollection.js +64 -877
- 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 +13 -0
- package/lib/intervalIndex/index.d.ts.map +1 -0
- package/lib/intervalIndex/index.js +11 -0
- package/lib/intervalIndex/index.js.map +1 -0
- 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 +33 -0
- package/lib/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -0
- package/lib/intervalIndex/overlappingIntervalsIndex.js +98 -0
- package/lib/intervalIndex/overlappingIntervalsIndex.js.map +1 -0
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.d.ts +8 -0
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.d.ts.map +1 -0
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js +29 -0
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js.map +1 -0
- package/lib/intervalIndex/sequenceIntervalIndexes.d.ts +33 -0
- package/lib/intervalIndex/sequenceIntervalIndexes.d.ts.map +1 -0
- package/lib/intervalIndex/sequenceIntervalIndexes.js +6 -0
- package/lib/intervalIndex/sequenceIntervalIndexes.js.map +1 -0
- 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 +69 -36
- 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 +31 -34
- package/src/defaultMap.ts +2 -1
- package/src/defaultMapInterfaces.ts +1 -1
- package/src/index.ts +21 -9
- package/src/intervalCollection.ts +118 -1403
- 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 +16 -0
- package/src/intervalIndex/intervalIndex.ts +31 -0
- package/src/intervalIndex/intervalIndexUtils.ts +27 -0
- package/src/intervalIndex/overlappingIntervalsIndex.ts +162 -0
- package/src/intervalIndex/overlappingSequenceIntervalsIndex.ts +71 -0
- package/src/intervalIndex/sequenceIntervalIndexes.ts +32 -0
- 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 +81 -16
- 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");
|
|
25
|
-
const
|
|
14
|
+
const intervals_1 = require("./intervals");
|
|
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,770 +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
|
-
function createPositionReference(client, pos, refType, op, fromSnapshot, localSeq, slidingPreference) {
|
|
525
|
-
let segoff;
|
|
526
|
-
if (op) {
|
|
527
|
-
(0, common_utils_1.assert)((refType & merge_tree_1.ReferenceType.SlideOnRemove) !== 0, 0x2f5 /* op create references must be SlideOnRemove */);
|
|
528
|
-
segoff = client.getContainingSegment(pos, {
|
|
529
|
-
referenceSequenceNumber: op.referenceSequenceNumber,
|
|
530
|
-
clientId: op.clientId,
|
|
531
|
-
});
|
|
532
|
-
segoff = client.getSlideToSegment(segoff);
|
|
533
|
-
}
|
|
534
|
-
else {
|
|
535
|
-
(0, common_utils_1.assert)((refType & merge_tree_1.ReferenceType.SlideOnRemove) === 0 || !!fromSnapshot, 0x2f6 /* SlideOnRemove references must be op created */);
|
|
536
|
-
segoff = client.getContainingSegment(pos, undefined, localSeq);
|
|
537
|
-
}
|
|
538
|
-
return createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot, slidingPreference);
|
|
539
|
-
}
|
|
540
|
-
function createSequenceInterval(label, start, end, client, intervalType, op, fromSnapshot, stickiness = exports.IntervalStickiness.END) {
|
|
541
|
-
let beginRefType = merge_tree_1.ReferenceType.RangeBegin;
|
|
542
|
-
let endRefType = merge_tree_1.ReferenceType.RangeEnd;
|
|
543
|
-
if (intervalType === IntervalType.Transient) {
|
|
544
|
-
beginRefType = merge_tree_1.ReferenceType.Transient;
|
|
545
|
-
endRefType = merge_tree_1.ReferenceType.Transient;
|
|
546
|
-
}
|
|
547
|
-
else {
|
|
548
|
-
if (intervalType === IntervalType.Nest) {
|
|
549
|
-
beginRefType = merge_tree_1.ReferenceType.NestBegin;
|
|
550
|
-
endRefType = merge_tree_1.ReferenceType.NestEnd;
|
|
551
|
-
}
|
|
552
|
-
// All non-transient interval references must eventually be SlideOnRemove
|
|
553
|
-
// To ensure eventual consistency, they must start as StayOnRemove when
|
|
554
|
-
// pending (created locally and creation op is not acked)
|
|
555
|
-
if (op || fromSnapshot) {
|
|
556
|
-
beginRefType |= merge_tree_1.ReferenceType.SlideOnRemove;
|
|
557
|
-
endRefType |= merge_tree_1.ReferenceType.SlideOnRemove;
|
|
558
|
-
}
|
|
559
|
-
else {
|
|
560
|
-
beginRefType |= merge_tree_1.ReferenceType.StayOnRemove;
|
|
561
|
-
endRefType |= merge_tree_1.ReferenceType.StayOnRemove;
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
const startLref = createPositionReference(client, start, beginRefType, op, fromSnapshot, undefined, startReferenceSlidingPreference(stickiness));
|
|
565
|
-
const endLref = createPositionReference(client, end, endRefType, op, fromSnapshot, undefined, endReferenceSlidingPreference(stickiness));
|
|
566
|
-
const rangeProp = {
|
|
567
|
-
[merge_tree_1.reservedRangeLabelsKey]: [label],
|
|
568
|
-
};
|
|
569
|
-
startLref.addProperties(rangeProp);
|
|
570
|
-
endLref.addProperties(rangeProp);
|
|
571
|
-
const ival = new SequenceInterval(client, startLref, endLref, intervalType, rangeProp, stickiness);
|
|
572
|
-
return ival;
|
|
573
|
-
}
|
|
574
|
-
exports.createSequenceInterval = createSequenceInterval;
|
|
575
51
|
function createIntervalIndex() {
|
|
576
52
|
const helpers = {
|
|
577
|
-
compareEnds:
|
|
578
|
-
create: createInterval,
|
|
53
|
+
compareEnds: (a, b) => a.end - b.end,
|
|
54
|
+
create: intervals_1.createInterval,
|
|
579
55
|
};
|
|
580
56
|
const lc = new LocalIntervalCollection(undefined, "", helpers);
|
|
581
57
|
return lc;
|
|
582
58
|
}
|
|
583
59
|
exports.createIntervalIndex = createIntervalIndex;
|
|
584
|
-
class OverlappingIntervalsIndex {
|
|
585
|
-
constructor(client, helpers) {
|
|
586
|
-
this.client = client;
|
|
587
|
-
this.helpers = helpers;
|
|
588
|
-
this.intervalTree = new intervalTree_1.IntervalTree();
|
|
589
|
-
}
|
|
590
|
-
map(fn) {
|
|
591
|
-
this.intervalTree.map(fn);
|
|
592
|
-
}
|
|
593
|
-
mapUntil(fn) {
|
|
594
|
-
this.intervalTree.mapUntil(fn);
|
|
595
|
-
}
|
|
596
|
-
gatherIterationResults(results, iteratesForward, start, end) {
|
|
597
|
-
if (this.intervalTree.intervals.isEmpty()) {
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
if (start === undefined && end === undefined) {
|
|
601
|
-
// No start/end provided. Gather the whole tree in the specified order.
|
|
602
|
-
if (iteratesForward) {
|
|
603
|
-
this.intervalTree.map((interval) => {
|
|
604
|
-
results.push(interval);
|
|
605
|
-
});
|
|
606
|
-
}
|
|
607
|
-
else {
|
|
608
|
-
this.intervalTree.mapBackward((interval) => {
|
|
609
|
-
results.push(interval);
|
|
610
|
-
});
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
else {
|
|
614
|
-
const transientInterval = this.helpers.create("transient", start, end, this.client, IntervalType.Transient);
|
|
615
|
-
if (start === undefined) {
|
|
616
|
-
// Only end position provided. Since the tree is not sorted by end position,
|
|
617
|
-
// walk the whole tree in the specified order, gathering intervals that match the end.
|
|
618
|
-
if (iteratesForward) {
|
|
619
|
-
this.intervalTree.map((interval) => {
|
|
620
|
-
if (transientInterval.compareEnd(interval) === 0) {
|
|
621
|
-
results.push(interval);
|
|
622
|
-
}
|
|
623
|
-
});
|
|
624
|
-
}
|
|
625
|
-
else {
|
|
626
|
-
this.intervalTree.mapBackward((interval) => {
|
|
627
|
-
if (transientInterval.compareEnd(interval) === 0) {
|
|
628
|
-
results.push(interval);
|
|
629
|
-
}
|
|
630
|
-
});
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
else {
|
|
634
|
-
// Start and (possibly) end provided. Walk the subtrees that may contain
|
|
635
|
-
// this start position.
|
|
636
|
-
const compareFn = end === undefined
|
|
637
|
-
? (node) => {
|
|
638
|
-
return transientInterval.compareStart(node.key);
|
|
639
|
-
}
|
|
640
|
-
: (node) => {
|
|
641
|
-
return transientInterval.compare(node.key);
|
|
642
|
-
};
|
|
643
|
-
const continueLeftFn = (cmpResult) => cmpResult <= 0;
|
|
644
|
-
const continueRightFn = (cmpResult) => cmpResult >= 0;
|
|
645
|
-
const actionFn = (node) => {
|
|
646
|
-
results.push(node.key);
|
|
647
|
-
};
|
|
648
|
-
if (iteratesForward) {
|
|
649
|
-
this.intervalTree.intervals.walkExactMatchesForward(compareFn, actionFn, continueLeftFn, continueRightFn);
|
|
650
|
-
}
|
|
651
|
-
else {
|
|
652
|
-
this.intervalTree.intervals.walkExactMatchesBackward(compareFn, actionFn, continueLeftFn, continueRightFn);
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
/**
|
|
658
|
-
* @returns an array of all intervals contained in this collection that overlap the range
|
|
659
|
-
* `[startPosition, endPosition)`.
|
|
660
|
-
*/
|
|
661
|
-
findOverlappingIntervals(startPosition, endPosition) {
|
|
662
|
-
if (endPosition < startPosition || this.intervalTree.intervals.isEmpty()) {
|
|
663
|
-
return [];
|
|
664
|
-
}
|
|
665
|
-
const transientInterval = this.helpers.create("transient", startPosition, endPosition, this.client, IntervalType.Transient);
|
|
666
|
-
const overlappingIntervalNodes = this.intervalTree.match(transientInterval);
|
|
667
|
-
return overlappingIntervalNodes.map((node) => node.key);
|
|
668
|
-
}
|
|
669
|
-
remove(interval) {
|
|
670
|
-
this.intervalTree.removeExisting(interval);
|
|
671
|
-
}
|
|
672
|
-
add(interval) {
|
|
673
|
-
this.intervalTree.put(interval);
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
class IdIntervalIndex {
|
|
677
|
-
constructor() {
|
|
678
|
-
this.intervalIdMap = new Map();
|
|
679
|
-
}
|
|
680
|
-
add(interval) {
|
|
681
|
-
const id = interval.getIntervalId();
|
|
682
|
-
(0, common_utils_1.assert)(id !== undefined, 0x2c0 /* "ID must be created before adding interval to collection" */);
|
|
683
|
-
// Make the ID immutable.
|
|
684
|
-
Object.defineProperty(interval.properties, reservedIntervalIdKey, {
|
|
685
|
-
configurable: false,
|
|
686
|
-
enumerable: true,
|
|
687
|
-
writable: false,
|
|
688
|
-
});
|
|
689
|
-
this.intervalIdMap.set(id, interval);
|
|
690
|
-
}
|
|
691
|
-
remove(interval) {
|
|
692
|
-
const id = interval.getIntervalId();
|
|
693
|
-
(0, common_utils_1.assert)(id !== undefined, 0x311 /* expected id to exist on interval */);
|
|
694
|
-
this.intervalIdMap.delete(id);
|
|
695
|
-
}
|
|
696
|
-
getIntervalById(id) {
|
|
697
|
-
return this.intervalIdMap.get(id);
|
|
698
|
-
}
|
|
699
|
-
[Symbol.iterator]() {
|
|
700
|
-
return this.intervalIdMap.values();
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
class EndpointIndex {
|
|
704
|
-
constructor(client, helpers) {
|
|
705
|
-
this.client = client;
|
|
706
|
-
this.helpers = helpers;
|
|
707
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
708
|
-
this.endIntervalTree = new merge_tree_1.RedBlackTree(helpers.compareEnds);
|
|
709
|
-
}
|
|
710
|
-
previousInterval(pos) {
|
|
711
|
-
const transientInterval = this.helpers.create("transient", pos, pos, this.client, IntervalType.Transient);
|
|
712
|
-
const rbNode = this.endIntervalTree.floor(transientInterval);
|
|
713
|
-
if (rbNode) {
|
|
714
|
-
return rbNode.data;
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
nextInterval(pos) {
|
|
718
|
-
const transientInterval = this.helpers.create("transient", pos, pos, this.client, IntervalType.Transient);
|
|
719
|
-
const rbNode = this.endIntervalTree.ceil(transientInterval);
|
|
720
|
-
if (rbNode) {
|
|
721
|
-
return rbNode.data;
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
add(interval) {
|
|
725
|
-
this.endIntervalTree.put(interval, interval);
|
|
726
|
-
}
|
|
727
|
-
remove(interval) {
|
|
728
|
-
this.endIntervalTree.remove(interval);
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
/**
|
|
732
|
-
* Interface for intervals that have comparison override properties.
|
|
733
|
-
*/
|
|
734
|
-
const forceCompare = Symbol();
|
|
735
|
-
/**
|
|
736
|
-
* Compares two objects based on their comparison override properties.
|
|
737
|
-
* @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).
|
|
738
|
-
*/
|
|
739
|
-
function compareOverrideables(a, b) {
|
|
740
|
-
var _a, _b;
|
|
741
|
-
const forceCompareA = (_a = a[forceCompare]) !== null && _a !== void 0 ? _a : 0;
|
|
742
|
-
const forceCompareB = (_b = b[forceCompare]) !== null && _b !== void 0 ? _b : 0;
|
|
743
|
-
return forceCompareA - forceCompareB;
|
|
744
|
-
}
|
|
745
|
-
class EndpointInRangeIndex {
|
|
746
|
-
constructor(helpers, client) {
|
|
747
|
-
this.helpers = helpers;
|
|
748
|
-
this.client = client;
|
|
749
|
-
this.intervalTree = new merge_tree_1.RedBlackTree((a, b) => {
|
|
750
|
-
const compareEndsResult = helpers.compareEnds(a, b);
|
|
751
|
-
if (compareEndsResult !== 0) {
|
|
752
|
-
return compareEndsResult;
|
|
753
|
-
}
|
|
754
|
-
const overrideablesComparison = compareOverrideables(a, b);
|
|
755
|
-
if (overrideablesComparison !== 0) {
|
|
756
|
-
return overrideablesComparison;
|
|
757
|
-
}
|
|
758
|
-
const aId = a.getIntervalId();
|
|
759
|
-
const bId = b.getIntervalId();
|
|
760
|
-
if (aId !== undefined && bId !== undefined) {
|
|
761
|
-
return aId.localeCompare(bId);
|
|
762
|
-
}
|
|
763
|
-
return 0;
|
|
764
|
-
});
|
|
765
|
-
}
|
|
766
|
-
add(interval) {
|
|
767
|
-
this.intervalTree.put(interval, interval);
|
|
768
|
-
}
|
|
769
|
-
remove(interval) {
|
|
770
|
-
this.intervalTree.remove(interval);
|
|
771
|
-
}
|
|
772
|
-
findIntervalsWithEndpointInRange(start, end) {
|
|
773
|
-
if (start <= 0 || start > end || this.intervalTree.isEmpty()) {
|
|
774
|
-
return [];
|
|
775
|
-
}
|
|
776
|
-
const results = [];
|
|
777
|
-
const action = (node) => {
|
|
778
|
-
results.push(node.data);
|
|
779
|
-
return true;
|
|
780
|
-
};
|
|
781
|
-
const transientStartInterval = this.helpers.create("transient", start, start, this.client, IntervalType.Transient);
|
|
782
|
-
const transientEndInterval = this.helpers.create("transient", end, end, this.client, IntervalType.Transient);
|
|
783
|
-
// Add comparison overrides to the transient intervals
|
|
784
|
-
transientStartInterval[forceCompare] = -1;
|
|
785
|
-
transientEndInterval[forceCompare] = 1;
|
|
786
|
-
this.intervalTree.mapRange(action, results, transientStartInterval, transientEndInterval);
|
|
787
|
-
return results;
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
class StartpointInRangeIndex {
|
|
791
|
-
constructor(helpers, client) {
|
|
792
|
-
this.helpers = helpers;
|
|
793
|
-
this.client = client;
|
|
794
|
-
this.intervalTree = new merge_tree_1.RedBlackTree((a, b) => {
|
|
795
|
-
(0, common_utils_1.assert)(typeof helpers.compareStarts === "function", 0x6d1 /* compareStarts does not exist in the helpers */);
|
|
796
|
-
const compareStartsResult = helpers.compareStarts(a, b);
|
|
797
|
-
if (compareStartsResult !== 0) {
|
|
798
|
-
return compareStartsResult;
|
|
799
|
-
}
|
|
800
|
-
const overrideablesComparison = compareOverrideables(a, b);
|
|
801
|
-
if (overrideablesComparison !== 0) {
|
|
802
|
-
return overrideablesComparison;
|
|
803
|
-
}
|
|
804
|
-
const aId = a.getIntervalId();
|
|
805
|
-
const bId = b.getIntervalId();
|
|
806
|
-
if (aId !== undefined && bId !== undefined) {
|
|
807
|
-
return aId.localeCompare(bId);
|
|
808
|
-
}
|
|
809
|
-
return 0;
|
|
810
|
-
});
|
|
811
|
-
}
|
|
812
|
-
add(interval) {
|
|
813
|
-
this.intervalTree.put(interval, interval);
|
|
814
|
-
}
|
|
815
|
-
remove(interval) {
|
|
816
|
-
this.intervalTree.remove(interval);
|
|
817
|
-
}
|
|
818
|
-
findIntervalsWithStartpointInRange(start, end) {
|
|
819
|
-
if (start <= 0 || start > end || this.intervalTree.isEmpty()) {
|
|
820
|
-
return [];
|
|
821
|
-
}
|
|
822
|
-
const results = [];
|
|
823
|
-
const action = (node) => {
|
|
824
|
-
results.push(node.data);
|
|
825
|
-
return true;
|
|
826
|
-
};
|
|
827
|
-
const transientStartInterval = this.helpers.create("transient", start, start, this.client, IntervalType.Transient);
|
|
828
|
-
const transientEndInterval = this.helpers.create("transient", end, end, this.client, IntervalType.Transient);
|
|
829
|
-
// Add comparison overrides to the transient intervals
|
|
830
|
-
transientStartInterval[forceCompare] = -1;
|
|
831
|
-
transientEndInterval[forceCompare] = 1;
|
|
832
|
-
this.intervalTree.mapRange(action, results, transientStartInterval, transientEndInterval);
|
|
833
|
-
return results;
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
function createEndpointInRangeIndex(helpers, client) {
|
|
837
|
-
return new EndpointInRangeIndex(helpers, client);
|
|
838
|
-
}
|
|
839
|
-
exports.createEndpointInRangeIndex = createEndpointInRangeIndex;
|
|
840
|
-
function createStartpointInRangeIndex(helpers, client) {
|
|
841
|
-
return new StartpointInRangeIndex(helpers, client);
|
|
842
|
-
}
|
|
843
|
-
exports.createStartpointInRangeIndex = createStartpointInRangeIndex;
|
|
844
60
|
class LocalIntervalCollection {
|
|
845
61
|
constructor(client, label, helpers,
|
|
846
62
|
/** Callback invoked each time one of the endpoints of an interval slides. */
|
|
@@ -849,9 +65,9 @@ class LocalIntervalCollection {
|
|
|
849
65
|
this.label = label;
|
|
850
66
|
this.helpers = helpers;
|
|
851
67
|
this.onPositionChange = onPositionChange;
|
|
852
|
-
this.overlappingIntervalsIndex =
|
|
853
|
-
this.idIntervalIndex =
|
|
854
|
-
this.endIntervalIndex =
|
|
68
|
+
this.overlappingIntervalsIndex = (0, intervalIndex_1.createOverlappingIntervalsIndex)(client, helpers);
|
|
69
|
+
this.idIntervalIndex = (0, intervalIndex_1.createIdIntervalIndex)();
|
|
70
|
+
this.endIntervalIndex = (0, intervalIndex_1.createEndpointIndex)(client, helpers);
|
|
855
71
|
this.indexes = new Set([
|
|
856
72
|
this.overlappingIntervalsIndex,
|
|
857
73
|
this.idIntervalIndex,
|
|
@@ -871,8 +87,7 @@ class LocalIntervalCollection {
|
|
|
871
87
|
* @returns The interval's existing or newly created id
|
|
872
88
|
*/
|
|
873
89
|
ensureSerializedId(serializedInterval) {
|
|
874
|
-
|
|
875
|
-
let id = (_a = serializedInterval.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
|
|
90
|
+
let id = serializedInterval.properties?.[reservedIntervalIdKey];
|
|
876
91
|
if (id === undefined) {
|
|
877
92
|
// Back-compat: 0.39 and earlier did not have IDs on intervals. If an interval from such a client
|
|
878
93
|
// comes over the wire, create a non-unique one based on start/end.
|
|
@@ -906,27 +121,33 @@ class LocalIntervalCollection {
|
|
|
906
121
|
this.removeIntervalFromIndexes(interval);
|
|
907
122
|
this.removeIntervalListeners(interval);
|
|
908
123
|
}
|
|
909
|
-
createInterval(start, end, intervalType, op, stickiness =
|
|
124
|
+
createInterval(start, end, intervalType, op, stickiness = intervals_1.IntervalStickiness.END) {
|
|
910
125
|
return this.helpers.create(this.label, start, end, this.client, intervalType, op, undefined, stickiness);
|
|
911
126
|
}
|
|
912
|
-
addInterval(start, end, intervalType, props, op, stickiness =
|
|
127
|
+
addInterval(start, end, intervalType, props, op, stickiness = intervals_1.IntervalStickiness.END) {
|
|
913
128
|
var _a;
|
|
914
|
-
var _b;
|
|
915
129
|
const interval = this.createInterval(start, end, intervalType, op, stickiness);
|
|
916
130
|
if (interval) {
|
|
917
131
|
if (!interval.properties) {
|
|
918
132
|
interval.properties = (0, merge_tree_1.createMap)();
|
|
919
133
|
}
|
|
920
134
|
if (props) {
|
|
135
|
+
// This check is intended to prevent scenarios where a random interval is created and then
|
|
136
|
+
// inserted into a collection. The aim is to ensure that the collection is created first
|
|
137
|
+
// then the user can create/add intervals based on the collection
|
|
138
|
+
if (props[merge_tree_1.reservedRangeLabelsKey] !== undefined &&
|
|
139
|
+
props[merge_tree_1.reservedRangeLabelsKey][0] !== this.label) {
|
|
140
|
+
throw new telemetry_utils_1.LoggingError("Adding an interval that belongs to another interval collection is not permitted");
|
|
141
|
+
}
|
|
921
142
|
interval.addProperties(props);
|
|
922
143
|
}
|
|
923
|
-
(_a =
|
|
144
|
+
(_a = interval.properties)[reservedIntervalIdKey] ?? (_a[reservedIntervalIdKey] = (0, uuid_1.v4)());
|
|
924
145
|
this.add(interval);
|
|
925
146
|
}
|
|
926
147
|
return interval;
|
|
927
148
|
}
|
|
928
149
|
linkEndpointsToInterval(interval) {
|
|
929
|
-
if (interval instanceof SequenceInterval) {
|
|
150
|
+
if (interval instanceof intervals_1.SequenceInterval) {
|
|
930
151
|
interval.start.addProperties({ interval });
|
|
931
152
|
interval.end.addProperties({ interval });
|
|
932
153
|
}
|
|
@@ -967,7 +188,7 @@ class LocalIntervalCollection {
|
|
|
967
188
|
}
|
|
968
189
|
return this.client.createLocalReferencePosition(segment, ref.getOffset(), merge_tree_1.ReferenceType.Transient, ref.properties, ref.slidingPreference);
|
|
969
190
|
};
|
|
970
|
-
if (interval instanceof SequenceInterval) {
|
|
191
|
+
if (interval instanceof intervals_1.SequenceInterval) {
|
|
971
192
|
let previousInterval;
|
|
972
193
|
let pendingChanges = 0;
|
|
973
194
|
interval.addPositionChangeListeners(() => {
|
|
@@ -980,42 +201,27 @@ class LocalIntervalCollection {
|
|
|
980
201
|
this.removeIntervalFromIndexes(interval);
|
|
981
202
|
}
|
|
982
203
|
}, () => {
|
|
983
|
-
|
|
984
|
-
(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 */);
|
|
985
205
|
pendingChanges--;
|
|
986
206
|
if (pendingChanges === 0) {
|
|
987
207
|
this.addIntervalToIndexes(interval);
|
|
988
|
-
|
|
208
|
+
this.onPositionChange?.(interval, previousInterval);
|
|
989
209
|
previousInterval = undefined;
|
|
990
210
|
}
|
|
991
211
|
});
|
|
992
212
|
}
|
|
993
213
|
}
|
|
994
214
|
removeIntervalListeners(interval) {
|
|
995
|
-
if (interval instanceof SequenceInterval) {
|
|
215
|
+
if (interval instanceof intervals_1.SequenceInterval) {
|
|
996
216
|
interval.removePositionChangeListeners();
|
|
997
217
|
}
|
|
998
218
|
}
|
|
999
219
|
}
|
|
1000
220
|
exports.LocalIntervalCollection = LocalIntervalCollection;
|
|
1001
221
|
LocalIntervalCollection.legacyIdPrefix = "legacy";
|
|
1002
|
-
const compareSequenceIntervalEnds = (a, b) => (0, merge_tree_1.compareReferencePositions)(a.end, b.end);
|
|
1003
|
-
exports.compareSequenceIntervalEnds = compareSequenceIntervalEnds;
|
|
1004
|
-
const compareSequenceIntervalStarts = (a, b) => (0, merge_tree_1.compareReferencePositions)(a.start, b.start);
|
|
1005
|
-
exports.compareSequenceIntervalStarts = compareSequenceIntervalStarts;
|
|
1006
|
-
exports.sequenceIntervalHelpers = {
|
|
1007
|
-
compareEnds: exports.compareSequenceIntervalEnds,
|
|
1008
|
-
compareStarts: exports.compareSequenceIntervalStarts,
|
|
1009
|
-
create: createSequenceInterval,
|
|
1010
|
-
};
|
|
1011
|
-
exports.intervalHelpers = {
|
|
1012
|
-
compareEnds: (a, b) => a.end - b.end,
|
|
1013
|
-
compareStarts: (a, b) => a.start - b.start,
|
|
1014
|
-
create: createInterval,
|
|
1015
|
-
};
|
|
1016
222
|
class SequenceIntervalCollectionFactory {
|
|
1017
223
|
load(emitter, raw = [], options) {
|
|
1018
|
-
return new IntervalCollection(
|
|
224
|
+
return new IntervalCollection(intervals_1.sequenceIntervalHelpers, true, emitter, raw, options);
|
|
1019
225
|
}
|
|
1020
226
|
store(value) {
|
|
1021
227
|
return value.serializeInternal();
|
|
@@ -1036,19 +242,11 @@ exports.SequenceIntervalCollectionValueType = SequenceIntervalCollectionValueTyp
|
|
|
1036
242
|
SequenceIntervalCollectionValueType.Name = "sharedStringIntervalCollection";
|
|
1037
243
|
SequenceIntervalCollectionValueType._factory = new SequenceIntervalCollectionFactory();
|
|
1038
244
|
SequenceIntervalCollectionValueType._ops = makeOpsMap();
|
|
1039
|
-
const compareIntervalEnds = (a, b) => a.end - b.end;
|
|
1040
|
-
function createInterval(label, start, end, client, intervalType, op, fromSnapshot) {
|
|
1041
|
-
const rangeProp = {};
|
|
1042
|
-
if (label && label.length > 0) {
|
|
1043
|
-
rangeProp[merge_tree_1.reservedRangeLabelsKey] = [label];
|
|
1044
|
-
}
|
|
1045
|
-
return new Interval(start, end, rangeProp);
|
|
1046
|
-
}
|
|
1047
245
|
class IntervalCollectionFactory {
|
|
1048
246
|
load(emitter, raw = [], options) {
|
|
1049
247
|
const helpers = {
|
|
1050
|
-
compareEnds:
|
|
1051
|
-
create: createInterval,
|
|
248
|
+
compareEnds: (a, b) => a.end - b.end,
|
|
249
|
+
create: intervals_1.createInterval,
|
|
1052
250
|
};
|
|
1053
251
|
const collection = new IntervalCollection(helpers, false, emitter, raw, options);
|
|
1054
252
|
collection.attachGraph(undefined, "");
|
|
@@ -1077,12 +275,12 @@ function makeOpsMap() {
|
|
|
1077
275
|
const rebase = (collection, op, localOpMetadata) => {
|
|
1078
276
|
const { localSeq } = localOpMetadata;
|
|
1079
277
|
const rebasedValue = collection.rebaseLocalInterval(op.opName, op.value, localSeq);
|
|
1080
|
-
const rebasedOp =
|
|
278
|
+
const rebasedOp = { ...op, value: rebasedValue };
|
|
1081
279
|
return { rebasedOp, rebasedLocalOpMetadata: localOpMetadata };
|
|
1082
280
|
};
|
|
1083
281
|
return new Map([
|
|
1084
282
|
[
|
|
1085
|
-
|
|
283
|
+
intervals_1.IntervalOpType.ADD,
|
|
1086
284
|
{
|
|
1087
285
|
process: (collection, params, local, op, localOpMetadata) => {
|
|
1088
286
|
// if params is undefined, the interval was deleted during
|
|
@@ -1090,17 +288,17 @@ function makeOpsMap() {
|
|
|
1090
288
|
if (!params) {
|
|
1091
289
|
return;
|
|
1092
290
|
}
|
|
1093
|
-
(0,
|
|
291
|
+
(0, core_utils_1.assert)(op !== undefined, 0x3fb /* op should exist here */);
|
|
1094
292
|
collection.ackAdd(params, local, op, localOpMetadata);
|
|
1095
293
|
},
|
|
1096
294
|
rebase,
|
|
1097
295
|
},
|
|
1098
296
|
],
|
|
1099
297
|
[
|
|
1100
|
-
|
|
298
|
+
intervals_1.IntervalOpType.DELETE,
|
|
1101
299
|
{
|
|
1102
300
|
process: (collection, params, local, op) => {
|
|
1103
|
-
(0,
|
|
301
|
+
(0, core_utils_1.assert)(op !== undefined, 0x3fc /* op should exist here */);
|
|
1104
302
|
collection.ackDelete(params, local, op);
|
|
1105
303
|
},
|
|
1106
304
|
rebase: (collection, op, localOpMetadata) => {
|
|
@@ -1110,7 +308,7 @@ function makeOpsMap() {
|
|
|
1110
308
|
},
|
|
1111
309
|
],
|
|
1112
310
|
[
|
|
1113
|
-
|
|
311
|
+
intervals_1.IntervalOpType.CHANGE,
|
|
1114
312
|
{
|
|
1115
313
|
process: (collection, params, local, op, localOpMetadata) => {
|
|
1116
314
|
// if params is undefined, the interval was deleted during
|
|
@@ -1118,7 +316,7 @@ function makeOpsMap() {
|
|
|
1118
316
|
if (!params) {
|
|
1119
317
|
return;
|
|
1120
318
|
}
|
|
1121
|
-
(0,
|
|
319
|
+
(0, core_utils_1.assert)(op !== undefined, 0x3fd /* op should exist here */);
|
|
1122
320
|
collection.ackChange(params, local, op, localOpMetadata);
|
|
1123
321
|
},
|
|
1124
322
|
rebase,
|
|
@@ -1149,7 +347,7 @@ class IntervalCollectionIterator {
|
|
|
1149
347
|
/**
|
|
1150
348
|
* {@inheritdoc IIntervalCollection}
|
|
1151
349
|
*/
|
|
1152
|
-
class IntervalCollection extends
|
|
350
|
+
class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
1153
351
|
/** @internal */
|
|
1154
352
|
constructor(helpers, requiresClient, emitter, serializedIntervals, options = {}) {
|
|
1155
353
|
super();
|
|
@@ -1172,25 +370,23 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1172
370
|
* {@inheritdoc IIntervalCollection.attachIndex}
|
|
1173
371
|
*/
|
|
1174
372
|
attachIndex(index) {
|
|
1175
|
-
var _a;
|
|
1176
373
|
if (!this.attached) {
|
|
1177
374
|
throw new telemetry_utils_1.LoggingError("The local interval collection must exist");
|
|
1178
375
|
}
|
|
1179
376
|
for (const interval of this) {
|
|
1180
377
|
index.add(interval);
|
|
1181
378
|
}
|
|
1182
|
-
|
|
379
|
+
this.localCollection?.appendIndex(index);
|
|
1183
380
|
}
|
|
1184
381
|
/**
|
|
1185
382
|
* {@inheritdoc IIntervalCollection.detachIndex}
|
|
1186
383
|
*/
|
|
1187
384
|
detachIndex(index) {
|
|
1188
|
-
var _a;
|
|
1189
385
|
if (!this.attached) {
|
|
1190
386
|
throw new telemetry_utils_1.LoggingError("The local interval collection must exist");
|
|
1191
387
|
}
|
|
1192
388
|
// Avoid removing intervals if the index does not exist
|
|
1193
|
-
if (!
|
|
389
|
+
if (!this.localCollection?.removeIndex(index)) {
|
|
1194
390
|
return false;
|
|
1195
391
|
}
|
|
1196
392
|
for (const interval of this) {
|
|
@@ -1199,7 +395,6 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1199
395
|
return true;
|
|
1200
396
|
}
|
|
1201
397
|
rebasePositionWithSegmentSlide(pos, seqNumberFrom, localSeq) {
|
|
1202
|
-
var _a;
|
|
1203
398
|
if (!this.client) {
|
|
1204
399
|
throw new telemetry_utils_1.LoggingError("mergeTree client must exist");
|
|
1205
400
|
}
|
|
@@ -1209,20 +404,20 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1209
404
|
clientId: this.client.getLongClientId(clientId),
|
|
1210
405
|
}, localSeq);
|
|
1211
406
|
// if segment is undefined, it slid off the string
|
|
1212
|
-
(0,
|
|
1213
|
-
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;
|
|
1214
409
|
// case happens when rebasing op, but concurrently entire string has been deleted
|
|
1215
410
|
if (segoff.segment === undefined || segoff.offset === undefined) {
|
|
1216
411
|
return merge_tree_1.DetachedReferencePosition;
|
|
1217
412
|
}
|
|
1218
|
-
(0,
|
|
413
|
+
(0, core_utils_1.assert)(offset !== undefined && 0 <= offset && offset < segment.cachedLength, 0x54f /* Invalid offset */);
|
|
1219
414
|
return this.client.findReconnectionPosition(segoff.segment, localSeq) + segoff.offset;
|
|
1220
415
|
}
|
|
1221
416
|
computeRebasedPositions(localSeq) {
|
|
1222
|
-
(0,
|
|
417
|
+
(0, core_utils_1.assert)(this.client !== undefined, 0x550 /* Client should be defined when computing rebased position */);
|
|
1223
418
|
const original = this.localSeqToSerializedInterval.get(localSeq);
|
|
1224
|
-
(0,
|
|
1225
|
-
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 };
|
|
1226
421
|
const { start, end, sequenceNumber } = original;
|
|
1227
422
|
if (start !== undefined) {
|
|
1228
423
|
rebased.start = this.rebasePositionWithSegmentSlide(start, sequenceNumber, localSeq);
|
|
@@ -1249,7 +444,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1249
444
|
}
|
|
1250
445
|
});
|
|
1251
446
|
}
|
|
1252
|
-
this.localCollection = new LocalIntervalCollection(client, label, this.helpers, (interval, previousInterval) => this.emitChange(interval, previousInterval, true));
|
|
447
|
+
this.localCollection = new LocalIntervalCollection(client, label, this.helpers, (interval, previousInterval) => this.emitChange(interval, previousInterval, true, true));
|
|
1253
448
|
if (this.savedSerializedIntervals) {
|
|
1254
449
|
for (const serializedInterval of this.savedSerializedIntervals) {
|
|
1255
450
|
this.localCollection.ensureSerializedId(serializedInterval);
|
|
@@ -1272,23 +467,23 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1272
467
|
}
|
|
1273
468
|
return 0;
|
|
1274
469
|
}
|
|
1275
|
-
emitChange(interval, previousInterval, local, op) {
|
|
470
|
+
emitChange(interval, previousInterval, local, slide, op) {
|
|
1276
471
|
// Temporarily make references transient so that positional queries work (non-transient refs
|
|
1277
472
|
// on resolve to DetachedPosition on any segments that don't contain them). The original refType
|
|
1278
473
|
// is restored as single-endpoint changes re-use previous references.
|
|
1279
474
|
let startRefType;
|
|
1280
475
|
let endRefType;
|
|
1281
|
-
if (previousInterval instanceof SequenceInterval) {
|
|
476
|
+
if (previousInterval instanceof intervals_1.SequenceInterval) {
|
|
1282
477
|
startRefType = previousInterval.start.refType;
|
|
1283
478
|
endRefType = previousInterval.end.refType;
|
|
1284
479
|
previousInterval.start.refType = merge_tree_1.ReferenceType.Transient;
|
|
1285
480
|
previousInterval.end.refType = merge_tree_1.ReferenceType.Transient;
|
|
1286
|
-
this.emit("changeInterval", interval, previousInterval, local, op);
|
|
481
|
+
this.emit("changeInterval", interval, previousInterval, local, op, slide);
|
|
1287
482
|
previousInterval.start.refType = startRefType;
|
|
1288
483
|
previousInterval.end.refType = endRefType;
|
|
1289
484
|
}
|
|
1290
485
|
else {
|
|
1291
|
-
this.emit("changeInterval", interval, previousInterval, local, op);
|
|
486
|
+
this.emit("changeInterval", interval, previousInterval, local, op, slide);
|
|
1292
487
|
}
|
|
1293
488
|
}
|
|
1294
489
|
/**
|
|
@@ -1303,16 +498,15 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1303
498
|
/**
|
|
1304
499
|
* {@inheritdoc IIntervalCollection.add}
|
|
1305
500
|
*/
|
|
1306
|
-
add(start, end, intervalType, props, stickiness =
|
|
1307
|
-
var _a, _b;
|
|
501
|
+
add(start, end, intervalType, props, stickiness = intervals_1.IntervalStickiness.END) {
|
|
1308
502
|
if (!this.localCollection) {
|
|
1309
503
|
throw new telemetry_utils_1.LoggingError("attach must be called prior to adding intervals");
|
|
1310
504
|
}
|
|
1311
|
-
if (intervalType & IntervalType.Transient) {
|
|
505
|
+
if (intervalType & intervals_1.IntervalType.Transient) {
|
|
1312
506
|
throw new telemetry_utils_1.LoggingError("Can not add transient intervals");
|
|
1313
507
|
}
|
|
1314
|
-
if (stickiness !==
|
|
1315
|
-
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");
|
|
1316
510
|
}
|
|
1317
511
|
const interval = this.localCollection.addInterval(start, end, intervalType, props, undefined, stickiness);
|
|
1318
512
|
if (interval) {
|
|
@@ -1320,7 +514,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1320
514
|
end,
|
|
1321
515
|
intervalType,
|
|
1322
516
|
properties: interval.properties,
|
|
1323
|
-
sequenceNumber:
|
|
517
|
+
sequenceNumber: this.client?.getCurrentSeq() ?? 0,
|
|
1324
518
|
start,
|
|
1325
519
|
stickiness,
|
|
1326
520
|
};
|
|
@@ -1379,6 +573,11 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1379
573
|
if (!props) {
|
|
1380
574
|
throw new telemetry_utils_1.LoggingError("changeProperties should be called with a property set");
|
|
1381
575
|
}
|
|
576
|
+
// prevent the overwriting of an interval label, it should remain unchanged
|
|
577
|
+
// once it has been inserted into the collection.
|
|
578
|
+
if (props[merge_tree_1.reservedRangeLabelsKey] !== undefined) {
|
|
579
|
+
throw new telemetry_utils_1.LoggingError("The label property should not be modified once inserted to the collection");
|
|
580
|
+
}
|
|
1382
581
|
const interval = this.getIntervalById(id);
|
|
1383
582
|
if (interval) {
|
|
1384
583
|
// Pass Unassigned as the sequence number to indicate that this is a local op that is waiting for an ack.
|
|
@@ -1424,7 +623,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1424
623
|
this.localSeqToSerializedInterval.set(localSeq, serializedInterval);
|
|
1425
624
|
this.emitter.emit("change", undefined, serializedInterval, { localSeq });
|
|
1426
625
|
this.addPendingChange(id, serializedInterval);
|
|
1427
|
-
this.emitChange(newInterval, interval, true);
|
|
626
|
+
this.emitChange(newInterval, interval, true, false);
|
|
1428
627
|
return newInterval;
|
|
1429
628
|
}
|
|
1430
629
|
// No interval to change
|
|
@@ -1447,9 +646,8 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1447
646
|
entries.push(serializedInterval);
|
|
1448
647
|
}
|
|
1449
648
|
removePendingChange(serializedInterval) {
|
|
1450
|
-
var _a;
|
|
1451
649
|
// Change ops always have an ID.
|
|
1452
|
-
const id =
|
|
650
|
+
const id = serializedInterval.properties?.[reservedIntervalIdKey];
|
|
1453
651
|
if (serializedInterval.start !== undefined) {
|
|
1454
652
|
this.removePendingChangeHelper(id, this.pendingChangesStart, serializedInterval);
|
|
1455
653
|
}
|
|
@@ -1464,8 +662,8 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1464
662
|
if (entries.length === 0) {
|
|
1465
663
|
pendingChanges.delete(id);
|
|
1466
664
|
}
|
|
1467
|
-
if (
|
|
1468
|
-
|
|
665
|
+
if (pendingChange?.start !== serializedInterval.start ||
|
|
666
|
+
pendingChange?.end !== serializedInterval.end) {
|
|
1469
667
|
throw new telemetry_utils_1.LoggingError("Mismatch in pending changes");
|
|
1470
668
|
}
|
|
1471
669
|
}
|
|
@@ -1480,21 +678,20 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1480
678
|
}
|
|
1481
679
|
/** @internal */
|
|
1482
680
|
ackChange(serializedInterval, local, op, localOpMetadata) {
|
|
1483
|
-
var _a, _b, _c, _d;
|
|
1484
681
|
if (!this.localCollection) {
|
|
1485
682
|
throw new telemetry_utils_1.LoggingError("Attach must be called before accessing intervals");
|
|
1486
683
|
}
|
|
1487
684
|
if (local) {
|
|
1488
|
-
(0,
|
|
1489
|
-
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);
|
|
1490
687
|
// This is an ack from the server. Remove the pending change.
|
|
1491
688
|
this.removePendingChange(serializedInterval);
|
|
1492
689
|
}
|
|
1493
690
|
// Note that the ID is in the property bag only to allow us to find the interval.
|
|
1494
691
|
// This API cannot change the ID, and writing to the ID property will result in an exception. So we
|
|
1495
692
|
// strip it out of the properties here.
|
|
1496
|
-
const
|
|
1497
|
-
(0,
|
|
693
|
+
const { [reservedIntervalIdKey]: id, ...newProps } = serializedInterval.properties ?? {};
|
|
694
|
+
(0, core_utils_1.assert)(id !== undefined, 0x3fe /* id must exist on the interval */);
|
|
1498
695
|
const interval = this.getIntervalById(id);
|
|
1499
696
|
if (!interval) {
|
|
1500
697
|
// The interval has been removed locally; no-op.
|
|
@@ -1502,9 +699,9 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1502
699
|
}
|
|
1503
700
|
if (local) {
|
|
1504
701
|
// Let the propertyManager prune its pending change-properties set.
|
|
1505
|
-
|
|
702
|
+
interval.propertyManager?.ackPendingProperties({
|
|
1506
703
|
type: merge_tree_1.MergeTreeDeltaType.ANNOTATE,
|
|
1507
|
-
props:
|
|
704
|
+
props: serializedInterval.properties ?? {},
|
|
1508
705
|
});
|
|
1509
706
|
this.ackInterval(interval, op);
|
|
1510
707
|
}
|
|
@@ -1525,14 +722,14 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1525
722
|
// If changeInterval gives us a new interval, work with that one. Otherwise keep working with
|
|
1526
723
|
// the one we originally found in the tree.
|
|
1527
724
|
newInterval =
|
|
1528
|
-
|
|
725
|
+
this.localCollection.changeInterval(interval, start, end, op) ?? interval;
|
|
1529
726
|
}
|
|
1530
727
|
const deltaProps = newInterval.addProperties(newProps, true, op.sequenceNumber);
|
|
1531
728
|
if (this.onDeserialize) {
|
|
1532
729
|
this.onDeserialize(newInterval);
|
|
1533
730
|
}
|
|
1534
731
|
if (newInterval !== interval) {
|
|
1535
|
-
this.emitChange(newInterval, interval, local, op);
|
|
732
|
+
this.emitChange(newInterval, interval, local, false, op);
|
|
1536
733
|
}
|
|
1537
734
|
const changedProperties = Object.keys(newProps).length > 0;
|
|
1538
735
|
if (changedProperties) {
|
|
@@ -1540,18 +737,6 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1540
737
|
}
|
|
1541
738
|
}
|
|
1542
739
|
}
|
|
1543
|
-
/**
|
|
1544
|
-
* @deprecated - This functionality was useful when adding two intervals at the same start/end positions resulted
|
|
1545
|
-
* in a conflict. This is no longer the case (as of PR#6407), as interval collections support multiple intervals
|
|
1546
|
-
* at the same location and gives each interval a unique id.
|
|
1547
|
-
*
|
|
1548
|
-
* As such, the conflict resolver is never invoked and unnecessary. This API will be removed in an upcoming release.
|
|
1549
|
-
*/
|
|
1550
|
-
addConflictResolver(_) {
|
|
1551
|
-
if (!this.localCollection) {
|
|
1552
|
-
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
1553
|
-
}
|
|
1554
|
-
}
|
|
1555
740
|
/**
|
|
1556
741
|
* {@inheritdoc IIntervalCollection.attachDeserializer}
|
|
1557
742
|
*/
|
|
@@ -1575,7 +760,6 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1575
760
|
* @internal
|
|
1576
761
|
*/
|
|
1577
762
|
rebaseLocalInterval(opName, serializedInterval, localSeq) {
|
|
1578
|
-
var _a, _b, _c, _d, _e, _f;
|
|
1579
763
|
if (!this.client) {
|
|
1580
764
|
// If there's no associated mergeTree client, the originally submitted op is still correct.
|
|
1581
765
|
return serializedInterval;
|
|
@@ -1584,14 +768,14 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1584
768
|
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
1585
769
|
}
|
|
1586
770
|
const { intervalType, properties } = serializedInterval;
|
|
1587
|
-
const { start: startRebased, end: endRebased } =
|
|
1588
|
-
const intervalId = properties
|
|
1589
|
-
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);
|
|
1590
774
|
const rebased = {
|
|
1591
775
|
start: startRebased,
|
|
1592
776
|
end: endRebased,
|
|
1593
777
|
intervalType,
|
|
1594
|
-
sequenceNumber:
|
|
778
|
+
sequenceNumber: this.client?.getCurrentSeq() ?? 0,
|
|
1595
779
|
properties,
|
|
1596
780
|
};
|
|
1597
781
|
if (opName === "change" &&
|
|
@@ -1603,29 +787,28 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1603
787
|
if (startRebased === merge_tree_1.DetachedReferencePosition ||
|
|
1604
788
|
endRebased === merge_tree_1.DetachedReferencePosition) {
|
|
1605
789
|
if (localInterval) {
|
|
1606
|
-
|
|
790
|
+
this.localCollection?.removeExistingInterval(localInterval);
|
|
1607
791
|
}
|
|
1608
792
|
return undefined;
|
|
1609
793
|
}
|
|
1610
794
|
if (localInterval !== undefined) {
|
|
1611
795
|
// we know we must be using `SequenceInterval` because `this.client` exists
|
|
1612
|
-
(0,
|
|
796
|
+
(0, core_utils_1.assert)(localInterval instanceof intervals_1.SequenceInterval, 0x3a0 /* localInterval must be `SequenceInterval` when used with client */);
|
|
1613
797
|
// The rebased op may place this interval's endpoints on different segments. Calling `changeInterval` here
|
|
1614
798
|
// updates the local client's state to be consistent with the emitted op.
|
|
1615
|
-
|
|
799
|
+
this.localCollection?.changeInterval(localInterval, startRebased, endRebased, undefined, localSeq);
|
|
1616
800
|
}
|
|
1617
801
|
return rebased;
|
|
1618
802
|
}
|
|
1619
803
|
getSlideToSegment(lref) {
|
|
1620
|
-
var _a, _b;
|
|
1621
804
|
if (!this.client) {
|
|
1622
805
|
throw new telemetry_utils_1.LoggingError("client does not exist");
|
|
1623
806
|
}
|
|
1624
807
|
const segoff = { segment: lref.getSegment(), offset: lref.getOffset() };
|
|
1625
|
-
if (
|
|
808
|
+
if (segoff.segment?.localRefs?.has(lref) !== true) {
|
|
1626
809
|
return undefined;
|
|
1627
810
|
}
|
|
1628
|
-
const newSegoff =
|
|
811
|
+
const newSegoff = (0, merge_tree_1.getSlideToSegoff)(segoff);
|
|
1629
812
|
const value = segoff.segment === newSegoff.segment && segoff.offset === newSegoff.offset
|
|
1630
813
|
? undefined
|
|
1631
814
|
: newSegoff;
|
|
@@ -1638,9 +821,8 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1638
821
|
lref.refType = refType;
|
|
1639
822
|
}
|
|
1640
823
|
ackInterval(interval, op) {
|
|
1641
|
-
var _a, _b;
|
|
1642
824
|
// Only SequenceIntervals need potential sliding
|
|
1643
|
-
if (!(interval instanceof SequenceInterval)) {
|
|
825
|
+
if (!(interval instanceof intervals_1.SequenceInterval)) {
|
|
1644
826
|
return;
|
|
1645
827
|
}
|
|
1646
828
|
if (!(0, merge_tree_1.refTypeIncludesFlag)(interval.start, merge_tree_1.ReferenceType.StayOnRemove) &&
|
|
@@ -1675,7 +857,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1675
857
|
}
|
|
1676
858
|
if (needsStartUpdate) {
|
|
1677
859
|
const props = interval.start.properties;
|
|
1678
|
-
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));
|
|
1679
861
|
if (props) {
|
|
1680
862
|
interval.start.addProperties(props);
|
|
1681
863
|
}
|
|
@@ -1683,11 +865,11 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1683
865
|
// remove and rebuild start interval as transient for event
|
|
1684
866
|
this.client.removeLocalReferencePosition(oldInterval.start);
|
|
1685
867
|
oldInterval.start.refType = merge_tree_1.ReferenceType.Transient;
|
|
1686
|
-
|
|
868
|
+
oldSeg?.localRefs?.addLocalRef(oldInterval.start, oldInterval.start.getOffset());
|
|
1687
869
|
}
|
|
1688
870
|
if (needsEndUpdate) {
|
|
1689
871
|
const props = interval.end.properties;
|
|
1690
|
-
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));
|
|
1691
873
|
if (props) {
|
|
1692
874
|
interval.end.addProperties(props);
|
|
1693
875
|
}
|
|
@@ -1695,19 +877,18 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1695
877
|
const oldSeg = oldInterval.end.getSegment();
|
|
1696
878
|
this.client.removeLocalReferencePosition(oldInterval.end);
|
|
1697
879
|
oldInterval.end.refType = merge_tree_1.ReferenceType.Transient;
|
|
1698
|
-
|
|
880
|
+
oldSeg?.localRefs?.addLocalRef(oldInterval.end, oldInterval.end.getOffset());
|
|
1699
881
|
}
|
|
1700
882
|
this.localCollection.add(interval);
|
|
1701
|
-
this.emitChange(interval, oldInterval, true, op);
|
|
883
|
+
this.emitChange(interval, oldInterval, true, true, op);
|
|
1702
884
|
}
|
|
1703
885
|
}
|
|
1704
886
|
/** @internal */
|
|
1705
887
|
ackAdd(serializedInterval, local, op, localOpMetadata) {
|
|
1706
|
-
var _a;
|
|
1707
888
|
if (local) {
|
|
1708
|
-
(0,
|
|
889
|
+
(0, core_utils_1.assert)(localOpMetadata !== undefined, 0x553 /* op metadata should be defined for local op */);
|
|
1709
890
|
this.localSeqToSerializedInterval.delete(localOpMetadata.localSeq);
|
|
1710
|
-
const id =
|
|
891
|
+
const id = serializedInterval.properties?.[reservedIntervalIdKey];
|
|
1711
892
|
const localInterval = this.getIntervalById(id);
|
|
1712
893
|
if (localInterval) {
|
|
1713
894
|
this.ackInterval(localInterval, op);
|
|
@@ -1844,9 +1025,8 @@ exports.IntervalCollection = IntervalCollection;
|
|
|
1844
1025
|
* endpoint is a part of.
|
|
1845
1026
|
*/
|
|
1846
1027
|
function intervalLocatorFromEndpoint(potentialEndpoint) {
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
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
|
|
1850
1030
|
? { label: collectionNameArray[0], interval }
|
|
1851
1031
|
: undefined;
|
|
1852
1032
|
}
|