@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,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
/* eslint-disable no-bitwise */
|
|
7
|
+
/* eslint-disable import/no-deprecated */
|
|
7
8
|
|
|
8
9
|
import {
|
|
9
10
|
Client,
|
|
@@ -26,6 +27,13 @@ import {
|
|
|
26
27
|
import { assert } from "@fluidframework/core-utils";
|
|
27
28
|
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
28
29
|
import { UsageError } from "@fluidframework/telemetry-utils";
|
|
30
|
+
import {
|
|
31
|
+
SequencePlace,
|
|
32
|
+
Side,
|
|
33
|
+
computeStickinessFromSide,
|
|
34
|
+
endpointPosAndSide,
|
|
35
|
+
sidesFromStickiness,
|
|
36
|
+
} from "../intervalCollection";
|
|
29
37
|
import {
|
|
30
38
|
IIntervalHelpers,
|
|
31
39
|
ISerializableInterval,
|
|
@@ -38,14 +46,42 @@ import {
|
|
|
38
46
|
|
|
39
47
|
const reservedIntervalIdKey = "intervalId";
|
|
40
48
|
|
|
49
|
+
function compareSides(sideA: Side, sideB: Side): number {
|
|
50
|
+
if (sideA === sideB) {
|
|
51
|
+
return 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (sideA === Side.Before) {
|
|
55
|
+
return 1;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return -1;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function minSide(sideA: Side, sideB: Side): Side {
|
|
62
|
+
if (sideA === Side.After && sideB === Side.After) {
|
|
63
|
+
return Side.After;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return Side.Before;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function maxSide(sideA: Side, sideB: Side): Side {
|
|
70
|
+
if (sideA === Side.Before && sideB === Side.Before) {
|
|
71
|
+
return Side.Before;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return Side.After;
|
|
75
|
+
}
|
|
76
|
+
|
|
41
77
|
/**
|
|
42
78
|
* Interval implementation whose ends are associated with positions in a mutatable sequence.
|
|
43
79
|
* As such, when content is inserted into the middle of the interval, the interval expands to
|
|
44
80
|
* include that content.
|
|
45
81
|
*
|
|
46
|
-
* @remarks
|
|
47
|
-
* an interval referring to "hello" in "hello world"
|
|
48
|
-
* position of 5.
|
|
82
|
+
* @remarks The endpoints' positions should be treated exclusively to get
|
|
83
|
+
* reasonable behavior. E.g., an interval referring to "hello" in "hello world"
|
|
84
|
+
* should have a start position of 0 and an end position of 5.
|
|
49
85
|
*
|
|
50
86
|
* To see why, consider what happens if "llo wor" is removed from the string to make "held".
|
|
51
87
|
* The interval's startpoint remains on the "h" (it isn't altered), but the interval's endpoint
|
|
@@ -55,9 +91,15 @@ const reservedIntervalIdKey = "intervalId";
|
|
|
55
91
|
* If the interval endpoint was treated inclusively, the interval would now refer to "hel", which
|
|
56
92
|
* is undesirable.
|
|
57
93
|
*
|
|
58
|
-
* Since the
|
|
59
|
-
* length of the associated sequence,
|
|
60
|
-
*
|
|
94
|
+
* Since the endpoints of an interval are treated exclusively but cannot be greater
|
|
95
|
+
* than or equal to the length of the associated sequence, there exist special
|
|
96
|
+
* endpoint segments, "start" and "end", which represent the position immediately
|
|
97
|
+
* before or immediately after the string respectively.
|
|
98
|
+
*
|
|
99
|
+
* If a `SequenceInterval` is created on a sequence with the
|
|
100
|
+
* `mergeTreeReferencesCanSlideToEndpoint` feature flag set to true, the endpoints
|
|
101
|
+
* of the interval that are exclusive will have the ability to slide to these
|
|
102
|
+
* special endpoint segments.
|
|
61
103
|
*/
|
|
62
104
|
export class SequenceInterval implements ISerializableInterval {
|
|
63
105
|
/**
|
|
@@ -70,21 +112,36 @@ export class SequenceInterval implements ISerializableInterval {
|
|
|
70
112
|
*/
|
|
71
113
|
public propertyManager: PropertiesManager;
|
|
72
114
|
|
|
115
|
+
/**
|
|
116
|
+
* @internal
|
|
117
|
+
*/
|
|
118
|
+
public get stickiness(): IntervalStickiness {
|
|
119
|
+
const startSegment = this.start.getSegment();
|
|
120
|
+
const endSegment = this.end.getSegment();
|
|
121
|
+
return computeStickinessFromSide(
|
|
122
|
+
startSegment?.endpointType,
|
|
123
|
+
this.startSide,
|
|
124
|
+
endSegment?.endpointType,
|
|
125
|
+
this.endSide,
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
73
129
|
constructor(
|
|
74
130
|
private readonly client: Client,
|
|
75
131
|
/**
|
|
76
132
|
* Start endpoint of this interval.
|
|
77
|
-
* @remarks
|
|
133
|
+
* @remarks This endpoint can be resolved into a character position using the SharedString it's a part of.
|
|
78
134
|
*/
|
|
79
135
|
public start: LocalReferencePosition,
|
|
80
136
|
/**
|
|
81
137
|
* End endpoint of this interval.
|
|
82
|
-
* @remarks
|
|
138
|
+
* @remarks This endpoint can be resolved into a character position using the SharedString it's a part of.
|
|
83
139
|
*/
|
|
84
140
|
public end: LocalReferencePosition,
|
|
85
141
|
public intervalType: IntervalType,
|
|
86
142
|
props?: PropertySet,
|
|
87
|
-
public readonly
|
|
143
|
+
public readonly startSide: Side = Side.Before,
|
|
144
|
+
public readonly endSide: Side = Side.Before,
|
|
88
145
|
) {
|
|
89
146
|
this.propertyManager = new PropertiesManager();
|
|
90
147
|
this.properties = {};
|
|
@@ -136,19 +193,20 @@ export class SequenceInterval implements ISerializableInterval {
|
|
|
136
193
|
public serialize(): ISerializedInterval {
|
|
137
194
|
const startPosition = this.client.localReferencePositionToPosition(this.start);
|
|
138
195
|
const endPosition = this.client.localReferencePositionToPosition(this.end);
|
|
196
|
+
const { startSide, endSide } = sidesFromStickiness(this.stickiness);
|
|
139
197
|
const serializedInterval: ISerializedInterval = {
|
|
140
198
|
end: endPosition,
|
|
141
199
|
intervalType: this.intervalType,
|
|
142
200
|
sequenceNumber: this.client.getCurrentSeq(),
|
|
143
201
|
start: startPosition,
|
|
202
|
+
stickiness: this.stickiness,
|
|
203
|
+
startSide,
|
|
204
|
+
endSide,
|
|
144
205
|
};
|
|
145
206
|
|
|
146
207
|
if (this.properties) {
|
|
147
208
|
serializedInterval.properties = this.properties;
|
|
148
209
|
}
|
|
149
|
-
if (this.stickiness !== IntervalStickiness.END) {
|
|
150
|
-
serializedInterval.stickiness = this.stickiness;
|
|
151
|
-
}
|
|
152
210
|
|
|
153
211
|
return serializedInterval;
|
|
154
212
|
}
|
|
@@ -163,7 +221,8 @@ export class SequenceInterval implements ISerializableInterval {
|
|
|
163
221
|
this.end,
|
|
164
222
|
this.intervalType,
|
|
165
223
|
this.properties,
|
|
166
|
-
this.
|
|
224
|
+
this.startSide,
|
|
225
|
+
this.endSide,
|
|
167
226
|
);
|
|
168
227
|
}
|
|
169
228
|
|
|
@@ -196,14 +255,26 @@ export class SequenceInterval implements ISerializableInterval {
|
|
|
196
255
|
* {@inheritDoc IInterval.compareStart}
|
|
197
256
|
*/
|
|
198
257
|
public compareStart(b: SequenceInterval) {
|
|
199
|
-
|
|
258
|
+
const dist = compareReferencePositions(this.start, b.start);
|
|
259
|
+
|
|
260
|
+
if (dist === 0) {
|
|
261
|
+
return compareSides(this.startSide, b.startSide);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return dist;
|
|
200
265
|
}
|
|
201
266
|
|
|
202
267
|
/**
|
|
203
268
|
* {@inheritDoc IInterval.compareEnd}
|
|
204
269
|
*/
|
|
205
|
-
public compareEnd(b: SequenceInterval) {
|
|
206
|
-
|
|
270
|
+
public compareEnd(b: SequenceInterval): number {
|
|
271
|
+
const dist = compareReferencePositions(this.end, b.end);
|
|
272
|
+
|
|
273
|
+
if (dist === 0) {
|
|
274
|
+
return compareSides(b.endSide, this.endSide);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return dist;
|
|
207
278
|
}
|
|
208
279
|
|
|
209
280
|
/**
|
|
@@ -230,11 +301,33 @@ export class SequenceInterval implements ISerializableInterval {
|
|
|
230
301
|
* @internal
|
|
231
302
|
*/
|
|
232
303
|
public union(b: SequenceInterval) {
|
|
304
|
+
const newStart = minReferencePosition(this.start, b.start);
|
|
305
|
+
const newEnd = maxReferencePosition(this.end, b.end);
|
|
306
|
+
|
|
307
|
+
let startSide: Side;
|
|
308
|
+
|
|
309
|
+
if (this.start === b.start) {
|
|
310
|
+
startSide = minSide(this.startSide, b.startSide);
|
|
311
|
+
} else {
|
|
312
|
+
startSide = this.start === newStart ? this.startSide : b.startSide;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
let endSide: Side;
|
|
316
|
+
|
|
317
|
+
if (this.end === b.end) {
|
|
318
|
+
endSide = maxSide(this.endSide, b.endSide);
|
|
319
|
+
} else {
|
|
320
|
+
endSide = this.end === newEnd ? this.endSide : b.endSide;
|
|
321
|
+
}
|
|
322
|
+
|
|
233
323
|
return new SequenceInterval(
|
|
234
324
|
this.client,
|
|
235
|
-
|
|
236
|
-
|
|
325
|
+
newStart,
|
|
326
|
+
newEnd,
|
|
237
327
|
this.intervalType,
|
|
328
|
+
undefined,
|
|
329
|
+
startSide,
|
|
330
|
+
endSide,
|
|
238
331
|
);
|
|
239
332
|
}
|
|
240
333
|
|
|
@@ -267,12 +360,19 @@ export class SequenceInterval implements ISerializableInterval {
|
|
|
267
360
|
*/
|
|
268
361
|
public modify(
|
|
269
362
|
label: string,
|
|
270
|
-
start:
|
|
271
|
-
end:
|
|
363
|
+
start: SequencePlace | undefined,
|
|
364
|
+
end: SequencePlace | undefined,
|
|
272
365
|
op?: ISequencedDocumentMessage,
|
|
273
366
|
localSeq?: number,
|
|
274
|
-
|
|
367
|
+
useNewSlidingBehavior: boolean = false,
|
|
275
368
|
) {
|
|
369
|
+
const { startSide, endSide, startPos, endPos } = endpointPosAndSide(start, end);
|
|
370
|
+
const stickiness = computeStickinessFromSide(
|
|
371
|
+
startPos ?? this.start.getSegment()?.endpointType,
|
|
372
|
+
startSide ?? this.startSide,
|
|
373
|
+
endPos ?? this.end.getSegment()?.endpointType,
|
|
374
|
+
endSide ?? this.endSide,
|
|
375
|
+
);
|
|
276
376
|
const getRefType = (baseType: ReferenceType): ReferenceType => {
|
|
277
377
|
let refType = baseType;
|
|
278
378
|
if (op === undefined) {
|
|
@@ -283,15 +383,17 @@ export class SequenceInterval implements ISerializableInterval {
|
|
|
283
383
|
};
|
|
284
384
|
|
|
285
385
|
let startRef = this.start;
|
|
286
|
-
if (
|
|
386
|
+
if (startPos !== undefined) {
|
|
287
387
|
startRef = createPositionReference(
|
|
288
388
|
this.client,
|
|
289
|
-
|
|
389
|
+
startPos,
|
|
290
390
|
getRefType(this.start.refType),
|
|
291
391
|
op,
|
|
292
392
|
undefined,
|
|
293
393
|
localSeq,
|
|
294
394
|
startReferenceSlidingPreference(stickiness),
|
|
395
|
+
startReferenceSlidingPreference(stickiness) === SlidingPreference.BACKWARD,
|
|
396
|
+
useNewSlidingBehavior,
|
|
295
397
|
);
|
|
296
398
|
if (this.start.properties) {
|
|
297
399
|
startRef.addProperties(this.start.properties);
|
|
@@ -299,22 +401,32 @@ export class SequenceInterval implements ISerializableInterval {
|
|
|
299
401
|
}
|
|
300
402
|
|
|
301
403
|
let endRef = this.end;
|
|
302
|
-
if (
|
|
404
|
+
if (endPos !== undefined) {
|
|
303
405
|
endRef = createPositionReference(
|
|
304
406
|
this.client,
|
|
305
|
-
|
|
407
|
+
endPos,
|
|
306
408
|
getRefType(this.end.refType),
|
|
307
409
|
op,
|
|
308
410
|
undefined,
|
|
309
411
|
localSeq,
|
|
310
412
|
endReferenceSlidingPreference(stickiness),
|
|
413
|
+
endReferenceSlidingPreference(stickiness) === SlidingPreference.FORWARD,
|
|
414
|
+
useNewSlidingBehavior,
|
|
311
415
|
);
|
|
312
416
|
if (this.end.properties) {
|
|
313
417
|
endRef.addProperties(this.end.properties);
|
|
314
418
|
}
|
|
315
419
|
}
|
|
316
420
|
|
|
317
|
-
const newInterval = new SequenceInterval(
|
|
421
|
+
const newInterval = new SequenceInterval(
|
|
422
|
+
this.client,
|
|
423
|
+
startRef,
|
|
424
|
+
endRef,
|
|
425
|
+
this.intervalType,
|
|
426
|
+
undefined,
|
|
427
|
+
startSide ?? this.startSide,
|
|
428
|
+
endSide ?? this.endSide,
|
|
429
|
+
);
|
|
318
430
|
if (this.properties) {
|
|
319
431
|
newInterval.initializeProperties();
|
|
320
432
|
this.propertyManager.copyTo(
|
|
@@ -338,13 +450,25 @@ export class SequenceInterval implements ISerializableInterval {
|
|
|
338
450
|
|
|
339
451
|
export function createPositionReferenceFromSegoff(
|
|
340
452
|
client: Client,
|
|
341
|
-
segoff: { segment: ISegment | undefined; offset: number | undefined },
|
|
453
|
+
segoff: { segment: ISegment | undefined; offset: number | undefined } | "start" | "end",
|
|
342
454
|
refType: ReferenceType,
|
|
343
455
|
op?: ISequencedDocumentMessage,
|
|
344
456
|
localSeq?: number,
|
|
345
457
|
fromSnapshot?: boolean,
|
|
346
458
|
slidingPreference?: SlidingPreference,
|
|
459
|
+
canSlideToEndpoint?: boolean,
|
|
347
460
|
): LocalReferencePosition {
|
|
461
|
+
if (segoff === "start" || segoff === "end") {
|
|
462
|
+
return client.createLocalReferencePosition(
|
|
463
|
+
segoff,
|
|
464
|
+
undefined,
|
|
465
|
+
refType,
|
|
466
|
+
undefined,
|
|
467
|
+
slidingPreference,
|
|
468
|
+
canSlideToEndpoint,
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
|
|
348
472
|
if (segoff.segment) {
|
|
349
473
|
const ref = client.createLocalReferencePosition(
|
|
350
474
|
segoff.segment,
|
|
@@ -352,6 +476,7 @@ export function createPositionReferenceFromSegoff(
|
|
|
352
476
|
refType,
|
|
353
477
|
undefined,
|
|
354
478
|
slidingPreference,
|
|
479
|
+
canSlideToEndpoint,
|
|
355
480
|
);
|
|
356
481
|
return ref;
|
|
357
482
|
}
|
|
@@ -375,30 +500,40 @@ export function createPositionReferenceFromSegoff(
|
|
|
375
500
|
|
|
376
501
|
function createPositionReference(
|
|
377
502
|
client: Client,
|
|
378
|
-
pos: number,
|
|
503
|
+
pos: number | "start" | "end",
|
|
379
504
|
refType: ReferenceType,
|
|
380
505
|
op?: ISequencedDocumentMessage,
|
|
381
506
|
fromSnapshot?: boolean,
|
|
382
507
|
localSeq?: number,
|
|
383
508
|
slidingPreference?: SlidingPreference,
|
|
509
|
+
exclusive: boolean = false,
|
|
510
|
+
useNewSlidingBehavior: boolean = false,
|
|
384
511
|
): LocalReferencePosition {
|
|
385
512
|
let segoff;
|
|
513
|
+
|
|
386
514
|
if (op) {
|
|
387
515
|
assert(
|
|
388
516
|
(refType & ReferenceType.SlideOnRemove) !== 0,
|
|
389
517
|
0x2f5 /* op create references must be SlideOnRemove */,
|
|
390
518
|
);
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
519
|
+
if (pos === "start" || pos === "end") {
|
|
520
|
+
segoff = pos;
|
|
521
|
+
} else {
|
|
522
|
+
segoff = client.getContainingSegment(pos, {
|
|
523
|
+
referenceSequenceNumber: op.referenceSequenceNumber,
|
|
524
|
+
clientId: op.clientId,
|
|
525
|
+
});
|
|
526
|
+
segoff = getSlideToSegoff(segoff, undefined, useNewSlidingBehavior);
|
|
527
|
+
}
|
|
396
528
|
} else {
|
|
397
529
|
assert(
|
|
398
530
|
(refType & ReferenceType.SlideOnRemove) === 0 || !!fromSnapshot,
|
|
399
531
|
0x2f6 /* SlideOnRemove references must be op created */,
|
|
400
532
|
);
|
|
401
|
-
segoff =
|
|
533
|
+
segoff =
|
|
534
|
+
pos === "start" || pos === "end"
|
|
535
|
+
? pos
|
|
536
|
+
: client.getContainingSegment(pos, undefined, localSeq);
|
|
402
537
|
}
|
|
403
538
|
|
|
404
539
|
return createPositionReferenceFromSegoff(
|
|
@@ -409,19 +544,32 @@ function createPositionReference(
|
|
|
409
544
|
localSeq,
|
|
410
545
|
fromSnapshot,
|
|
411
546
|
slidingPreference,
|
|
547
|
+
exclusive,
|
|
412
548
|
);
|
|
413
549
|
}
|
|
414
550
|
|
|
415
551
|
export function createSequenceInterval(
|
|
416
552
|
label: string,
|
|
417
|
-
start:
|
|
418
|
-
end:
|
|
553
|
+
start: SequencePlace | undefined,
|
|
554
|
+
end: SequencePlace | undefined,
|
|
419
555
|
client: Client,
|
|
420
556
|
intervalType: IntervalType,
|
|
421
557
|
op?: ISequencedDocumentMessage,
|
|
422
558
|
fromSnapshot?: boolean,
|
|
423
|
-
|
|
559
|
+
useNewSlidingBehavior: boolean = false,
|
|
424
560
|
): SequenceInterval {
|
|
561
|
+
const { startPos, startSide, endPos, endSide } = endpointPosAndSide(
|
|
562
|
+
start ?? "start",
|
|
563
|
+
end ?? "end",
|
|
564
|
+
);
|
|
565
|
+
assert(
|
|
566
|
+
startPos !== undefined &&
|
|
567
|
+
endPos !== undefined &&
|
|
568
|
+
startSide !== undefined &&
|
|
569
|
+
endSide !== undefined,
|
|
570
|
+
0x794 /* start and end cannot be undefined because they were not passed in as undefined */,
|
|
571
|
+
);
|
|
572
|
+
const stickiness = computeStickinessFromSide(startPos, startSide, endPos, endSide);
|
|
425
573
|
let beginRefType = ReferenceType.RangeBegin;
|
|
426
574
|
let endRefType = ReferenceType.RangeEnd;
|
|
427
575
|
if (intervalType === IntervalType.Transient) {
|
|
@@ -435,7 +583,7 @@ export function createSequenceInterval(
|
|
|
435
583
|
// All non-transient interval references must eventually be SlideOnRemove
|
|
436
584
|
// To ensure eventual consistency, they must start as StayOnRemove when
|
|
437
585
|
// pending (created locally and creation op is not acked)
|
|
438
|
-
if (op
|
|
586
|
+
if (op ?? fromSnapshot) {
|
|
439
587
|
beginRefType |= ReferenceType.SlideOnRemove;
|
|
440
588
|
endRefType |= ReferenceType.SlideOnRemove;
|
|
441
589
|
} else {
|
|
@@ -446,22 +594,26 @@ export function createSequenceInterval(
|
|
|
446
594
|
|
|
447
595
|
const startLref = createPositionReference(
|
|
448
596
|
client,
|
|
449
|
-
|
|
597
|
+
startPos,
|
|
450
598
|
beginRefType,
|
|
451
599
|
op,
|
|
452
600
|
fromSnapshot,
|
|
453
601
|
undefined,
|
|
454
602
|
startReferenceSlidingPreference(stickiness),
|
|
603
|
+
startReferenceSlidingPreference(stickiness) === SlidingPreference.BACKWARD,
|
|
604
|
+
useNewSlidingBehavior,
|
|
455
605
|
);
|
|
456
606
|
|
|
457
607
|
const endLref = createPositionReference(
|
|
458
608
|
client,
|
|
459
|
-
|
|
609
|
+
endPos,
|
|
460
610
|
endRefType,
|
|
461
611
|
op,
|
|
462
612
|
fromSnapshot,
|
|
463
613
|
undefined,
|
|
464
614
|
endReferenceSlidingPreference(stickiness),
|
|
615
|
+
endReferenceSlidingPreference(stickiness) === SlidingPreference.FORWARD,
|
|
616
|
+
useNewSlidingBehavior,
|
|
465
617
|
);
|
|
466
618
|
|
|
467
619
|
const rangeProp = {
|
|
@@ -476,19 +628,15 @@ export function createSequenceInterval(
|
|
|
476
628
|
endLref,
|
|
477
629
|
intervalType,
|
|
478
630
|
rangeProp,
|
|
479
|
-
|
|
631
|
+
startSide,
|
|
632
|
+
endSide,
|
|
480
633
|
);
|
|
481
634
|
return ival;
|
|
482
635
|
}
|
|
483
636
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
export const compareSequenceIntervalStarts = (a: SequenceInterval, b: SequenceInterval): number =>
|
|
488
|
-
compareReferencePositions(a.start, b.start);
|
|
489
|
-
|
|
637
|
+
/**
|
|
638
|
+
* @deprecated The methods within have substitutions
|
|
639
|
+
*/
|
|
490
640
|
export const sequenceIntervalHelpers: IIntervalHelpers<SequenceInterval> = {
|
|
491
|
-
compareEnds: compareSequenceIntervalEnds,
|
|
492
|
-
compareStarts: compareSequenceIntervalStarts,
|
|
493
641
|
create: createSequenceInterval,
|
|
494
642
|
};
|
package/src/packageVersion.ts
CHANGED
package/src/revertibles.ts
CHANGED
|
@@ -27,9 +27,6 @@ import { ISequenceDeltaRange, SequenceDeltaEvent } from "./sequenceDeltaEvent";
|
|
|
27
27
|
/**
|
|
28
28
|
* Data for undoing edits on SharedStrings and Intervals.
|
|
29
29
|
*
|
|
30
|
-
* Revertibles are new and require the option mergeTreeUseNewLengthCalculations to
|
|
31
|
-
* be set as true on the underlying merge tree in order to function correctly.
|
|
32
|
-
*
|
|
33
30
|
* @alpha
|
|
34
31
|
*/
|
|
35
32
|
export type SharedStringRevertible = MergeTreeDeltaRevertible | IntervalRevertible;
|
|
@@ -41,9 +38,6 @@ type IntervalOpType = typeof IntervalOpType[keyof typeof IntervalOpType];
|
|
|
41
38
|
/**
|
|
42
39
|
* Data for undoing edits affecting Intervals.
|
|
43
40
|
*
|
|
44
|
-
* Revertibles are new and require the option mergeTreeUseNewLengthCalculations to
|
|
45
|
-
* be set as true on the underlying merge tree in order to function correctly.
|
|
46
|
-
*
|
|
47
41
|
* @alpha
|
|
48
42
|
*/
|
|
49
43
|
export type IntervalRevertible =
|
|
@@ -271,9 +265,6 @@ function addIfRevertibleRef(
|
|
|
271
265
|
* Create revertibles for SharedStringDeltas, handling indirectly modified intervals
|
|
272
266
|
* (e.g. reverting remove of a range that contains an interval will move the interval back)
|
|
273
267
|
*
|
|
274
|
-
* Revertibles are new and require the option mergeTreeUseNewLengthCalculations to
|
|
275
|
-
* be set as true on the underlying merge tree in order to function correctly.
|
|
276
|
-
*
|
|
277
268
|
* @alpha
|
|
278
269
|
*/
|
|
279
270
|
export function appendSharedStringDeltaToRevertibles(
|
|
@@ -537,27 +528,14 @@ function revertLocalSequenceRemove(
|
|
|
537
528
|
const intervalId = getUpdatedId(intervalInfo.intervalId);
|
|
538
529
|
const interval = intervalCollection.getIntervalById(intervalId);
|
|
539
530
|
if (interval !== undefined) {
|
|
540
|
-
const
|
|
541
|
-
intervalInfo.startOffset,
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
sharedString,
|
|
549
|
-
);
|
|
550
|
-
// only move interval if start <= end
|
|
551
|
-
if (
|
|
552
|
-
(newStart === undefined &&
|
|
553
|
-
newEnd !== undefined &&
|
|
554
|
-
sharedString.localReferencePositionToPosition(interval.start) <= newEnd) ||
|
|
555
|
-
(newEnd === undefined &&
|
|
556
|
-
newStart !== undefined &&
|
|
557
|
-
sharedString.localReferencePositionToPosition(interval.end) >= newStart) ||
|
|
558
|
-
(newStart !== undefined && newEnd !== undefined && newStart <= newEnd)
|
|
559
|
-
) {
|
|
560
|
-
intervalCollection.change(intervalId, newStart, newEnd);
|
|
531
|
+
const start =
|
|
532
|
+
newEndpointPosition(intervalInfo.startOffset, restoredRanges, sharedString) ??
|
|
533
|
+
sharedString.localReferencePositionToPosition(interval.start);
|
|
534
|
+
const end =
|
|
535
|
+
newEndpointPosition(intervalInfo.endOffset, restoredRanges, sharedString) ??
|
|
536
|
+
sharedString.localReferencePositionToPosition(interval.end);
|
|
537
|
+
if (start <= end) {
|
|
538
|
+
intervalCollection.change(intervalId, start, end);
|
|
561
539
|
}
|
|
562
540
|
}
|
|
563
541
|
});
|
|
@@ -597,9 +575,6 @@ function revertLocalSequenceRemove(
|
|
|
597
575
|
/**
|
|
598
576
|
* Invoke revertibles to reverse prior edits
|
|
599
577
|
*
|
|
600
|
-
* Revertibles are new and require the option mergeTreeUseNewLengthCalculations to
|
|
601
|
-
* be set as true on the underlying merge tree in order to function correctly.
|
|
602
|
-
*
|
|
603
578
|
* @alpha
|
|
604
579
|
*/
|
|
605
580
|
export function revertSharedStringRevertibles(
|
package/src/sequence.ts
CHANGED
|
@@ -340,6 +340,7 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
340
340
|
refType: ReferenceType,
|
|
341
341
|
properties: PropertySet | undefined,
|
|
342
342
|
slidingPreference?: SlidingPreference,
|
|
343
|
+
canSlideToEndpoint?: boolean,
|
|
343
344
|
): LocalReferencePosition {
|
|
344
345
|
return this.client.createLocalReferencePosition(
|
|
345
346
|
segment,
|
|
@@ -347,6 +348,7 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
347
348
|
refType,
|
|
348
349
|
properties,
|
|
349
350
|
slidingPreference,
|
|
351
|
+
canSlideToEndpoint,
|
|
350
352
|
);
|
|
351
353
|
}
|
|
352
354
|
|
|
@@ -452,7 +454,7 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
452
454
|
}
|
|
453
455
|
|
|
454
456
|
/**
|
|
455
|
-
* @returns
|
|
457
|
+
* @returns The most recent sequence number which has been acked by the server and processed by this
|
|
456
458
|
* SharedSegmentSequence.
|
|
457
459
|
*/
|
|
458
460
|
public getCurrentSeq() {
|
|
@@ -489,6 +491,7 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
489
491
|
* @returns An iterable object that enumerates the IntervalCollection labels.
|
|
490
492
|
*
|
|
491
493
|
* @example
|
|
494
|
+
*
|
|
492
495
|
* ```typescript
|
|
493
496
|
* const iter = this.getIntervalCollectionKeys();
|
|
494
497
|
* for (key of iter)
|
|
@@ -704,7 +707,7 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
704
707
|
* {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.applyStashedOp}
|
|
705
708
|
*/
|
|
706
709
|
protected applyStashedOp(content: any): unknown {
|
|
707
|
-
return this.client.applyStashedOp(content);
|
|
710
|
+
return this.client.applyStashedOp(parseHandles(content, this.serializer));
|
|
708
711
|
}
|
|
709
712
|
|
|
710
713
|
private summarizeMergeTree(serializer: IFluidSerializer): ISummaryTreeWithStats {
|
|
@@ -147,25 +147,33 @@ export interface ISequenceDeltaRange<
|
|
|
147
147
|
> {
|
|
148
148
|
/**
|
|
149
149
|
* The type of operation that changed this range.
|
|
150
|
-
*
|
|
150
|
+
*
|
|
151
|
+
* @remarks Consuming code should typically compare this to the enum values defined in
|
|
151
152
|
* `MergeTreeDeltaOperationTypes`.
|
|
152
153
|
*/
|
|
153
154
|
operation: TOperation;
|
|
155
|
+
|
|
154
156
|
/**
|
|
155
157
|
* The index of the start of the range.
|
|
156
158
|
*/
|
|
157
159
|
position: number;
|
|
160
|
+
|
|
158
161
|
/**
|
|
159
162
|
* The segment that corresponds to the range.
|
|
160
163
|
*/
|
|
161
164
|
segment: ISegment;
|
|
165
|
+
|
|
162
166
|
/**
|
|
163
167
|
* Deltas object which contains all modified properties with their previous values.
|
|
164
168
|
* Since `undefined` doesn't survive a round-trip through JSON serialization, the old value being absent
|
|
165
169
|
* is instead encoded with `null`.
|
|
166
|
-
*
|
|
170
|
+
*
|
|
171
|
+
* @remarks This object is motivated by undo/redo scenarios, and provides a convenient "inverse op" to apply to
|
|
167
172
|
* undo a property change.
|
|
168
|
-
*
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
*
|
|
176
|
+
* If a segment initially had properties `{ foo: "1", bar: 2 }` and it was annotated with
|
|
169
177
|
* `{ foo: 3, baz: 5 }`, the corresponding event would have a `propertyDeltas` of `{ foo: "1", baz: null }`.
|
|
170
178
|
*/
|
|
171
179
|
propertyDeltas: PropertySet;
|
package/src/sequenceFactory.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { SharedString, SharedStringSegment } from "./sharedString";
|
|
|
15
15
|
|
|
16
16
|
export class SharedStringFactory implements IChannelFactory {
|
|
17
17
|
// TODO rename back to https://graph.microsoft.com/types/mergeTree/string once paparazzi is able to dynamically
|
|
18
|
-
// load code
|
|
18
|
+
// load code (UPDATE: paparazzi is gone... anything to do here?)
|
|
19
19
|
public static Type = "https://graph.microsoft.com/types/mergeTree";
|
|
20
20
|
|
|
21
21
|
public static readonly Attributes: IChannelAttributes = {
|
package/src/sharedString.ts
CHANGED
|
@@ -406,7 +406,8 @@ const gatherTextAndMarkers: ISegmentAction<ITextAndMarkerAccumulator> = (
|
|
|
406
406
|
if (placeholder && placeholder.length > 0) {
|
|
407
407
|
const placeholderText =
|
|
408
408
|
placeholder === "*"
|
|
409
|
-
?
|
|
409
|
+
? // eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
410
|
+
`\n${segment.toString()}`
|
|
410
411
|
: placeholder.repeat(segment.cachedLength);
|
|
411
412
|
textSegment.text += placeholderText;
|
|
412
413
|
} else {
|