@fluidframework/matrix 2.0.0-internal.4.3.0 → 2.0.0-internal.5.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 +8 -0
- package/dist/matrix.d.ts +3 -3
- package/dist/matrix.d.ts.map +1 -1
- package/dist/matrix.js +4 -26
- package/dist/matrix.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/permutationvector.d.ts +5 -12
- package/dist/permutationvector.d.ts.map +1 -1
- package/dist/permutationvector.js +24 -40
- package/dist/permutationvector.js.map +1 -1
- package/dist/serialization.d.ts +1 -1
- package/dist/serialization.d.ts.map +1 -1
- package/dist/serialization.js +2 -2
- package/dist/serialization.js.map +1 -1
- package/dist/undoprovider.d.ts +6 -8
- package/dist/undoprovider.d.ts.map +1 -1
- package/dist/undoprovider.js +74 -62
- package/dist/undoprovider.js.map +1 -1
- package/lib/matrix.d.ts +3 -3
- package/lib/matrix.d.ts.map +1 -1
- package/lib/matrix.js +5 -27
- package/lib/matrix.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/permutationvector.d.ts +5 -12
- package/lib/permutationvector.d.ts.map +1 -1
- package/lib/permutationvector.js +23 -40
- package/lib/permutationvector.js.map +1 -1
- package/lib/serialization.d.ts +1 -1
- package/lib/serialization.d.ts.map +1 -1
- package/lib/serialization.js +1 -1
- package/lib/serialization.js.map +1 -1
- package/lib/undoprovider.d.ts +6 -8
- package/lib/undoprovider.d.ts.map +1 -1
- package/lib/undoprovider.js +75 -63
- package/lib/undoprovider.js.map +1 -1
- package/package.json +12 -12
- package/src/matrix.ts +6 -38
- package/src/packageVersion.ts +1 -1
- package/src/permutationvector.ts +33 -46
- package/src/serialization.ts +1 -1
- package/src/undoprovider.ts +83 -74
package/src/undoprovider.ts
CHANGED
|
@@ -5,10 +5,15 @@
|
|
|
5
5
|
|
|
6
6
|
import { assert } from "@fluidframework/common-utils";
|
|
7
7
|
import {
|
|
8
|
-
TrackingGroup,
|
|
9
|
-
MergeTreeDeltaOperationType,
|
|
10
8
|
MergeTreeDeltaType,
|
|
11
|
-
|
|
9
|
+
MergeTreeDeltaRevertible,
|
|
10
|
+
IMergeTreeDeltaCallbackArgs,
|
|
11
|
+
appendToMergeTreeDeltaRevertibles,
|
|
12
|
+
revertMergeTreeDeltaRevertibles,
|
|
13
|
+
MergeTreeRevertibleDriver,
|
|
14
|
+
discardMergeTreeDeltaRevertible,
|
|
15
|
+
TrackingGroup,
|
|
16
|
+
ITrackingGroup,
|
|
12
17
|
} from "@fluidframework/merge-tree";
|
|
13
18
|
import { MatrixItem, SharedMatrix } from "./matrix";
|
|
14
19
|
import { Handle, isHandleValid } from "./handletable";
|
|
@@ -19,58 +24,55 @@ export class VectorUndoProvider {
|
|
|
19
24
|
// 'currentGroup' and 'currentOp' are used while applying an IRevertable.revert() to coalesce
|
|
20
25
|
// the recorded into a single IRevertable / tracking group as they move between the undo <->
|
|
21
26
|
// redo stacks.
|
|
22
|
-
private currentGroup?:
|
|
27
|
+
private currentGroup?: MergeTreeDeltaRevertible[];
|
|
23
28
|
private currentOp?: MergeTreeDeltaType;
|
|
29
|
+
private currentRemoveTrackingGroup?: TrackingGroup;
|
|
24
30
|
|
|
25
31
|
constructor(
|
|
26
32
|
private readonly manager: IUndoConsumer,
|
|
27
|
-
private readonly
|
|
28
|
-
private readonly undoRemove: (segment: PermutationSegment) => void,
|
|
33
|
+
private readonly driver: MergeTreeRevertibleDriver,
|
|
29
34
|
) {}
|
|
30
35
|
|
|
31
|
-
public record(
|
|
32
|
-
|
|
33
|
-
ranges: { segment: PermutationSegment }[],
|
|
34
|
-
) {
|
|
35
|
-
if (ranges.length > 0) {
|
|
36
|
-
// Link each segment to a new TrackingGroup. A TrackingGroup keeps track of the original
|
|
37
|
-
// set of linked segments, including any fragmentatiton that occurs due to future splitting.
|
|
38
|
-
//
|
|
39
|
-
// A TrackingGroup also prevents removed segments from being unlinked from the tree during
|
|
40
|
-
// Zamboni and guarantees segments will not be merged/coalesced with segments outside of the
|
|
41
|
-
// current tracking group.
|
|
42
|
-
//
|
|
43
|
-
// These properties allow us to rely on MergeTree.getPosition() to find the locations/lengths
|
|
44
|
-
// of all content contained within the tracking group in the future.
|
|
45
|
-
|
|
36
|
+
public record(deltaArgs: IMergeTreeDeltaCallbackArgs) {
|
|
37
|
+
if (deltaArgs.deltaSegments.length > 0) {
|
|
46
38
|
// If we are in the process of reverting, the `IRevertible.revert()` will provide the tracking
|
|
47
39
|
// group so that we can preserve the original segment ranges as a single op/group as we move
|
|
48
40
|
// ops between the undo <-> redo stacks.
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
trackingGroup.link(range.segment);
|
|
52
|
-
}
|
|
41
|
+
const revertibles: MergeTreeDeltaRevertible[] = this.currentGroup ?? [];
|
|
42
|
+
appendToMergeTreeDeltaRevertibles(deltaArgs, revertibles);
|
|
53
43
|
|
|
54
44
|
// For SharedMatrix, each IRevertibles always holds a single row/col operation.
|
|
55
45
|
// Therefore, 'currentOp' must either be undefined or equal to the current op.
|
|
56
46
|
assert(
|
|
57
|
-
this.currentOp === undefined || this.currentOp === operation,
|
|
47
|
+
this.currentOp === undefined || this.currentOp === deltaArgs.operation,
|
|
58
48
|
0x02a /* "On vector undo, unexpected 'currentOp' type/state!" */,
|
|
59
49
|
);
|
|
50
|
+
let removeTrackingGroup: TrackingGroup | undefined;
|
|
51
|
+
if (deltaArgs.operation === MergeTreeDeltaType.REMOVE) {
|
|
52
|
+
// for removed segment we need a tracking group.
|
|
53
|
+
// this is for a few reason:
|
|
54
|
+
// 1. the handle for the row/column on the removed segment is still allocated,
|
|
55
|
+
// and needs to be in order to process unacked ops sent before the remove.
|
|
56
|
+
// 2. handles are freed on unlink(zamboni), but that also clears the row/column data.
|
|
57
|
+
// which we don't want to happen, so we can re-insert the cells when the row/col comes back.
|
|
58
|
+
// the tracking group prevents unlink.
|
|
59
|
+
// 3. when we re-insert we need to find the old segment and clear their handles
|
|
60
|
+
// so the new segment takes them over. there is no efficient look-up for this.
|
|
61
|
+
// the tracking group provides one.
|
|
62
|
+
const trackingGroup = (removeTrackingGroup =
|
|
63
|
+
this.currentRemoveTrackingGroup ?? new TrackingGroup());
|
|
64
|
+
deltaArgs.deltaSegments.forEach((d) =>
|
|
65
|
+
d.segment.trackingCollection.link(trackingGroup),
|
|
66
|
+
);
|
|
67
|
+
}
|
|
60
68
|
|
|
61
|
-
switch (operation) {
|
|
69
|
+
switch (deltaArgs.operation) {
|
|
70
|
+
case MergeTreeDeltaType.REMOVE:
|
|
62
71
|
case MergeTreeDeltaType.INSERT:
|
|
63
|
-
if (this.currentOp !==
|
|
64
|
-
this.pushRevertible(
|
|
65
|
-
}
|
|
66
|
-
break;
|
|
67
|
-
|
|
68
|
-
case MergeTreeDeltaType.REMOVE: {
|
|
69
|
-
if (this.currentOp !== MergeTreeDeltaType.REMOVE) {
|
|
70
|
-
this.pushRevertible(trackingGroup, this.undoRemove);
|
|
72
|
+
if (this.currentOp !== deltaArgs.operation) {
|
|
73
|
+
this.pushRevertible(revertibles, removeTrackingGroup);
|
|
71
74
|
}
|
|
72
75
|
break;
|
|
73
|
-
}
|
|
74
76
|
|
|
75
77
|
default:
|
|
76
78
|
throw new Error("operation type not revertible");
|
|
@@ -80,50 +82,59 @@ export class VectorUndoProvider {
|
|
|
80
82
|
// another revertible until `IRevertable.revert()` finishes the current op and clears this
|
|
81
83
|
// field.
|
|
82
84
|
if (this.currentGroup !== undefined) {
|
|
83
|
-
this.currentOp
|
|
85
|
+
this.currentOp ??= deltaArgs.operation;
|
|
86
|
+
this.currentRemoveTrackingGroup ??= removeTrackingGroup;
|
|
84
87
|
}
|
|
85
88
|
}
|
|
86
89
|
}
|
|
87
90
|
|
|
88
91
|
private pushRevertible(
|
|
89
|
-
|
|
90
|
-
|
|
92
|
+
revertibles: MergeTreeDeltaRevertible[],
|
|
93
|
+
removedTrackingGroup: ITrackingGroup | undefined,
|
|
91
94
|
) {
|
|
92
|
-
const
|
|
95
|
+
const reverter = {
|
|
93
96
|
revert: () => {
|
|
94
97
|
assert(
|
|
95
98
|
this.currentGroup === undefined && this.currentOp === undefined,
|
|
96
99
|
0x02b /* "Must not nest calls to IRevertible.revert()" */,
|
|
97
100
|
);
|
|
98
101
|
|
|
99
|
-
this.currentGroup =
|
|
102
|
+
this.currentGroup = [];
|
|
100
103
|
|
|
101
104
|
try {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
105
|
+
if (removedTrackingGroup !== undefined) {
|
|
106
|
+
while (removedTrackingGroup.size > 0) {
|
|
107
|
+
const tracked = removedTrackingGroup.tracked[0];
|
|
108
|
+
removedTrackingGroup.unlink(tracked);
|
|
109
|
+
// if there are groups tracked, this in a revert of a remove.
|
|
110
|
+
// this means we are about to re-insert the row/column
|
|
111
|
+
// with the same handle. We reuse the handle so the row/columns cells
|
|
112
|
+
// get re-inserted too.
|
|
113
|
+
// since a new segment will have the handle, we need to
|
|
114
|
+
// remove it from the removed segment which was tracked
|
|
115
|
+
(tracked as PermutationSegment).reset();
|
|
116
|
+
}
|
|
111
117
|
}
|
|
118
|
+
revertMergeTreeDeltaRevertibles(this.driver, revertibles);
|
|
112
119
|
} finally {
|
|
113
120
|
this.currentOp = undefined;
|
|
114
121
|
this.currentGroup = undefined;
|
|
122
|
+
this.currentRemoveTrackingGroup = undefined;
|
|
115
123
|
}
|
|
116
124
|
},
|
|
117
125
|
discard: () => {
|
|
118
|
-
|
|
119
|
-
|
|
126
|
+
if (removedTrackingGroup !== undefined) {
|
|
127
|
+
while (removedTrackingGroup.size > 0) {
|
|
128
|
+
removedTrackingGroup.unlink(removedTrackingGroup.tracked[0]);
|
|
129
|
+
}
|
|
120
130
|
}
|
|
131
|
+
discardMergeTreeDeltaRevertible(revertibles);
|
|
121
132
|
},
|
|
122
133
|
};
|
|
123
134
|
|
|
124
|
-
this.manager.pushToCurrentOperation(
|
|
135
|
+
this.manager.pushToCurrentOperation(reverter);
|
|
125
136
|
|
|
126
|
-
return
|
|
137
|
+
return reverter;
|
|
127
138
|
}
|
|
128
139
|
}
|
|
129
140
|
|
|
@@ -134,30 +145,28 @@ export class MatrixUndoProvider<T> {
|
|
|
134
145
|
private readonly rows: PermutationVector,
|
|
135
146
|
private readonly cols: PermutationVector,
|
|
136
147
|
) {
|
|
137
|
-
rows.undo = new VectorUndoProvider(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if (toRemovalInfo(segment) === undefined) {
|
|
141
|
-
const start = this.rows.getPosition(segment);
|
|
142
|
-
this.matrix.removeRows(start, segment.cachedLength);
|
|
143
|
-
}
|
|
148
|
+
rows.undo = new VectorUndoProvider(consumer, {
|
|
149
|
+
annotateRange() {
|
|
150
|
+
throw new Error("not implemented");
|
|
144
151
|
},
|
|
145
|
-
|
|
146
|
-
|
|
152
|
+
insertFromSpec(pos, spec) {
|
|
153
|
+
matrix._undoRemoveRows(pos, spec);
|
|
147
154
|
},
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
consumer,
|
|
151
|
-
/* undoInsert: */ (segment: PermutationSegment) => {
|
|
152
|
-
if (toRemovalInfo(segment) === undefined) {
|
|
153
|
-
const start = this.cols.getPosition(segment);
|
|
154
|
-
this.matrix.removeCols(start, segment.cachedLength);
|
|
155
|
-
}
|
|
155
|
+
removeRange(start, end) {
|
|
156
|
+
matrix.removeRows(start, end - start);
|
|
156
157
|
},
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
});
|
|
159
|
+
cols.undo = new VectorUndoProvider(consumer, {
|
|
160
|
+
annotateRange() {
|
|
161
|
+
throw new Error("not implemented");
|
|
159
162
|
},
|
|
160
|
-
|
|
163
|
+
insertFromSpec(pos, spec) {
|
|
164
|
+
matrix._undoRemoveCols(pos, spec);
|
|
165
|
+
},
|
|
166
|
+
removeRange(start, end) {
|
|
167
|
+
matrix.removeCols(start, end - start);
|
|
168
|
+
},
|
|
169
|
+
});
|
|
161
170
|
}
|
|
162
171
|
|
|
163
172
|
cellSet(rowHandle: Handle, colHandle: Handle, oldValue: MatrixItem<T>) {
|