@fluidframework/sequence 2.31.1 → 2.33.0-333010
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 +4 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/intervalCollection.d.ts +11 -13
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalCollection.js +96 -149
- package/dist/intervalCollection.js.map +1 -1
- package/dist/intervalCollectionMap.d.ts +4 -4
- package/dist/intervalCollectionMap.d.ts.map +1 -1
- package/dist/intervalCollectionMap.js +16 -49
- package/dist/intervalCollectionMap.js.map +1 -1
- package/dist/intervalCollectionMapInterfaces.d.ts +21 -15
- package/dist/intervalCollectionMapInterfaces.d.ts.map +1 -1
- package/dist/intervalCollectionMapInterfaces.js.map +1 -1
- package/dist/intervalIndex/endpointInRangeIndex.d.ts.map +1 -1
- package/dist/intervalIndex/endpointInRangeIndex.js +2 -2
- package/dist/intervalIndex/endpointInRangeIndex.js.map +1 -1
- package/dist/intervalIndex/endpointIndex.d.ts.map +1 -1
- package/dist/intervalIndex/endpointIndex.js +2 -3
- package/dist/intervalIndex/endpointIndex.js.map +1 -1
- package/dist/intervalIndex/idIntervalIndex.d.ts.map +1 -1
- package/dist/intervalIndex/idIntervalIndex.js +0 -7
- package/dist/intervalIndex/idIntervalIndex.js.map +1 -1
- package/dist/intervalIndex/index.d.ts +0 -1
- package/dist/intervalIndex/index.d.ts.map +1 -1
- package/dist/intervalIndex/index.js +1 -3
- package/dist/intervalIndex/index.js.map +1 -1
- package/dist/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -1
- package/dist/intervalIndex/overlappingIntervalsIndex.js +2 -2
- package/dist/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
- package/dist/intervalIndex/startpointInRangeIndex.d.ts.map +1 -1
- package/dist/intervalIndex/startpointInRangeIndex.js +2 -2
- package/dist/intervalIndex/startpointInRangeIndex.js.map +1 -1
- package/dist/intervals/index.d.ts +2 -2
- package/dist/intervals/index.d.ts.map +1 -1
- package/dist/intervals/index.js +3 -1
- package/dist/intervals/index.js.map +1 -1
- package/dist/intervals/intervalUtils.d.ts +1 -5
- package/dist/intervals/intervalUtils.d.ts.map +1 -1
- package/dist/intervals/intervalUtils.js.map +1 -1
- package/dist/intervals/sequenceInterval.d.ts +20 -9
- package/dist/intervals/sequenceInterval.d.ts.map +1 -1
- package/dist/intervals/sequenceInterval.js +82 -27
- package/dist/intervals/sequenceInterval.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/revertibles.d.ts.map +1 -1
- package/dist/revertibles.js +8 -7
- package/dist/revertibles.js.map +1 -1
- package/lib/index.d.ts +1 -1
- 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 +11 -13
- package/lib/intervalCollection.d.ts.map +1 -1
- package/lib/intervalCollection.js +98 -151
- package/lib/intervalCollection.js.map +1 -1
- package/lib/intervalCollectionMap.d.ts +4 -4
- package/lib/intervalCollectionMap.d.ts.map +1 -1
- package/lib/intervalCollectionMap.js +17 -50
- package/lib/intervalCollectionMap.js.map +1 -1
- package/lib/intervalCollectionMapInterfaces.d.ts +21 -15
- package/lib/intervalCollectionMapInterfaces.d.ts.map +1 -1
- package/lib/intervalCollectionMapInterfaces.js.map +1 -1
- package/lib/intervalIndex/endpointInRangeIndex.d.ts.map +1 -1
- package/lib/intervalIndex/endpointInRangeIndex.js +3 -3
- package/lib/intervalIndex/endpointInRangeIndex.js.map +1 -1
- package/lib/intervalIndex/endpointIndex.d.ts.map +1 -1
- package/lib/intervalIndex/endpointIndex.js +3 -4
- package/lib/intervalIndex/endpointIndex.js.map +1 -1
- package/lib/intervalIndex/idIntervalIndex.d.ts.map +1 -1
- package/lib/intervalIndex/idIntervalIndex.js +0 -7
- package/lib/intervalIndex/idIntervalIndex.js.map +1 -1
- package/lib/intervalIndex/index.d.ts +0 -1
- package/lib/intervalIndex/index.d.ts.map +1 -1
- package/lib/intervalIndex/index.js +0 -1
- package/lib/intervalIndex/index.js.map +1 -1
- package/lib/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -1
- package/lib/intervalIndex/overlappingIntervalsIndex.js +3 -3
- package/lib/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
- package/lib/intervalIndex/startpointInRangeIndex.d.ts.map +1 -1
- package/lib/intervalIndex/startpointInRangeIndex.js +3 -3
- package/lib/intervalIndex/startpointInRangeIndex.js.map +1 -1
- package/lib/intervals/index.d.ts +2 -2
- package/lib/intervals/index.d.ts.map +1 -1
- package/lib/intervals/index.js +1 -1
- package/lib/intervals/index.js.map +1 -1
- package/lib/intervals/intervalUtils.d.ts +1 -5
- package/lib/intervals/intervalUtils.d.ts.map +1 -1
- package/lib/intervals/intervalUtils.js.map +1 -1
- package/lib/intervals/sequenceInterval.d.ts +20 -9
- package/lib/intervals/sequenceInterval.d.ts.map +1 -1
- package/lib/intervals/sequenceInterval.js +81 -28
- package/lib/intervals/sequenceInterval.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/revertibles.d.ts.map +1 -1
- package/lib/revertibles.js +8 -7
- package/lib/revertibles.js.map +1 -1
- package/package.json +19 -18
- package/src/index.ts +0 -1
- package/src/intervalCollection.ts +135 -198
- package/src/intervalCollectionMap.ts +19 -61
- package/src/intervalCollectionMapInterfaces.ts +33 -29
- package/src/intervalIndex/endpointInRangeIndex.ts +3 -15
- package/src/intervalIndex/endpointIndex.ts +3 -17
- package/src/intervalIndex/idIntervalIndex.ts +0 -7
- package/src/intervalIndex/index.ts +0 -1
- package/src/intervalIndex/overlappingIntervalsIndex.ts +3 -12
- package/src/intervalIndex/startpointInRangeIndex.ts +3 -15
- package/src/intervals/index.ts +2 -1
- package/src/intervals/intervalUtils.ts +0 -7
- package/src/intervals/sequenceInterval.ts +124 -33
- package/src/packageVersion.ts +1 -1
- package/src/revertibles.ts +8 -7
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.d.ts +0 -11
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.d.ts.map +0 -1
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js +0 -38
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js.map +0 -1
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.d.ts +0 -11
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.d.ts.map +0 -1
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js +0 -34
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js.map +0 -1
- package/src/intervalIndex/overlappingSequenceIntervalsIndex.ts +0 -80
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.intervalLocatorFromEndpoint = exports.IntervalCollection = exports.
|
|
7
|
+
exports.intervalLocatorFromEndpoint = exports.IntervalCollection = exports.LocalIntervalCollection = exports.computeStickinessFromSide = exports.toOptionalSequencePlace = exports.toSequencePlace = exports.sidesFromStickiness = void 0;
|
|
8
8
|
/* eslint-disable no-bitwise */
|
|
9
9
|
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
10
10
|
const internal_1 = require("@fluidframework/core-utils/internal");
|
|
@@ -13,7 +13,6 @@ const internal_3 = require("@fluidframework/telemetry-utils/internal");
|
|
|
13
13
|
const uuid_1 = require("uuid");
|
|
14
14
|
const index_js_1 = require("./intervalIndex/index.js");
|
|
15
15
|
const index_js_2 = require("./intervals/index.js");
|
|
16
|
-
exports.reservedIntervalIdKey = "intervalId";
|
|
17
16
|
function sidesFromStickiness(stickiness) {
|
|
18
17
|
const startSide = (stickiness & index_js_2.IntervalStickiness.START) !== 0 ? internal_2.Side.After : internal_2.Side.Before;
|
|
19
18
|
const endSide = (stickiness & index_js_2.IntervalStickiness.END) !== 0 ? internal_2.Side.Before : internal_2.Side.After;
|
|
@@ -95,11 +94,6 @@ class LocalIntervalCollection {
|
|
|
95
94
|
this.endIntervalIndex,
|
|
96
95
|
]);
|
|
97
96
|
}
|
|
98
|
-
createLegacyId(start, end) {
|
|
99
|
-
// Create a non-unique ID based on start and end to be used on intervals that come from legacy clients
|
|
100
|
-
// without ID's.
|
|
101
|
-
return `${LocalIntervalCollection.legacyIdPrefix}${start}-${end}`;
|
|
102
|
-
}
|
|
103
97
|
/**
|
|
104
98
|
* Validates that a serialized interval has the ID property. Creates an ID
|
|
105
99
|
* if one does not already exist
|
|
@@ -107,26 +101,6 @@ class LocalIntervalCollection {
|
|
|
107
101
|
* @param serializedInterval - The interval to be checked
|
|
108
102
|
* @returns The interval's existing or newly created id
|
|
109
103
|
*/
|
|
110
|
-
ensureSerializedId(serializedInterval) {
|
|
111
|
-
let id = serializedInterval.properties?.[exports.reservedIntervalIdKey];
|
|
112
|
-
if (id === undefined) {
|
|
113
|
-
// Back-compat: 0.39 and earlier did not have IDs on intervals. If an interval from such a client
|
|
114
|
-
// comes over the wire, create a non-unique one based on start/end.
|
|
115
|
-
// This will allow all clients to refer to this interval consistently.
|
|
116
|
-
id = this.createLegacyId(serializedInterval.start, serializedInterval.end);
|
|
117
|
-
const newProps = {
|
|
118
|
-
[exports.reservedIntervalIdKey]: id,
|
|
119
|
-
};
|
|
120
|
-
serializedInterval.properties = (0, internal_2.addProperties)(serializedInterval.properties, newProps);
|
|
121
|
-
}
|
|
122
|
-
// Make the ID immutable for safety's sake.
|
|
123
|
-
Object.defineProperty(serializedInterval.properties, exports.reservedIntervalIdKey, {
|
|
124
|
-
configurable: false,
|
|
125
|
-
enumerable: true,
|
|
126
|
-
writable: false,
|
|
127
|
-
});
|
|
128
|
-
return id;
|
|
129
|
-
}
|
|
130
104
|
removeIntervalFromIndexes(interval) {
|
|
131
105
|
for (const index of this.indexes) {
|
|
132
106
|
index.remove(interval);
|
|
@@ -142,28 +116,16 @@ class LocalIntervalCollection {
|
|
|
142
116
|
this.removeIntervalFromIndexes(interval);
|
|
143
117
|
this.removeIntervalListeners(interval);
|
|
144
118
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
interval.properties = (0, internal_2.createMap)();
|
|
153
|
-
}
|
|
154
|
-
if (props) {
|
|
155
|
-
// This check is intended to prevent scenarios where a random interval is created and then
|
|
156
|
-
// inserted into a collection. The aim is to ensure that the collection is created first
|
|
157
|
-
// then the user can create/add intervals based on the collection
|
|
158
|
-
if (props[internal_2.reservedRangeLabelsKey] !== undefined &&
|
|
159
|
-
props[internal_2.reservedRangeLabelsKey][0] !== this.label) {
|
|
160
|
-
throw new internal_3.LoggingError("Adding an interval that belongs to another interval collection is not permitted");
|
|
161
|
-
}
|
|
162
|
-
interval.properties = (0, internal_2.addProperties)(interval.properties, props);
|
|
163
|
-
}
|
|
164
|
-
interval.properties[exports.reservedIntervalIdKey] ??= (0, uuid_1.v4)();
|
|
165
|
-
this.add(interval);
|
|
119
|
+
addInterval(id, start, end, props, op) {
|
|
120
|
+
// This check is intended to prevent scenarios where a random interval is created and then
|
|
121
|
+
// inserted into a collection. The aim is to ensure that the collection is created first
|
|
122
|
+
// then the user can create/add intervals based on the collection
|
|
123
|
+
if (props?.[internal_2.reservedRangeLabelsKey] !== undefined &&
|
|
124
|
+
props[internal_2.reservedRangeLabelsKey][0] !== this.label) {
|
|
125
|
+
throw new internal_3.LoggingError("Adding an interval that belongs to another interval collection is not permitted");
|
|
166
126
|
}
|
|
127
|
+
const interval = (0, index_js_2.createSequenceInterval)(this.label, id, start, end, this.client, index_js_2.IntervalType.SlideOnRemove, op, undefined, this.options.mergeTreeReferencesCanSlideToEndpoint, props);
|
|
128
|
+
this.add(interval);
|
|
167
129
|
return interval;
|
|
168
130
|
}
|
|
169
131
|
linkEndpointsToInterval(interval) {
|
|
@@ -235,52 +197,6 @@ class LocalIntervalCollection {
|
|
|
235
197
|
}
|
|
236
198
|
}
|
|
237
199
|
exports.LocalIntervalCollection = LocalIntervalCollection;
|
|
238
|
-
LocalIntervalCollection.legacyIdPrefix = "legacy";
|
|
239
|
-
const rebase = (collection, op, localOpMetadata) => {
|
|
240
|
-
const { localSeq } = localOpMetadata;
|
|
241
|
-
const rebasedValue = collection.rebaseLocalInterval(op.opName, op.value, localSeq);
|
|
242
|
-
if (rebasedValue === undefined) {
|
|
243
|
-
return undefined;
|
|
244
|
-
}
|
|
245
|
-
const rebasedOp = { ...op, value: rebasedValue };
|
|
246
|
-
return { rebasedOp, rebasedLocalOpMetadata: localOpMetadata };
|
|
247
|
-
};
|
|
248
|
-
exports.opsMap = {
|
|
249
|
-
[index_js_2.IntervalDeltaOpType.ADD]: {
|
|
250
|
-
process: (collection, params, local, op, localOpMetadata) => {
|
|
251
|
-
// if params is undefined, the interval was deleted during
|
|
252
|
-
// rebasing
|
|
253
|
-
if (!params) {
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
(0, internal_1.assert)(op !== undefined, 0x3fb /* op should exist here */);
|
|
257
|
-
collection.ackAdd(params, local, op, localOpMetadata);
|
|
258
|
-
},
|
|
259
|
-
rebase,
|
|
260
|
-
},
|
|
261
|
-
[index_js_2.IntervalDeltaOpType.DELETE]: {
|
|
262
|
-
process: (collection, params, local, op) => {
|
|
263
|
-
(0, internal_1.assert)(op !== undefined, 0x3fc /* op should exist here */);
|
|
264
|
-
collection.ackDelete(params, local, op);
|
|
265
|
-
},
|
|
266
|
-
rebase: (collection, op, localOpMetadata) => {
|
|
267
|
-
// Deletion of intervals is based on id, so requires no rebasing.
|
|
268
|
-
return { rebasedOp: op, rebasedLocalOpMetadata: localOpMetadata };
|
|
269
|
-
},
|
|
270
|
-
},
|
|
271
|
-
[index_js_2.IntervalDeltaOpType.CHANGE]: {
|
|
272
|
-
process: (collection, params, local, op, localOpMetadata) => {
|
|
273
|
-
// if params is undefined, the interval was deleted during
|
|
274
|
-
// rebasing
|
|
275
|
-
if (!params) {
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
(0, internal_1.assert)(op !== undefined, 0x3fd /* op should exist here */);
|
|
279
|
-
collection.ackChange(params, local, op, localOpMetadata);
|
|
280
|
-
},
|
|
281
|
-
rebase,
|
|
282
|
-
},
|
|
283
|
-
};
|
|
284
200
|
class IntervalCollectionIterator {
|
|
285
201
|
constructor(collection, iteratesForward = true, start, end) {
|
|
286
202
|
this.results = [];
|
|
@@ -347,6 +263,64 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
347
263
|
}
|
|
348
264
|
return true;
|
|
349
265
|
}
|
|
266
|
+
process(op, local, message, localOpMetadata) {
|
|
267
|
+
const { opName, value } = op;
|
|
268
|
+
switch (opName) {
|
|
269
|
+
case "add": {
|
|
270
|
+
this.ackAdd(value, local, message, localOpMetadata);
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
case "delete": {
|
|
274
|
+
this.ackDelete(value, local, message);
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
case "change": {
|
|
278
|
+
this.ackChange(value, local, message, localOpMetadata);
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
default:
|
|
282
|
+
(0, internal_1.unreachableCase)(opName);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
resubmitMessage(op, localOpMetadata) {
|
|
286
|
+
const { opName, value } = op;
|
|
287
|
+
const { localSeq } = localOpMetadata;
|
|
288
|
+
const rebasedValue = opName === "delete" ? value : this.rebaseLocalInterval(opName, value, localSeq);
|
|
289
|
+
if (rebasedValue === undefined) {
|
|
290
|
+
return undefined;
|
|
291
|
+
}
|
|
292
|
+
this.submitDelta({ opName, value: rebasedValue }, localOpMetadata);
|
|
293
|
+
}
|
|
294
|
+
applyStashedOp(op) {
|
|
295
|
+
const { opName, value } = op;
|
|
296
|
+
const { id, properties } = (0, index_js_2.getSerializedProperties)(value);
|
|
297
|
+
switch (opName) {
|
|
298
|
+
case "add": {
|
|
299
|
+
this.add({
|
|
300
|
+
id,
|
|
301
|
+
// Todo: we should improve typing so we know add ops always have start and end
|
|
302
|
+
start: toSequencePlace(value.start, value.startSide),
|
|
303
|
+
end: toSequencePlace(value.end, value.endSide),
|
|
304
|
+
props: properties,
|
|
305
|
+
});
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
case "change": {
|
|
309
|
+
this.change(id, {
|
|
310
|
+
start: toOptionalSequencePlace(value.start, value.startSide),
|
|
311
|
+
end: toOptionalSequencePlace(value.end, value.endSide),
|
|
312
|
+
props: properties,
|
|
313
|
+
});
|
|
314
|
+
break;
|
|
315
|
+
}
|
|
316
|
+
case "delete": {
|
|
317
|
+
this.removeIntervalById(id);
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
default:
|
|
321
|
+
throw new Error("unknown ops should not be stashed");
|
|
322
|
+
}
|
|
323
|
+
}
|
|
350
324
|
rebasePositionWithSegmentSlide(pos, seqNumberFrom, localSeq) {
|
|
351
325
|
if (!this.client) {
|
|
352
326
|
throw new internal_3.LoggingError("mergeTree client must exist");
|
|
@@ -361,7 +335,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
361
335
|
}, localSeq);
|
|
362
336
|
// if segment is undefined, it slid off the string
|
|
363
337
|
(0, internal_1.assert)(segment !== undefined, 0x54e /* No segment found */);
|
|
364
|
-
const segoff = (0, internal_2.getSlideToSegoff)({ segment, offset }, undefined, this.options.mergeTreeReferencesCanSlideToEndpoint) ?? segment;
|
|
338
|
+
const segoff = (0, internal_2.getSlideToSegoff)({ segment, offset }, undefined, (0, internal_2.createLocalReconnectingPerspective)(this.client.getCurrentSeq(), clientId, localSeq), this.options.mergeTreeReferencesCanSlideToEndpoint) ?? segment;
|
|
365
339
|
// case happens when rebasing op, but concurrently entire string has been deleted
|
|
366
340
|
if (segoff.segment === undefined || segoff.offset === undefined) {
|
|
367
341
|
return internal_2.DetachedReferencePosition;
|
|
@@ -402,18 +376,15 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
402
376
|
this.localCollection = new LocalIntervalCollection(client, label, this.options, (interval, previousInterval) => this.emitChange(interval, previousInterval, true, true));
|
|
403
377
|
if (this.savedSerializedIntervals) {
|
|
404
378
|
for (const serializedInterval of this.savedSerializedIntervals) {
|
|
405
|
-
|
|
406
|
-
const { start: startPos, end: endPos, intervalType,
|
|
379
|
+
const { id, properties } = (0, index_js_2.getSerializedProperties)(serializedInterval);
|
|
380
|
+
const { start: startPos, end: endPos, intervalType, startSide, endSide, } = serializedInterval;
|
|
407
381
|
const start = typeof startPos === "number" && startSide !== undefined
|
|
408
382
|
? { pos: startPos, side: startSide }
|
|
409
383
|
: startPos;
|
|
410
384
|
const end = typeof endPos === "number" && endSide !== undefined
|
|
411
385
|
? { pos: endPos, side: endSide }
|
|
412
386
|
: endPos;
|
|
413
|
-
const interval = (0, index_js_2.createSequenceInterval)(label, start, end, client, intervalType, undefined, true, this.options.mergeTreeReferencesCanSlideToEndpoint);
|
|
414
|
-
if (properties) {
|
|
415
|
-
interval.properties = (0, internal_2.addProperties)(interval.properties, properties);
|
|
416
|
-
}
|
|
387
|
+
const interval = (0, index_js_2.createSequenceInterval)(label, id, start, end, client, intervalType, undefined, true, this.options.mergeTreeReferencesCanSlideToEndpoint, properties);
|
|
417
388
|
this.localCollection.add(interval);
|
|
418
389
|
}
|
|
419
390
|
}
|
|
@@ -459,7 +430,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
459
430
|
/**
|
|
460
431
|
* {@inheritdoc IIntervalCollection.add}
|
|
461
432
|
*/
|
|
462
|
-
add({ start, end, props, }) {
|
|
433
|
+
add({ id, start, end, props, }) {
|
|
463
434
|
if (!this.localCollection) {
|
|
464
435
|
throw new internal_3.LoggingError("attach must be called prior to adding intervals");
|
|
465
436
|
}
|
|
@@ -468,24 +439,14 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
468
439
|
endPos !== undefined &&
|
|
469
440
|
startSide !== undefined &&
|
|
470
441
|
endSide !== undefined, 0x793 /* start and end cannot be undefined because they were not passed in as undefined */);
|
|
471
|
-
const stickiness = computeStickinessFromSide(startPos, startSide, endPos, endSide);
|
|
472
442
|
this.assertStickinessEnabled(start, end);
|
|
473
|
-
const interval = this.localCollection.addInterval(toSequencePlace(startPos, startSide), toSequencePlace(endPos, endSide),
|
|
443
|
+
const interval = this.localCollection.addInterval(id ?? (0, uuid_1.v4)(), toSequencePlace(startPos, startSide), toSequencePlace(endPos, endSide), props);
|
|
474
444
|
if (interval) {
|
|
475
445
|
if (!this.isCollaborating) {
|
|
476
446
|
setSlideOnRemove(interval.start);
|
|
477
447
|
setSlideOnRemove(interval.end);
|
|
478
448
|
}
|
|
479
|
-
const serializedInterval =
|
|
480
|
-
start: startPos,
|
|
481
|
-
end: endPos,
|
|
482
|
-
intervalType: index_js_2.IntervalType.SlideOnRemove,
|
|
483
|
-
properties: { ...interval.properties },
|
|
484
|
-
sequenceNumber: this.client?.getCurrentSeq() ?? 0,
|
|
485
|
-
stickiness,
|
|
486
|
-
startSide,
|
|
487
|
-
endSide,
|
|
488
|
-
};
|
|
449
|
+
const serializedInterval = interval.serialize();
|
|
489
450
|
const localSeq = this.getNextLocalSeq();
|
|
490
451
|
if (this.isCollaborating) {
|
|
491
452
|
this.localSeqToSerializedInterval.set(localSeq, serializedInterval);
|
|
@@ -562,29 +523,21 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
562
523
|
let deltaProps;
|
|
563
524
|
let newInterval;
|
|
564
525
|
if (props !== undefined) {
|
|
565
|
-
|
|
566
|
-
deltaProps = interval.propertyManager.handleProperties({ props }, interval, this.isCollaborating ? internal_2.UnassignedSequenceNumber : internal_2.UniversalSequenceNumber, internal_2.UniversalSequenceNumber, true);
|
|
526
|
+
deltaProps = interval.changeProperties(props);
|
|
567
527
|
}
|
|
568
|
-
|
|
528
|
+
const changeEndpoints = start !== undefined && end !== undefined;
|
|
529
|
+
if (changeEndpoints) {
|
|
569
530
|
newInterval = this.localCollection.changeInterval(interval, start, end);
|
|
570
531
|
if (!this.isCollaborating && newInterval !== undefined) {
|
|
571
532
|
setSlideOnRemove(newInterval.start);
|
|
572
533
|
setSlideOnRemove(newInterval.end);
|
|
573
534
|
}
|
|
574
535
|
}
|
|
575
|
-
const serializedInterval = interval.serialize();
|
|
576
|
-
const { startPos, startSide, endPos, endSide } = (0, internal_2.endpointPosAndSide)(start, end);
|
|
577
|
-
const stickiness = computeStickinessFromSide(startPos, startSide, endPos, endSide);
|
|
578
|
-
serializedInterval.start = startPos;
|
|
579
|
-
serializedInterval.end = endPos;
|
|
580
|
-
serializedInterval.startSide = startSide;
|
|
581
|
-
serializedInterval.endSide = endSide;
|
|
582
|
-
serializedInterval.stickiness = stickiness;
|
|
583
536
|
// Emit a property bag containing the ID and the other (if any) properties changed
|
|
584
|
-
serializedInterval
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
};
|
|
537
|
+
const serializedInterval = (newInterval ?? interval).serializeDelta({
|
|
538
|
+
props,
|
|
539
|
+
includeEndpoints: changeEndpoints,
|
|
540
|
+
});
|
|
588
541
|
const localSeq = this.getNextLocalSeq();
|
|
589
542
|
if (this.isCollaborating) {
|
|
590
543
|
this.localSeqToSerializedInterval.set(localSeq, serializedInterval);
|
|
@@ -634,7 +587,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
634
587
|
}
|
|
635
588
|
removePendingChange(serializedInterval) {
|
|
636
589
|
// Change ops always have an ID.
|
|
637
|
-
const id = serializedInterval
|
|
590
|
+
const { id } = (0, index_js_2.getSerializedProperties)(serializedInterval);
|
|
638
591
|
if (serializedInterval.start !== undefined) {
|
|
639
592
|
this.removePendingChangeHelper(id, this.pendingChangesStart, serializedInterval);
|
|
640
593
|
}
|
|
@@ -676,7 +629,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
676
629
|
// Note that the ID is in the property bag only to allow us to find the interval.
|
|
677
630
|
// This API cannot change the ID, and writing to the ID property will result in an exception. So we
|
|
678
631
|
// strip it out of the properties here.
|
|
679
|
-
const {
|
|
632
|
+
const { id, properties } = (0, index_js_2.getSerializedProperties)(serializedInterval);
|
|
680
633
|
(0, internal_1.assert)(id !== undefined, 0x3fe /* id must exist on the interval */);
|
|
681
634
|
const interval = this.getIntervalById(id);
|
|
682
635
|
if (!interval) {
|
|
@@ -684,11 +637,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
684
637
|
return;
|
|
685
638
|
}
|
|
686
639
|
if (local) {
|
|
687
|
-
interval.
|
|
688
|
-
// Let the propertyManager prune its pending change-properties set.
|
|
689
|
-
interval.propertyManager.ack(op.sequenceNumber, op.minimumSequenceNumber, {
|
|
690
|
-
props: newProps,
|
|
691
|
-
});
|
|
640
|
+
interval.ackPropertiesChange(properties, op);
|
|
692
641
|
this.ackInterval(interval, op);
|
|
693
642
|
}
|
|
694
643
|
else {
|
|
@@ -710,15 +659,14 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
710
659
|
newInterval =
|
|
711
660
|
this.localCollection.changeInterval(interval, toOptionalSequencePlace(start, serializedInterval.startSide ?? internal_2.Side.Before), toOptionalSequencePlace(end, serializedInterval.endSide ?? internal_2.Side.Before), op) ?? interval;
|
|
712
661
|
}
|
|
713
|
-
|
|
714
|
-
const deltaProps = newInterval.propertyManager.handleProperties({ props: newProps }, newInterval, op.sequenceNumber, op.minimumSequenceNumber, true);
|
|
662
|
+
const deltaProps = newInterval.changeProperties(properties, op);
|
|
715
663
|
if (this.onDeserialize) {
|
|
716
664
|
this.onDeserialize(newInterval);
|
|
717
665
|
}
|
|
718
666
|
if (newInterval !== interval) {
|
|
719
667
|
this.emitChange(newInterval, interval, local, false, op);
|
|
720
668
|
}
|
|
721
|
-
const changedProperties = Object.keys(
|
|
669
|
+
const changedProperties = Object.keys(properties).length > 0;
|
|
722
670
|
if (changedProperties) {
|
|
723
671
|
this.emit("propertyChanged", interval, deltaProps, local, op);
|
|
724
672
|
this.emit("changed", interval, deltaProps, undefined, local, false);
|
|
@@ -755,9 +703,9 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
755
703
|
throw new internal_3.LoggingError("attachSequence must be called");
|
|
756
704
|
}
|
|
757
705
|
const { intervalType, properties, stickiness, startSide, endSide } = serializedInterval;
|
|
706
|
+
const { id } = (0, index_js_2.getSerializedProperties)(serializedInterval);
|
|
758
707
|
const { start: startRebased, end: endRebased } = this.localSeqToRebasedInterval.get(localSeq) ?? this.computeRebasedPositions(localSeq);
|
|
759
|
-
const
|
|
760
|
-
const localInterval = this.localCollection?.idIntervalIndex.getIntervalById(intervalId);
|
|
708
|
+
const localInterval = this.localCollection?.idIntervalIndex.getIntervalById(id);
|
|
761
709
|
const rebased = {
|
|
762
710
|
start: startRebased,
|
|
763
711
|
end: endRebased,
|
|
@@ -770,9 +718,9 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
770
718
|
};
|
|
771
719
|
if (opName === "change" &&
|
|
772
720
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- ?? is not logically equivalent when .hasPendingChangeStart returns false.
|
|
773
|
-
(this.hasPendingChangeStart(
|
|
721
|
+
(this.hasPendingChangeStart(id) || this.hasPendingChangeEnd(id))) {
|
|
774
722
|
this.removePendingChange(serializedInterval);
|
|
775
|
-
this.addPendingChange(
|
|
723
|
+
this.addPendingChange(id, rebased);
|
|
776
724
|
}
|
|
777
725
|
// if the interval slid off the string, rebase the op to be a noop and delete the interval.
|
|
778
726
|
if (!this.options.mergeTreeReferencesCanSlideToEndpoint &&
|
|
@@ -800,7 +748,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
800
748
|
if (segoff.segment?.localRefs?.has(lref) !== true) {
|
|
801
749
|
return undefined;
|
|
802
750
|
}
|
|
803
|
-
const newSegoff = (0, internal_2.getSlideToSegoff)(segoff, slidingPreference, this.options.mergeTreeReferencesCanSlideToEndpoint);
|
|
751
|
+
const newSegoff = (0, internal_2.getSlideToSegoff)(segoff, slidingPreference, undefined, this.options.mergeTreeReferencesCanSlideToEndpoint);
|
|
804
752
|
const value = segoff.segment === newSegoff.segment && segoff.offset === newSegoff.offset
|
|
805
753
|
? undefined
|
|
806
754
|
: newSegoff;
|
|
@@ -813,7 +761,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
813
761
|
}
|
|
814
762
|
const newStart = this.getSlideToSegment(interval.start, (0, index_js_2.startReferenceSlidingPreference)(interval.stickiness));
|
|
815
763
|
const newEnd = this.getSlideToSegment(interval.end, (0, index_js_2.endReferenceSlidingPreference)(interval.stickiness));
|
|
816
|
-
const id = interval.
|
|
764
|
+
const id = interval.getIntervalId();
|
|
817
765
|
const hasPendingStartChange = this.hasPendingChangeStart(id);
|
|
818
766
|
const hasPendingEndChange = this.hasPendingChangeEnd(id);
|
|
819
767
|
if (!hasPendingStartChange) {
|
|
@@ -866,10 +814,10 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
866
814
|
}
|
|
867
815
|
}
|
|
868
816
|
ackAdd(serializedInterval, local, op, localOpMetadata) {
|
|
817
|
+
const { id, properties } = (0, index_js_2.getSerializedProperties)(serializedInterval);
|
|
869
818
|
if (local) {
|
|
870
819
|
(0, internal_1.assert)(localOpMetadata !== undefined, 0x553 /* op metadata should be defined for local op */);
|
|
871
820
|
this.localSeqToSerializedInterval.delete(localOpMetadata.localSeq);
|
|
872
|
-
const id = serializedInterval.properties?.[exports.reservedIntervalIdKey];
|
|
873
821
|
const localInterval = this.getIntervalById(id);
|
|
874
822
|
if (localInterval) {
|
|
875
823
|
this.ackInterval(localInterval, op);
|
|
@@ -879,8 +827,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
879
827
|
if (!this.localCollection) {
|
|
880
828
|
throw new internal_3.LoggingError("attachSequence must be called");
|
|
881
829
|
}
|
|
882
|
-
this.localCollection.
|
|
883
|
-
const interval = this.localCollection.addInterval(toSequencePlace(serializedInterval.start, serializedInterval.startSide ?? internal_2.Side.Before), toSequencePlace(serializedInterval.end, serializedInterval.endSide ?? internal_2.Side.Before), serializedInterval.intervalType, serializedInterval.properties, op);
|
|
830
|
+
const interval = this.localCollection.addInterval(id, toSequencePlace(serializedInterval.start, serializedInterval.startSide ?? internal_2.Side.Before), toSequencePlace(serializedInterval.end, serializedInterval.endSide ?? internal_2.Side.Before), properties, op);
|
|
884
831
|
if (interval) {
|
|
885
832
|
if (this.onDeserialize) {
|
|
886
833
|
this.onDeserialize(interval);
|
|
@@ -899,7 +846,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
|
|
|
899
846
|
if (!this.localCollection) {
|
|
900
847
|
throw new internal_3.LoggingError("attach must be called prior to deleting intervals");
|
|
901
848
|
}
|
|
902
|
-
const id =
|
|
849
|
+
const { id } = (0, index_js_2.getSerializedProperties)(serializedInterval);
|
|
903
850
|
const interval = this.localCollection.idIntervalIndex.getIntervalById(id);
|
|
904
851
|
if (interval) {
|
|
905
852
|
this.deleteExistingInterval(interval, local, op);
|