@fluidframework/sequence 2.0.0-internal.6.3.3 → 2.0.0-internal.7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +64 -0
- package/README.md +130 -0
- package/dist/defaultMap.d.ts +1 -1
- package/dist/defaultMap.d.ts.map +1 -1
- package/dist/defaultMap.js +6 -6
- package/dist/defaultMap.js.map +1 -1
- package/dist/defaultMapInterfaces.d.ts +21 -2
- package/dist/defaultMapInterfaces.d.ts.map +1 -1
- package/dist/defaultMapInterfaces.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/intervalCollection.d.ts +140 -22
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalCollection.js +146 -49
- package/dist/intervalCollection.js.map +1 -1
- package/dist/intervalIndex/endpointInRangeIndex.d.ts +13 -3
- package/dist/intervalIndex/endpointInRangeIndex.d.ts.map +1 -1
- package/dist/intervalIndex/endpointInRangeIndex.js +9 -6
- package/dist/intervalIndex/endpointInRangeIndex.js.map +1 -1
- package/dist/intervalIndex/endpointIndex.d.ts +13 -2
- package/dist/intervalIndex/endpointIndex.d.ts.map +1 -1
- package/dist/intervalIndex/endpointIndex.js +7 -5
- package/dist/intervalIndex/endpointIndex.js.map +1 -1
- package/dist/intervalIndex/idIntervalIndex.js.map +1 -1
- package/dist/intervalIndex/index.d.ts +4 -4
- package/dist/intervalIndex/index.d.ts.map +1 -1
- package/dist/intervalIndex/index.js +5 -1
- package/dist/intervalIndex/index.js.map +1 -1
- package/dist/intervalIndex/intervalIndex.d.ts +2 -2
- package/dist/intervalIndex/intervalIndex.js.map +1 -1
- package/dist/intervalIndex/overlappingIntervalsIndex.d.ts +8 -6
- package/dist/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -1
- package/dist/intervalIndex/overlappingIntervalsIndex.js +11 -4
- package/dist/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.d.ts +2 -2
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.d.ts.map +1 -1
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js +3 -1
- 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 +13 -3
- package/dist/intervalIndex/startpointInRangeIndex.d.ts.map +1 -1
- package/dist/intervalIndex/startpointInRangeIndex.js +9 -8
- package/dist/intervalIndex/startpointInRangeIndex.js.map +1 -1
- package/dist/intervalTree.d.ts +1 -1
- package/dist/intervalTree.d.ts.map +1 -1
- package/dist/intervals/interval.d.ts +4 -3
- package/dist/intervals/interval.d.ts.map +1 -1
- package/dist/intervals/interval.js +14 -6
- package/dist/intervals/interval.js.map +1 -1
- package/dist/intervals/intervalUtils.d.ts +42 -20
- package/dist/intervals/intervalUtils.d.ts.map +1 -1
- package/dist/intervals/intervalUtils.js +12 -10
- package/dist/intervals/intervalUtils.js.map +1 -1
- package/dist/intervals/sequenceInterval.d.ts +30 -17
- package/dist/intervals/sequenceInterval.d.ts.map +1 -1
- package/dist/intervals/sequenceInterval.js +124 -45
- package/dist/intervals/sequenceInterval.js.map +1 -1
- 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 +3 -15
- package/dist/revertibles.d.ts.map +1 -1
- package/dist/revertibles.js +6 -17
- package/dist/revertibles.js.map +1 -1
- package/dist/sequence.d.ts +3 -2
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +46 -45
- 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.map +1 -1
- package/dist/sequenceFactory.js +1 -1
- package/dist/sequenceFactory.js.map +1 -1
- package/dist/sharedIntervalCollection.js +9 -9
- package/dist/sharedIntervalCollection.js.map +1 -1
- package/dist/sharedSequence.js +6 -6
- package/dist/sharedSequence.js.map +1 -1
- package/dist/sharedString.d.ts +1 -1
- package/dist/sharedString.d.ts.map +1 -1
- package/dist/sharedString.js +7 -6
- package/dist/sharedString.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/defaultMap.d.ts +1 -1
- package/lib/defaultMap.d.ts.map +1 -1
- package/lib/defaultMap.js +6 -6
- package/lib/defaultMap.js.map +1 -1
- package/lib/defaultMapInterfaces.d.ts +21 -2
- package/lib/defaultMapInterfaces.d.ts.map +1 -1
- package/lib/defaultMapInterfaces.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/intervalCollection.d.ts +140 -22
- package/lib/intervalCollection.d.ts.map +1 -1
- package/lib/intervalCollection.js +144 -50
- package/lib/intervalCollection.js.map +1 -1
- package/lib/intervalIndex/endpointInRangeIndex.d.ts +13 -3
- package/lib/intervalIndex/endpointInRangeIndex.d.ts.map +1 -1
- package/lib/intervalIndex/endpointInRangeIndex.js +9 -7
- package/lib/intervalIndex/endpointInRangeIndex.js.map +1 -1
- package/lib/intervalIndex/endpointIndex.d.ts +13 -2
- package/lib/intervalIndex/endpointIndex.d.ts.map +1 -1
- package/lib/intervalIndex/endpointIndex.js +7 -6
- package/lib/intervalIndex/endpointIndex.js.map +1 -1
- package/lib/intervalIndex/idIntervalIndex.js.map +1 -1
- package/lib/intervalIndex/index.d.ts +4 -4
- package/lib/intervalIndex/index.d.ts.map +1 -1
- package/lib/intervalIndex/index.js +4 -4
- package/lib/intervalIndex/index.js.map +1 -1
- package/lib/intervalIndex/intervalIndex.d.ts +2 -2
- package/lib/intervalIndex/intervalIndex.js.map +1 -1
- package/lib/intervalIndex/overlappingIntervalsIndex.d.ts +8 -6
- package/lib/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -1
- package/lib/intervalIndex/overlappingIntervalsIndex.js +12 -5
- package/lib/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.d.ts +2 -2
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.d.ts.map +1 -1
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js +3 -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 +13 -3
- package/lib/intervalIndex/startpointInRangeIndex.d.ts.map +1 -1
- package/lib/intervalIndex/startpointInRangeIndex.js +9 -9
- package/lib/intervalIndex/startpointInRangeIndex.js.map +1 -1
- package/lib/intervalTree.d.ts +1 -1
- package/lib/intervalTree.d.ts.map +1 -1
- package/lib/intervals/interval.d.ts +4 -3
- package/lib/intervals/interval.d.ts.map +1 -1
- package/lib/intervals/interval.js +14 -6
- package/lib/intervals/interval.js.map +1 -1
- package/lib/intervals/intervalUtils.d.ts +42 -20
- package/lib/intervals/intervalUtils.d.ts.map +1 -1
- package/lib/intervals/intervalUtils.js +8 -6
- package/lib/intervals/intervalUtils.js.map +1 -1
- package/lib/intervals/sequenceInterval.d.ts +30 -17
- package/lib/intervals/sequenceInterval.d.ts.map +1 -1
- package/lib/intervals/sequenceInterval.js +125 -44
- package/lib/intervals/sequenceInterval.js.map +1 -1
- 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 +3 -15
- package/lib/revertibles.d.ts.map +1 -1
- package/lib/revertibles.js +6 -17
- package/lib/revertibles.js.map +1 -1
- package/lib/sequence.d.ts +3 -2
- package/lib/sequence.d.ts.map +1 -1
- package/lib/sequence.js +46 -45
- 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.map +1 -1
- package/lib/sequenceFactory.js +1 -1
- package/lib/sequenceFactory.js.map +1 -1
- package/lib/sharedIntervalCollection.js +9 -9
- package/lib/sharedIntervalCollection.js.map +1 -1
- package/lib/sharedSequence.js +6 -6
- package/lib/sharedSequence.js.map +1 -1
- package/lib/sharedString.d.ts +1 -1
- package/lib/sharedString.d.ts.map +1 -1
- package/lib/sharedString.js +7 -6
- package/lib/sharedString.js.map +1 -1
- package/package.json +49 -23
- package/src/defaultMapInterfaces.ts +21 -2
- package/src/index.ts +4 -1
- package/src/intervalCollection.ts +347 -84
- package/src/intervalIndex/endpointInRangeIndex.ts +19 -11
- package/src/intervalIndex/endpointIndex.ts +16 -9
- package/src/intervalIndex/idIntervalIndex.ts +1 -1
- package/src/intervalIndex/index.ts +12 -3
- package/src/intervalIndex/intervalIndex.ts +2 -2
- package/src/intervalIndex/overlappingIntervalsIndex.ts +31 -15
- package/src/intervalIndex/overlappingSequenceIntervalsIndex.ts +4 -1
- package/src/intervalIndex/sequenceIntervalIndexes.ts +1 -1
- package/src/intervalIndex/startpointInRangeIndex.ts +19 -17
- package/src/intervals/interval.ts +30 -8
- package/src/intervals/intervalUtils.ts +51 -28
- package/src/intervals/sequenceInterval.ts +197 -49
- package/src/packageVersion.ts +1 -1
- package/src/revertibles.ts +8 -33
- package/src/sequence.ts +5 -2
- package/src/sequenceDeltaEvent.ts +11 -3
- package/src/sequenceFactory.ts +1 -1
- package/src/sharedString.ts +2 -1
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.intervalLocatorFromEndpoint = exports.IntervalCollection = exports.makeOpsMap = exports.IntervalCollectionValueType = exports.SequenceIntervalCollectionValueType = exports.LocalIntervalCollection = exports.createIntervalIndex = void 0;
|
|
7
|
+
exports.intervalLocatorFromEndpoint = exports.IntervalCollection = exports.makeOpsMap = exports.IntervalCollectionValueType = exports.SequenceIntervalCollectionValueType = exports.LocalIntervalCollection = exports.createIntervalIndex = exports.computeStickinessFromSide = exports.endpointPosAndSide = exports.sidesFromStickiness = exports.Side = void 0;
|
|
8
8
|
/* eslint-disable no-bitwise */
|
|
9
|
+
/* eslint-disable import/no-deprecated */
|
|
9
10
|
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
10
11
|
const core_utils_1 = require("@fluidframework/core-utils");
|
|
11
12
|
const merge_tree_1 = require("@fluidframework/merge-tree");
|
|
@@ -13,19 +14,39 @@ const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
|
13
14
|
const uuid_1 = require("uuid");
|
|
14
15
|
const intervals_1 = require("./intervals");
|
|
15
16
|
const intervalIndex_1 = require("./intervalIndex");
|
|
17
|
+
/**
|
|
18
|
+
* Defines a side relative to a character in a sequence.
|
|
19
|
+
*
|
|
20
|
+
* @remarks See {@link SequencePlace} for additional context on usage.
|
|
21
|
+
*/
|
|
22
|
+
var Side;
|
|
23
|
+
(function (Side) {
|
|
24
|
+
Side[Side["Before"] = 0] = "Before";
|
|
25
|
+
Side[Side["After"] = 1] = "After";
|
|
26
|
+
})(Side || (exports.Side = Side = {}));
|
|
16
27
|
const reservedIntervalIdKey = "intervalId";
|
|
28
|
+
function sidesFromStickiness(stickiness) {
|
|
29
|
+
const startSide = (stickiness & intervals_1.IntervalStickiness.START) !== 0 ? Side.After : Side.Before;
|
|
30
|
+
const endSide = (stickiness & intervals_1.IntervalStickiness.END) !== 0 ? Side.Before : Side.After;
|
|
31
|
+
return { startSide, endSide };
|
|
32
|
+
}
|
|
33
|
+
exports.sidesFromStickiness = sidesFromStickiness;
|
|
17
34
|
/**
|
|
18
35
|
* Decompress an interval after loading a summary from JSON. The exact format
|
|
19
36
|
* of this compression is unspecified and subject to change
|
|
20
37
|
*/
|
|
21
38
|
function decompressInterval(interval, label) {
|
|
39
|
+
const stickiness = interval[5] ?? intervals_1.IntervalStickiness.END;
|
|
40
|
+
const { startSide, endSide } = sidesFromStickiness(stickiness);
|
|
22
41
|
return {
|
|
23
42
|
start: interval[0],
|
|
24
43
|
end: interval[1],
|
|
25
44
|
sequenceNumber: interval[2],
|
|
26
45
|
intervalType: interval[3],
|
|
27
46
|
properties: { ...interval[4], [merge_tree_1.reservedRangeLabelsKey]: [label] },
|
|
28
|
-
stickiness
|
|
47
|
+
stickiness,
|
|
48
|
+
startSide,
|
|
49
|
+
endSide,
|
|
29
50
|
};
|
|
30
51
|
}
|
|
31
52
|
/**
|
|
@@ -34,7 +55,7 @@ function decompressInterval(interval, label) {
|
|
|
34
55
|
*/
|
|
35
56
|
function compressInterval(interval) {
|
|
36
57
|
const { start, end, sequenceNumber, intervalType, properties } = interval;
|
|
37
|
-
|
|
58
|
+
let base = [
|
|
38
59
|
start,
|
|
39
60
|
end,
|
|
40
61
|
sequenceNumber,
|
|
@@ -44,30 +65,63 @@ function compressInterval(interval) {
|
|
|
44
65
|
{ ...properties, [merge_tree_1.reservedRangeLabelsKey]: undefined },
|
|
45
66
|
];
|
|
46
67
|
if (interval.stickiness !== undefined && interval.stickiness !== intervals_1.IntervalStickiness.END) {
|
|
47
|
-
|
|
68
|
+
// reassignment to make it easier for typescript to reason about types
|
|
69
|
+
base = [...base, interval.stickiness];
|
|
48
70
|
}
|
|
49
71
|
return base;
|
|
50
72
|
}
|
|
73
|
+
function endpointPosAndSide(start, end) {
|
|
74
|
+
const startIsPlainEndpoint = typeof start === "number" || start === "start" || start === "end";
|
|
75
|
+
const endIsPlainEndpoint = typeof end === "number" || end === "start" || end === "end";
|
|
76
|
+
const startSide = startIsPlainEndpoint ? Side.Before : start?.side;
|
|
77
|
+
const endSide = endIsPlainEndpoint ? Side.Before : end?.side;
|
|
78
|
+
const startPos = startIsPlainEndpoint ? start : start?.pos;
|
|
79
|
+
const endPos = endIsPlainEndpoint ? end : end?.pos;
|
|
80
|
+
return {
|
|
81
|
+
startSide,
|
|
82
|
+
endSide,
|
|
83
|
+
startPos,
|
|
84
|
+
endPos,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
exports.endpointPosAndSide = endpointPosAndSide;
|
|
88
|
+
function toSequencePlace(pos, side) {
|
|
89
|
+
return typeof pos === "number" ? { pos, side } : pos;
|
|
90
|
+
}
|
|
91
|
+
function toOptionalSequencePlace(pos, side = Side.Before) {
|
|
92
|
+
return typeof pos === "number" ? { pos, side } : pos;
|
|
93
|
+
}
|
|
94
|
+
function computeStickinessFromSide(startPos = -1, startSide = Side.Before, endPos = -1, endSide = Side.Before) {
|
|
95
|
+
let stickiness = intervals_1.IntervalStickiness.NONE;
|
|
96
|
+
if (startSide === Side.After || startPos === "start") {
|
|
97
|
+
stickiness |= intervals_1.IntervalStickiness.START;
|
|
98
|
+
}
|
|
99
|
+
if (endSide === Side.Before || endPos === "end") {
|
|
100
|
+
stickiness |= intervals_1.IntervalStickiness.END;
|
|
101
|
+
}
|
|
102
|
+
return stickiness;
|
|
103
|
+
}
|
|
104
|
+
exports.computeStickinessFromSide = computeStickinessFromSide;
|
|
51
105
|
function createIntervalIndex() {
|
|
52
106
|
const helpers = {
|
|
53
|
-
compareEnds: (a, b) => a.end - b.end,
|
|
54
107
|
create: intervals_1.createInterval,
|
|
55
108
|
};
|
|
56
|
-
const lc = new LocalIntervalCollection(undefined, "", helpers);
|
|
109
|
+
const lc = new LocalIntervalCollection(undefined, "", helpers, {});
|
|
57
110
|
return lc;
|
|
58
111
|
}
|
|
59
112
|
exports.createIntervalIndex = createIntervalIndex;
|
|
60
113
|
class LocalIntervalCollection {
|
|
61
|
-
constructor(client, label, helpers,
|
|
114
|
+
constructor(client, label, helpers, options,
|
|
62
115
|
/** Callback invoked each time one of the endpoints of an interval slides. */
|
|
63
116
|
onPositionChange) {
|
|
64
117
|
this.client = client;
|
|
65
118
|
this.label = label;
|
|
66
119
|
this.helpers = helpers;
|
|
120
|
+
this.options = options;
|
|
67
121
|
this.onPositionChange = onPositionChange;
|
|
68
|
-
this.overlappingIntervalsIndex =
|
|
122
|
+
this.overlappingIntervalsIndex = new intervalIndex_1.OverlappingIntervalsIndex(client, helpers);
|
|
69
123
|
this.idIntervalIndex = (0, intervalIndex_1.createIdIntervalIndex)();
|
|
70
|
-
this.endIntervalIndex =
|
|
124
|
+
this.endIntervalIndex = new intervalIndex_1.EndpointIndex(client, helpers);
|
|
71
125
|
this.indexes = new Set([
|
|
72
126
|
this.overlappingIntervalsIndex,
|
|
73
127
|
this.idIntervalIndex,
|
|
@@ -121,12 +175,12 @@ class LocalIntervalCollection {
|
|
|
121
175
|
this.removeIntervalFromIndexes(interval);
|
|
122
176
|
this.removeIntervalListeners(interval);
|
|
123
177
|
}
|
|
124
|
-
createInterval(start, end, intervalType, op
|
|
125
|
-
return this.helpers.create(this.label, start, end, this.client, intervalType, op, undefined,
|
|
178
|
+
createInterval(start, end, intervalType, op) {
|
|
179
|
+
return this.helpers.create(this.label, start, end, this.client, intervalType, op, undefined, this.options.mergeTreeReferencesCanSlideToEndpoint);
|
|
126
180
|
}
|
|
127
|
-
addInterval(start, end, intervalType, props, op
|
|
181
|
+
addInterval(start, end, intervalType, props, op) {
|
|
128
182
|
var _a;
|
|
129
|
-
const interval = this.createInterval(start, end, intervalType, op
|
|
183
|
+
const interval = this.createInterval(start, end, intervalType, op);
|
|
130
184
|
if (interval) {
|
|
131
185
|
if (!interval.properties) {
|
|
132
186
|
interval.properties = (0, merge_tree_1.createMap)();
|
|
@@ -163,7 +217,7 @@ class LocalIntervalCollection {
|
|
|
163
217
|
this.addIntervalListeners(interval);
|
|
164
218
|
}
|
|
165
219
|
changeInterval(interval, start, end, op, localSeq) {
|
|
166
|
-
const newInterval = interval.modify(this.label, start, end, op, localSeq);
|
|
220
|
+
const newInterval = interval.modify(this.label, start, end, op, localSeq, this.options.mergeTreeReferencesCanSlideToEndpoint);
|
|
167
221
|
if (newInterval) {
|
|
168
222
|
this.removeExistingInterval(interval);
|
|
169
223
|
this.add(newInterval);
|
|
@@ -186,7 +240,7 @@ class LocalIntervalCollection {
|
|
|
186
240
|
// either, so this must be special-cased.
|
|
187
241
|
return ref;
|
|
188
242
|
}
|
|
189
|
-
return this.client.createLocalReferencePosition(segment, ref.getOffset(), merge_tree_1.ReferenceType.Transient, ref.properties, ref.slidingPreference);
|
|
243
|
+
return this.client.createLocalReferencePosition(segment, ref.getOffset(), merge_tree_1.ReferenceType.Transient, ref.properties, ref.slidingPreference, ref.canSlideToEndpoint);
|
|
190
244
|
};
|
|
191
245
|
if (interval instanceof intervals_1.SequenceInterval) {
|
|
192
246
|
let previousInterval;
|
|
@@ -245,7 +299,6 @@ SequenceIntervalCollectionValueType._ops = makeOpsMap();
|
|
|
245
299
|
class IntervalCollectionFactory {
|
|
246
300
|
load(emitter, raw = [], options) {
|
|
247
301
|
const helpers = {
|
|
248
|
-
compareEnds: (a, b) => a.end - b.end,
|
|
249
302
|
create: intervals_1.createInterval,
|
|
250
303
|
};
|
|
251
304
|
const collection = new IntervalCollection(helpers, false, emitter, raw, options);
|
|
@@ -348,6 +401,9 @@ class IntervalCollectionIterator {
|
|
|
348
401
|
* {@inheritdoc IIntervalCollection}
|
|
349
402
|
*/
|
|
350
403
|
class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
404
|
+
get attached() {
|
|
405
|
+
return !!this.localCollection;
|
|
406
|
+
}
|
|
351
407
|
/** @internal */
|
|
352
408
|
constructor(helpers, requiresClient, emitter, serializedIntervals, options = {}) {
|
|
353
409
|
super();
|
|
@@ -363,9 +419,6 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
363
419
|
? serializedIntervals
|
|
364
420
|
: serializedIntervals.intervals.map((i) => decompressInterval(i, serializedIntervals.label));
|
|
365
421
|
}
|
|
366
|
-
get attached() {
|
|
367
|
-
return !!this.localCollection;
|
|
368
|
-
}
|
|
369
422
|
/**
|
|
370
423
|
* {@inheritdoc IIntervalCollection.attachIndex}
|
|
371
424
|
*/
|
|
@@ -398,6 +451,9 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
398
451
|
if (!this.client) {
|
|
399
452
|
throw new telemetry_utils_1.LoggingError("mergeTree client must exist");
|
|
400
453
|
}
|
|
454
|
+
if (pos === "start" || pos === "end") {
|
|
455
|
+
return pos;
|
|
456
|
+
}
|
|
401
457
|
const { clientId } = this.client.getCollabWindow();
|
|
402
458
|
const { segment, offset } = this.client.getContainingSegment(pos, {
|
|
403
459
|
referenceSequenceNumber: seqNumberFrom,
|
|
@@ -405,7 +461,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
405
461
|
}, localSeq);
|
|
406
462
|
// if segment is undefined, it slid off the string
|
|
407
463
|
(0, core_utils_1.assert)(segment !== undefined, 0x54e /* No segment found */);
|
|
408
|
-
const segoff = (0, merge_tree_1.getSlideToSegoff)({ segment, offset }) ?? segment;
|
|
464
|
+
const segoff = (0, merge_tree_1.getSlideToSegoff)({ segment, offset }, undefined, this.options.mergeTreeReferencesCanSlideToEndpoint) ?? segment;
|
|
409
465
|
// case happens when rebasing op, but concurrently entire string has been deleted
|
|
410
466
|
if (segoff.segment === undefined || segoff.offset === undefined) {
|
|
411
467
|
return merge_tree_1.DetachedReferencePosition;
|
|
@@ -444,12 +500,18 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
444
500
|
}
|
|
445
501
|
});
|
|
446
502
|
}
|
|
447
|
-
this.localCollection = new LocalIntervalCollection(client, label, this.helpers, (interval, previousInterval) => this.emitChange(interval, previousInterval, true, true));
|
|
503
|
+
this.localCollection = new LocalIntervalCollection(client, label, this.helpers, this.options, (interval, previousInterval) => this.emitChange(interval, previousInterval, true, true));
|
|
448
504
|
if (this.savedSerializedIntervals) {
|
|
449
505
|
for (const serializedInterval of this.savedSerializedIntervals) {
|
|
450
506
|
this.localCollection.ensureSerializedId(serializedInterval);
|
|
451
|
-
const { start, end, intervalType, properties,
|
|
452
|
-
const
|
|
507
|
+
const { start: startPos, end: endPos, intervalType, properties, startSide, endSide, } = serializedInterval;
|
|
508
|
+
const start = typeof startPos === "number" && startSide !== undefined
|
|
509
|
+
? { pos: startPos, side: startSide }
|
|
510
|
+
: startPos;
|
|
511
|
+
const end = typeof endPos === "number" && endSide !== undefined
|
|
512
|
+
? { pos: endPos, side: endSide }
|
|
513
|
+
: endPos;
|
|
514
|
+
const interval = this.helpers.create(label, start, end, client, intervalType, undefined, true, this.options.mergeTreeReferencesCanSlideToEndpoint);
|
|
453
515
|
if (properties) {
|
|
454
516
|
interval.addProperties(properties);
|
|
455
517
|
}
|
|
@@ -495,28 +557,44 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
495
557
|
}
|
|
496
558
|
return this.localCollection.idIntervalIndex.getIntervalById(id);
|
|
497
559
|
}
|
|
560
|
+
assertStickinessEnabled(start, end) {
|
|
561
|
+
if (!(typeof start === "number" && typeof end === "number") &&
|
|
562
|
+
!this.options.intervalStickinessEnabled) {
|
|
563
|
+
throw new telemetry_utils_1.UsageError("attempted to set interval stickiness without enabling `intervalStickinessEnabled` feature flag");
|
|
564
|
+
}
|
|
565
|
+
}
|
|
498
566
|
/**
|
|
499
567
|
* {@inheritdoc IIntervalCollection.add}
|
|
500
568
|
*/
|
|
501
|
-
add(start, end, intervalType, props
|
|
569
|
+
add(start, end, intervalType, props) {
|
|
502
570
|
if (!this.localCollection) {
|
|
503
571
|
throw new telemetry_utils_1.LoggingError("attach must be called prior to adding intervals");
|
|
504
572
|
}
|
|
505
573
|
if (intervalType & intervals_1.IntervalType.Transient) {
|
|
506
574
|
throw new telemetry_utils_1.LoggingError("Can not add transient intervals");
|
|
507
575
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
576
|
+
const { startSide, endSide, startPos, endPos } = endpointPosAndSide(start, end);
|
|
577
|
+
(0, core_utils_1.assert)(startPos !== undefined &&
|
|
578
|
+
endPos !== undefined &&
|
|
579
|
+
startSide !== undefined &&
|
|
580
|
+
endSide !== undefined, 0x793 /* start and end cannot be undefined because they were not passed in as undefined */);
|
|
581
|
+
const stickiness = computeStickinessFromSide(startPos, startSide, endPos, endSide);
|
|
582
|
+
this.assertStickinessEnabled(start, end);
|
|
583
|
+
const interval = this.localCollection.addInterval(toSequencePlace(startPos, startSide), toSequencePlace(endPos, endSide), intervalType, props);
|
|
512
584
|
if (interval) {
|
|
585
|
+
if (!this.isCollaborating && interval instanceof intervals_1.SequenceInterval) {
|
|
586
|
+
setSlideOnRemove(interval.start);
|
|
587
|
+
setSlideOnRemove(interval.end);
|
|
588
|
+
}
|
|
513
589
|
const serializedInterval = {
|
|
514
|
-
|
|
590
|
+
start: startPos,
|
|
591
|
+
end: endPos,
|
|
515
592
|
intervalType,
|
|
516
593
|
properties: interval.properties,
|
|
517
594
|
sequenceNumber: this.client?.getCurrentSeq() ?? 0,
|
|
518
|
-
start,
|
|
519
595
|
stickiness,
|
|
596
|
+
startSide,
|
|
597
|
+
endSide,
|
|
520
598
|
};
|
|
521
599
|
const localSeq = this.getNextLocalSeq();
|
|
522
600
|
this.localSeqToSerializedInterval.set(localSeq, serializedInterval);
|
|
@@ -580,8 +658,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
580
658
|
}
|
|
581
659
|
const interval = this.getIntervalById(id);
|
|
582
660
|
if (interval) {
|
|
583
|
-
|
|
584
|
-
const deltaProps = interval.addProperties(props, true, merge_tree_1.UnassignedSequenceNumber);
|
|
661
|
+
const deltaProps = interval.addProperties(props, true, this.isCollaborating ? merge_tree_1.UnassignedSequenceNumber : merge_tree_1.UniversalSequenceNumber);
|
|
585
662
|
const serializedInterval = interval.serialize();
|
|
586
663
|
// Emit a change op that will only change properties. Add the ID to
|
|
587
664
|
// the property bag provided by the caller.
|
|
@@ -612,9 +689,18 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
612
689
|
if (!newInterval) {
|
|
613
690
|
return undefined;
|
|
614
691
|
}
|
|
692
|
+
if (!this.isCollaborating && newInterval instanceof intervals_1.SequenceInterval) {
|
|
693
|
+
setSlideOnRemove(newInterval.start);
|
|
694
|
+
setSlideOnRemove(newInterval.end);
|
|
695
|
+
}
|
|
615
696
|
const serializedInterval = interval.serialize();
|
|
616
|
-
|
|
617
|
-
|
|
697
|
+
const { startPos, startSide, endPos, endSide } = endpointPosAndSide(start, end);
|
|
698
|
+
const stickiness = computeStickinessFromSide(startPos, startSide, endPos, endSide);
|
|
699
|
+
serializedInterval.start = startPos;
|
|
700
|
+
serializedInterval.end = endPos;
|
|
701
|
+
serializedInterval.startSide = startSide;
|
|
702
|
+
serializedInterval.endSide = endSide;
|
|
703
|
+
serializedInterval.stickiness = stickiness;
|
|
618
704
|
// Emit a property bag containing only the ID, as we don't intend for this op to change any properties.
|
|
619
705
|
serializedInterval.properties = {
|
|
620
706
|
[reservedIntervalIdKey]: interval.getIntervalId(),
|
|
@@ -629,7 +715,13 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
629
715
|
// No interval to change
|
|
630
716
|
return undefined;
|
|
631
717
|
}
|
|
718
|
+
get isCollaborating() {
|
|
719
|
+
return this.client?.getCollabWindow().collaborating ?? false;
|
|
720
|
+
}
|
|
632
721
|
addPendingChange(id, serializedInterval) {
|
|
722
|
+
if (!this.isCollaborating) {
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
633
725
|
if (serializedInterval.start !== undefined) {
|
|
634
726
|
this.addPendingChangeHelper(id, this.pendingChangesStart, serializedInterval);
|
|
635
727
|
}
|
|
@@ -722,7 +814,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
722
814
|
// If changeInterval gives us a new interval, work with that one. Otherwise keep working with
|
|
723
815
|
// the one we originally found in the tree.
|
|
724
816
|
newInterval =
|
|
725
|
-
this.localCollection.changeInterval(interval, start, end, op) ?? interval;
|
|
817
|
+
this.localCollection.changeInterval(interval, toOptionalSequencePlace(start, serializedInterval.startSide), toOptionalSequencePlace(end, serializedInterval.endSide), op) ?? interval;
|
|
726
818
|
}
|
|
727
819
|
const deltaProps = newInterval.addProperties(newProps, true, op.sequenceNumber);
|
|
728
820
|
if (this.onDeserialize) {
|
|
@@ -767,7 +859,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
767
859
|
if (!this.attached) {
|
|
768
860
|
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
769
861
|
}
|
|
770
|
-
const { intervalType, properties } = serializedInterval;
|
|
862
|
+
const { intervalType, properties, stickiness, startSide, endSide } = serializedInterval;
|
|
771
863
|
const { start: startRebased, end: endRebased } = this.localSeqToRebasedInterval.get(localSeq) ?? this.computeRebasedPositions(localSeq);
|
|
772
864
|
const intervalId = properties?.[reservedIntervalIdKey];
|
|
773
865
|
const localInterval = this.localCollection?.idIntervalIndex.getIntervalById(intervalId);
|
|
@@ -777,6 +869,9 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
777
869
|
intervalType,
|
|
778
870
|
sequenceNumber: this.client?.getCurrentSeq() ?? 0,
|
|
779
871
|
properties,
|
|
872
|
+
stickiness,
|
|
873
|
+
startSide,
|
|
874
|
+
endSide,
|
|
780
875
|
};
|
|
781
876
|
if (opName === "change" &&
|
|
782
877
|
(this.hasPendingChangeStart(intervalId) || this.hasPendingChangeEnd(intervalId))) {
|
|
@@ -796,7 +891,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
796
891
|
(0, core_utils_1.assert)(localInterval instanceof intervals_1.SequenceInterval, 0x3a0 /* localInterval must be `SequenceInterval` when used with client */);
|
|
797
892
|
// The rebased op may place this interval's endpoints on different segments. Calling `changeInterval` here
|
|
798
893
|
// updates the local client's state to be consistent with the emitted op.
|
|
799
|
-
this.localCollection?.changeInterval(localInterval, startRebased, endRebased, undefined, localSeq);
|
|
894
|
+
this.localCollection?.changeInterval(localInterval, toOptionalSequencePlace(startRebased, startSide), toOptionalSequencePlace(endRebased, endSide), undefined, localSeq);
|
|
800
895
|
}
|
|
801
896
|
return rebased;
|
|
802
897
|
}
|
|
@@ -808,18 +903,12 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
808
903
|
if (segoff.segment?.localRefs?.has(lref) !== true) {
|
|
809
904
|
return undefined;
|
|
810
905
|
}
|
|
811
|
-
const newSegoff = (0, merge_tree_1.getSlideToSegoff)(segoff);
|
|
906
|
+
const newSegoff = (0, merge_tree_1.getSlideToSegoff)(segoff, undefined, this.options.mergeTreeReferencesCanSlideToEndpoint);
|
|
812
907
|
const value = segoff.segment === newSegoff.segment && segoff.offset === newSegoff.offset
|
|
813
908
|
? undefined
|
|
814
909
|
: newSegoff;
|
|
815
910
|
return value;
|
|
816
911
|
}
|
|
817
|
-
setSlideOnRemove(lref) {
|
|
818
|
-
let refType = lref.refType;
|
|
819
|
-
refType = refType & ~merge_tree_1.ReferenceType.StayOnRemove;
|
|
820
|
-
refType = refType | merge_tree_1.ReferenceType.SlideOnRemove;
|
|
821
|
-
lref.refType = refType;
|
|
822
|
-
}
|
|
823
912
|
ackInterval(interval, op) {
|
|
824
913
|
// Only SequenceIntervals need potential sliding
|
|
825
914
|
if (!(interval instanceof intervals_1.SequenceInterval)) {
|
|
@@ -835,10 +924,10 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
835
924
|
const hasPendingStartChange = this.hasPendingChangeStart(id);
|
|
836
925
|
const hasPendingEndChange = this.hasPendingChangeEnd(id);
|
|
837
926
|
if (!hasPendingStartChange) {
|
|
838
|
-
|
|
927
|
+
setSlideOnRemove(interval.start);
|
|
839
928
|
}
|
|
840
929
|
if (!hasPendingEndChange) {
|
|
841
|
-
|
|
930
|
+
setSlideOnRemove(interval.end);
|
|
842
931
|
}
|
|
843
932
|
const needsStartUpdate = newStart !== undefined && !hasPendingStartChange;
|
|
844
933
|
const needsEndUpdate = newEnd !== undefined && !hasPendingEndChange;
|
|
@@ -857,7 +946,8 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
857
946
|
}
|
|
858
947
|
if (needsStartUpdate) {
|
|
859
948
|
const props = interval.start.properties;
|
|
860
|
-
interval.start = (0, intervals_1.createPositionReferenceFromSegoff)(this.client, newStart, interval.start.refType, op, (0, intervals_1.startReferenceSlidingPreference)(interval.stickiness))
|
|
949
|
+
interval.start = (0, intervals_1.createPositionReferenceFromSegoff)(this.client, newStart, interval.start.refType, op, undefined, undefined, (0, intervals_1.startReferenceSlidingPreference)(interval.stickiness), (0, intervals_1.startReferenceSlidingPreference)(interval.stickiness) ===
|
|
950
|
+
merge_tree_1.SlidingPreference.BACKWARD);
|
|
861
951
|
if (props) {
|
|
862
952
|
interval.start.addProperties(props);
|
|
863
953
|
}
|
|
@@ -869,7 +959,8 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
869
959
|
}
|
|
870
960
|
if (needsEndUpdate) {
|
|
871
961
|
const props = interval.end.properties;
|
|
872
|
-
interval.end = (0, intervals_1.createPositionReferenceFromSegoff)(this.client, newEnd, interval.end.refType, op, (0, intervals_1.endReferenceSlidingPreference)(interval.stickiness))
|
|
962
|
+
interval.end = (0, intervals_1.createPositionReferenceFromSegoff)(this.client, newEnd, interval.end.refType, op, undefined, undefined, (0, intervals_1.endReferenceSlidingPreference)(interval.stickiness), (0, intervals_1.endReferenceSlidingPreference)(interval.stickiness) ===
|
|
963
|
+
merge_tree_1.SlidingPreference.FORWARD);
|
|
873
964
|
if (props) {
|
|
874
965
|
interval.end.addProperties(props);
|
|
875
966
|
}
|
|
@@ -899,7 +990,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
899
990
|
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
900
991
|
}
|
|
901
992
|
this.localCollection.ensureSerializedId(serializedInterval);
|
|
902
|
-
const interval = this.localCollection.addInterval(serializedInterval.start, serializedInterval.end, serializedInterval.intervalType, serializedInterval.properties, op
|
|
993
|
+
const interval = this.localCollection.addInterval(toSequencePlace(serializedInterval.start, serializedInterval.startSide ?? Side.Before), toSequencePlace(serializedInterval.end, serializedInterval.endSide ?? Side.Before), serializedInterval.intervalType, serializedInterval.properties, op);
|
|
903
994
|
if (interval) {
|
|
904
995
|
if (this.onDeserialize) {
|
|
905
996
|
this.onDeserialize(interval);
|
|
@@ -1018,6 +1109,12 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
1018
1109
|
}
|
|
1019
1110
|
}
|
|
1020
1111
|
exports.IntervalCollection = IntervalCollection;
|
|
1112
|
+
function setSlideOnRemove(lref) {
|
|
1113
|
+
let refType = lref.refType;
|
|
1114
|
+
refType = refType & ~merge_tree_1.ReferenceType.StayOnRemove;
|
|
1115
|
+
refType = refType | merge_tree_1.ReferenceType.SlideOnRemove;
|
|
1116
|
+
lref.refType = refType;
|
|
1117
|
+
}
|
|
1021
1118
|
/**
|
|
1022
1119
|
* Returns an object that can be used to find the interval a given LocalReferencePosition belongs to.
|
|
1023
1120
|
* @returns undefined if the reference position is not the endpoint of any interval (e.g. it was created
|