@fluidframework/merge-tree 0.58.0-55561 → 0.58.0-55983
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/dist/base.js.map +1 -1
- package/dist/client.d.ts +3 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +6 -7
- package/dist/client.js.map +1 -1
- package/dist/collections.d.ts +1 -1
- package/dist/collections.js +2 -2
- package/dist/collections.js.map +1 -1
- package/dist/mergeTree.d.ts +0 -4
- package/dist/mergeTree.d.ts.map +1 -1
- package/dist/mergeTree.js +2 -50
- package/dist/mergeTree.js.map +1 -1
- package/dist/mergeTreeDeltaCallback.d.ts.map +1 -1
- package/dist/mergeTreeDeltaCallback.js.map +1 -1
- package/dist/partialLengths.js +14 -17
- package/dist/partialLengths.js.map +1 -1
- package/dist/segmentPropertiesManager.js +1 -5
- package/dist/segmentPropertiesManager.js.map +1 -1
- package/dist/snapshotChunks.js +3 -3
- package/dist/snapshotChunks.js.map +1 -1
- package/dist/snapshotV1.d.ts +2 -1
- package/dist/snapshotV1.d.ts.map +1 -1
- package/dist/snapshotV1.js +4 -4
- package/dist/snapshotV1.js.map +1 -1
- package/dist/sortedSegmentSet.d.ts +3 -3
- package/dist/sortedSegmentSet.d.ts.map +1 -1
- package/dist/sortedSegmentSet.js +12 -12
- package/dist/sortedSegmentSet.js.map +1 -1
- package/dist/textSegment.js +3 -3
- package/dist/textSegment.js.map +1 -1
- package/lib/base.js.map +1 -1
- package/lib/client.d.ts +3 -3
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +6 -7
- package/lib/client.js.map +1 -1
- package/lib/collections.d.ts +1 -1
- package/lib/collections.js +2 -2
- package/lib/collections.js.map +1 -1
- package/lib/mergeTree.d.ts +0 -4
- package/lib/mergeTree.d.ts.map +1 -1
- package/lib/mergeTree.js +1 -48
- package/lib/mergeTree.js.map +1 -1
- package/lib/mergeTreeDeltaCallback.d.ts.map +1 -1
- package/lib/mergeTreeDeltaCallback.js.map +1 -1
- package/lib/partialLengths.js +14 -17
- package/lib/partialLengths.js.map +1 -1
- package/lib/segmentPropertiesManager.js +1 -5
- package/lib/segmentPropertiesManager.js.map +1 -1
- package/lib/snapshotChunks.js +3 -3
- package/lib/snapshotChunks.js.map +1 -1
- package/lib/snapshotV1.d.ts +2 -1
- package/lib/snapshotV1.d.ts.map +1 -1
- package/lib/snapshotV1.js +4 -4
- package/lib/snapshotV1.js.map +1 -1
- package/lib/sortedSegmentSet.d.ts +3 -3
- package/lib/sortedSegmentSet.d.ts.map +1 -1
- package/lib/sortedSegmentSet.js +12 -12
- package/lib/sortedSegmentSet.js.map +1 -1
- package/lib/textSegment.js +3 -3
- package/lib/textSegment.js.map +1 -1
- package/package.json +10 -10
- package/src/base.ts +2 -2
- package/src/client.ts +6 -7
- package/src/collections.ts +2 -2
- package/src/mergeTree.ts +1 -51
- package/src/mergeTreeDeltaCallback.ts +0 -1
- package/src/partialLengths.ts +17 -17
- package/src/segmentPropertiesManager.ts +5 -5
- package/src/snapshotChunks.ts +3 -3
- package/src/snapshotV1.ts +3 -3
- package/src/sortedSegmentSet.ts +12 -12
- package/src/textSegment.ts +3 -3
package/src/partialLengths.ts
CHANGED
|
@@ -177,8 +177,8 @@ export class PartialSequenceLengths {
|
|
|
177
177
|
// Find next earliest sequence number
|
|
178
178
|
if (indices[k] < childPartialsCounts[k]) {
|
|
179
179
|
const cpLen = childPartials[k].partialLengths[indices[k]];
|
|
180
|
-
|
|
181
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
180
|
+
|
|
181
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
182
182
|
if ((outerIndexOfEarliest < 0) || (cpLen.seq < earliestPartialLength!.seq)) {
|
|
183
183
|
outerIndexOfEarliest = k;
|
|
184
184
|
earliestPartialLength = cpLen;
|
|
@@ -186,8 +186,8 @@ export class PartialSequenceLengths {
|
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
188
|
if (outerIndexOfEarliest >= 0) {
|
|
189
|
-
|
|
190
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
189
|
+
|
|
190
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
191
191
|
addNext(earliestPartialLength!);
|
|
192
192
|
indices[outerIndexOfEarliest]++;
|
|
193
193
|
}
|
|
@@ -263,9 +263,9 @@ export class PartialSequenceLengths {
|
|
|
263
263
|
}
|
|
264
264
|
}
|
|
265
265
|
|
|
266
|
-
private static getOverlapClients(
|
|
266
|
+
private static getOverlapClients(overlapClientIds: number[], seglen: number) {
|
|
267
267
|
const bst = new RedBlackTree<number, IOverlapClient>(compareNumbers);
|
|
268
|
-
for (const clientId of
|
|
268
|
+
for (const clientId of overlapClientIds) {
|
|
269
269
|
bst.put(clientId, { clientId, seglen });
|
|
270
270
|
}
|
|
271
271
|
return bst;
|
|
@@ -277,11 +277,11 @@ export class PartialSequenceLengths {
|
|
|
277
277
|
seglen: number) {
|
|
278
278
|
if (partialLength.overlapRemoveClients) {
|
|
279
279
|
for (const clientId of overlapRemoveClientIds) {
|
|
280
|
-
const
|
|
281
|
-
if (!
|
|
280
|
+
const overlapClientNode = partialLength.overlapRemoveClients.get(clientId);
|
|
281
|
+
if (!overlapClientNode) {
|
|
282
282
|
partialLength.overlapRemoveClients.put(clientId, { clientId, seglen });
|
|
283
283
|
} else {
|
|
284
|
-
|
|
284
|
+
overlapClientNode.data.seglen += seglen;
|
|
285
285
|
}
|
|
286
286
|
}
|
|
287
287
|
} else {
|
|
@@ -367,7 +367,7 @@ export class PartialSequenceLengths {
|
|
|
367
367
|
}
|
|
368
368
|
}
|
|
369
369
|
if (seqPartialLen === undefined) {
|
|
370
|
-
|
|
370
|
+
|
|
371
371
|
seqPartialLen = {
|
|
372
372
|
clientId,
|
|
373
373
|
seglen: seqSeglen,
|
|
@@ -453,14 +453,14 @@ export class PartialSequenceLengths {
|
|
|
453
453
|
public getPartialLength(refSeq: number, clientId: number) {
|
|
454
454
|
let pLen = this.minLength;
|
|
455
455
|
const seqIndex = latestLEQ(this.partialLengths, refSeq);
|
|
456
|
-
const
|
|
456
|
+
const cliLatestIndex = this.cliLatest(clientId);
|
|
457
457
|
const cliSeq = this.clientSeqNumbers[clientId];
|
|
458
458
|
if (seqIndex >= 0) {
|
|
459
459
|
// Add the partial length up to refSeq
|
|
460
460
|
pLen += this.partialLengths[seqIndex].len;
|
|
461
461
|
|
|
462
|
-
if (
|
|
463
|
-
const cliLatest = cliSeq[
|
|
462
|
+
if (cliLatestIndex >= 0) {
|
|
463
|
+
const cliLatest = cliSeq[cliLatestIndex];
|
|
464
464
|
|
|
465
465
|
if (cliLatest.seq > refSeq) {
|
|
466
466
|
// The client has local edits after refSeq, add in the length adjustments
|
|
@@ -474,8 +474,8 @@ export class PartialSequenceLengths {
|
|
|
474
474
|
} else {
|
|
475
475
|
// RefSeq is before any of the partial lengths
|
|
476
476
|
// so just add in all local edits of that client (which should all be after the refSeq)
|
|
477
|
-
if (
|
|
478
|
-
const cliLatest = cliSeq[
|
|
477
|
+
if (cliLatestIndex >= 0) {
|
|
478
|
+
const cliLatest = cliSeq[cliLatestIndex];
|
|
479
479
|
pLen += cliLatest.len;
|
|
480
480
|
}
|
|
481
481
|
}
|
|
@@ -488,7 +488,7 @@ export class PartialSequenceLengths {
|
|
|
488
488
|
buf += `(${partial.seq},${partial.len}) `;
|
|
489
489
|
}
|
|
490
490
|
|
|
491
|
-
// eslint-disable-next-line @typescript-eslint/no-for-in-array
|
|
491
|
+
// eslint-disable-next-line @typescript-eslint/no-for-in-array
|
|
492
492
|
for (const clientId in this.clientSeqNumbers) {
|
|
493
493
|
if (this.clientSeqNumbers[clientId].length > 0) {
|
|
494
494
|
buf += `Client `;
|
|
@@ -530,7 +530,7 @@ export class PartialSequenceLengths {
|
|
|
530
530
|
return minLength;
|
|
531
531
|
}
|
|
532
532
|
this.minLength += copyDown(this.partialLengths);
|
|
533
|
-
// eslint-disable-next-line @typescript-eslint/no-for-in-array, guard-for-in
|
|
533
|
+
// eslint-disable-next-line @typescript-eslint/no-for-in-array, guard-for-in
|
|
534
534
|
for (const clientId in this.clientSeqNumbers) {
|
|
535
535
|
const cliPartials = this.clientSeqNumbers[clientId];
|
|
536
536
|
if (cliPartials) {
|
|
@@ -33,7 +33,7 @@ export class PropertiesManager {
|
|
|
33
33
|
0x05c /* "Trying to update more annotate props than do exist!" */);
|
|
34
34
|
this.pendingKeyUpdateCount[key]--;
|
|
35
35
|
if (this.pendingKeyUpdateCount?.[key] === 0) {
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
delete this.pendingKeyUpdateCount[key];
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -72,12 +72,12 @@ export class PropertiesManager {
|
|
|
72
72
|
if (collaborating && seq === UnassignedSequenceNumber) {
|
|
73
73
|
this.pendingRewriteCount++;
|
|
74
74
|
}
|
|
75
|
-
// We are re-
|
|
75
|
+
// We are re-writing so delete all the properties
|
|
76
76
|
// not in the new props
|
|
77
77
|
for (const key of Object.keys(oldProps)) {
|
|
78
78
|
if (!newProps[key] && shouldModifyKey(key)) {
|
|
79
79
|
deltas[key] = oldProps[key];
|
|
80
|
-
|
|
80
|
+
|
|
81
81
|
delete oldProps[key];
|
|
82
82
|
}
|
|
83
83
|
}
|
|
@@ -105,7 +105,7 @@ export class PropertiesManager {
|
|
|
105
105
|
newValue = newProps[key];
|
|
106
106
|
}
|
|
107
107
|
if (newValue === null) {
|
|
108
|
-
|
|
108
|
+
|
|
109
109
|
delete oldProps[key];
|
|
110
110
|
} else {
|
|
111
111
|
oldProps[key] = newValue;
|
|
@@ -122,7 +122,7 @@ export class PropertiesManager {
|
|
|
122
122
|
): PropertySet | undefined {
|
|
123
123
|
if (oldProps) {
|
|
124
124
|
if (!newProps) {
|
|
125
|
-
|
|
125
|
+
|
|
126
126
|
newProps = createMap<any>();
|
|
127
127
|
}
|
|
128
128
|
if (!newManager) {
|
package/src/snapshotChunks.ts
CHANGED
|
@@ -94,7 +94,7 @@ export function serializeAsMinSupportedVersion(
|
|
|
94
94
|
switch (chunk.version) {
|
|
95
95
|
case undefined:
|
|
96
96
|
targetChuck = chunk as MergeTreeChunkLegacy;
|
|
97
|
-
targetChuck.headerMetadata =
|
|
97
|
+
targetChuck.headerMetadata = buildHeaderMetadataForLegacyChunk(path, targetChuck, options);
|
|
98
98
|
break;
|
|
99
99
|
|
|
100
100
|
case "1":
|
|
@@ -143,7 +143,7 @@ export function toLatestVersion(
|
|
|
143
143
|
version: "1",
|
|
144
144
|
length: chunkLegacy.chunkLengthChars,
|
|
145
145
|
segmentCount: chunkLegacy.chunkSegmentCount,
|
|
146
|
-
headerMetadata:
|
|
146
|
+
headerMetadata: buildHeaderMetadataForLegacyChunk(path, chunkLegacy, options),
|
|
147
147
|
segments: chunkLegacy.segmentTexts,
|
|
148
148
|
startIndex: chunkLegacy.chunkStartSegmentIndex,
|
|
149
149
|
};
|
|
@@ -156,7 +156,7 @@ export function toLatestVersion(
|
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
function
|
|
159
|
+
function buildHeaderMetadataForLegacyChunk(
|
|
160
160
|
path: string, chunk: MergeTreeChunkLegacy, options: PropertySet | undefined): MergeTreeHeaderMetadata | undefined {
|
|
161
161
|
if (path === SnapshotLegacy.header) {
|
|
162
162
|
if (chunk.headerMetadata !== undefined) {
|
package/src/snapshotV1.ts
CHANGED
|
@@ -48,6 +48,7 @@ export class SnapshotV1 {
|
|
|
48
48
|
constructor(
|
|
49
49
|
public mergeTree: MergeTree,
|
|
50
50
|
logger: ITelemetryLogger,
|
|
51
|
+
private readonly getLongClientId: (id: number) => string,
|
|
51
52
|
public filename?: string,
|
|
52
53
|
public onCompletion?: () => void,
|
|
53
54
|
) {
|
|
@@ -209,8 +210,7 @@ export class SnapshotV1 {
|
|
|
209
210
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
210
211
|
if (segment.seq! > minSeq) {
|
|
211
212
|
raw.seq = segment.seq;
|
|
212
|
-
|
|
213
|
-
raw.client = mergeTree.getLongClientId!(segment.clientId);
|
|
213
|
+
raw.client = this.getLongClientId(segment.clientId);
|
|
214
214
|
}
|
|
215
215
|
// We have already dispensed with removed segments below the MSN and removed segments with unassigned
|
|
216
216
|
// sequence numbers. Any remaining removal info should be preserved.
|
|
@@ -219,7 +219,7 @@ export class SnapshotV1 {
|
|
|
219
219
|
0x065 /* "On removal info preservation, segment has invalid removed sequence number!" */);
|
|
220
220
|
raw.removedSeq = segment.removedSeq;
|
|
221
221
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
222
|
-
raw.removedClient =
|
|
222
|
+
raw.removedClient = this.getLongClientId(segment.removedClientId!);
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
// Sanity check that we are preserving either the seq < minSeq or a removed segment's info.
|
package/src/sortedSegmentSet.ts
CHANGED
|
@@ -10,37 +10,37 @@ import { ISegment } from "./mergeTree";
|
|
|
10
10
|
*
|
|
11
11
|
* This differs from a normal sorted set in that the keys are not fixed.
|
|
12
12
|
* The segments are sorted via their ordinals which can change as the merge tree is modified.
|
|
13
|
-
*
|
|
13
|
+
* Even though the values of the ordinals can change their ordering and uniqueness cannot, so the order of a set of
|
|
14
14
|
* segments ordered by their ordinals will always have the same order even if the ordinal values on
|
|
15
|
-
* the segments changes. This
|
|
15
|
+
* the segments changes. This invariant allows ensure the segments stay ordered and unique, and that new segments
|
|
16
16
|
* can be inserted into that order.
|
|
17
17
|
*/
|
|
18
18
|
export class SortedSegmentSet<T extends ISegment | { readonly segment: ISegment } = ISegment> {
|
|
19
|
-
private readonly
|
|
19
|
+
private readonly ordinalSortedItems: T[] = [];
|
|
20
20
|
|
|
21
21
|
public get size(): number {
|
|
22
|
-
return this.
|
|
22
|
+
return this.ordinalSortedItems.length;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
public get items(): readonly T[] {
|
|
26
|
-
return this.
|
|
26
|
+
return this.ordinalSortedItems;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
public addOrUpdate(newItem: T, update?: (existingItem: T, newItem: T) => T) {
|
|
30
30
|
const position = this.findOrdinalPosition(this.getOrdinal(newItem));
|
|
31
31
|
if (position.exists) {
|
|
32
32
|
if (update) {
|
|
33
|
-
update(this.
|
|
33
|
+
update(this.ordinalSortedItems[position.index], newItem);
|
|
34
34
|
}
|
|
35
35
|
} else {
|
|
36
|
-
this.
|
|
36
|
+
this.ordinalSortedItems.splice(position.index, 0, newItem);
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
public remove(item: T): boolean {
|
|
41
41
|
const position = this.findOrdinalPosition(this.getOrdinal(item));
|
|
42
42
|
if (position.exists) {
|
|
43
|
-
this.
|
|
43
|
+
this.ordinalSortedItems.splice(position.index, 1);
|
|
44
44
|
return true;
|
|
45
45
|
}
|
|
46
46
|
return false;
|
|
@@ -62,19 +62,19 @@ export class SortedSegmentSet<T extends ISegment | { readonly segment: ISegment
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
private findOrdinalPosition(ordinal: string, start?: number, end?: number): { exists: boolean, index: number } {
|
|
65
|
-
if (this.
|
|
65
|
+
if (this.ordinalSortedItems.length === 0) {
|
|
66
66
|
return { exists: false, index: 0 };
|
|
67
67
|
}
|
|
68
68
|
if (start === undefined || end === undefined) {
|
|
69
|
-
return this.findOrdinalPosition(ordinal, 0, this.
|
|
69
|
+
return this.findOrdinalPosition(ordinal, 0, this.ordinalSortedItems.length - 1);
|
|
70
70
|
}
|
|
71
71
|
const index = start + Math.floor((end - start) / 2);
|
|
72
|
-
if (this.getOrdinal(this.
|
|
72
|
+
if (this.getOrdinal(this.ordinalSortedItems[index]) > ordinal) {
|
|
73
73
|
if (start === index) {
|
|
74
74
|
return { exists: false, index };
|
|
75
75
|
}
|
|
76
76
|
return this.findOrdinalPosition(ordinal, start, index - 1);
|
|
77
|
-
} else if (this.getOrdinal(this.
|
|
77
|
+
} else if (this.getOrdinal(this.ordinalSortedItems[index]) < ordinal) {
|
|
78
78
|
if (index === end) {
|
|
79
79
|
return { exists: false, index: index + 1 };
|
|
80
80
|
}
|
package/src/textSegment.ts
CHANGED
|
@@ -31,11 +31,11 @@ export class TextSegment extends BaseSegment {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
public static make(text: string, props?: PropertySet) {
|
|
34
|
-
const
|
|
34
|
+
const seg = new TextSegment(text);
|
|
35
35
|
if (props) {
|
|
36
|
-
|
|
36
|
+
seg.addProperties(props);
|
|
37
37
|
}
|
|
38
|
-
return
|
|
38
|
+
return seg;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
public static fromJSONObject(spec: any) {
|