@fluid-experimental/tree 0.59.2001 → 0.59.3000
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/.eslintrc.js +2 -0
- package/.vscode/SharedTree.code-workspace +15 -0
- package/.vscode/settings.json +6 -0
- package/dist/ChangeCompression.js +9 -9
- package/dist/ChangeCompression.js.map +1 -1
- package/dist/ChangeTypes.d.ts +1 -6
- package/dist/ChangeTypes.d.ts.map +1 -1
- package/dist/ChangeTypes.js +5 -5
- package/dist/ChangeTypes.js.map +1 -1
- package/dist/Checkout.js +14 -14
- package/dist/Checkout.js.map +1 -1
- package/dist/Common.d.ts +21 -3
- package/dist/Common.d.ts.map +1 -1
- package/dist/Common.js +29 -4
- package/dist/Common.js.map +1 -1
- package/dist/EditLog.js +26 -25
- package/dist/EditLog.js.map +1 -1
- package/dist/EditUtilities.js +17 -17
- package/dist/EditUtilities.js.map +1 -1
- package/dist/Forest.js +31 -31
- package/dist/Forest.js.map +1 -1
- package/dist/HistoryEditFactory.js +9 -9
- package/dist/HistoryEditFactory.js.map +1 -1
- package/dist/IdConversion.js +9 -9
- package/dist/IdConversion.js.map +1 -1
- package/dist/Identifiers.d.ts +4 -0
- package/dist/Identifiers.d.ts.map +1 -1
- package/dist/Identifiers.js.map +1 -1
- package/dist/LogViewer.d.ts +1 -5
- package/dist/LogViewer.d.ts.map +1 -1
- package/dist/LogViewer.js +11 -19
- package/dist/LogViewer.js.map +1 -1
- package/dist/MergeHealth.js +2 -2
- package/dist/MergeHealth.js.map +1 -1
- package/dist/NodeIdUtilities.js +2 -2
- package/dist/NodeIdUtilities.js.map +1 -1
- package/dist/PayloadUtilities.js +1 -1
- package/dist/PayloadUtilities.js.map +1 -1
- package/dist/RevisionValueCache.d.ts +13 -10
- package/dist/RevisionValueCache.d.ts.map +1 -1
- package/dist/RevisionValueCache.js +14 -11
- package/dist/RevisionValueCache.js.map +1 -1
- package/dist/RevisionView.js +4 -4
- package/dist/RevisionView.js.map +1 -1
- package/dist/SerializationUtilities.js +4 -4
- package/dist/SerializationUtilities.js.map +1 -1
- package/dist/SharedTree.d.ts +93 -31
- package/dist/SharedTree.d.ts.map +1 -1
- package/dist/SharedTree.js +160 -131
- package/dist/SharedTree.js.map +1 -1
- package/dist/SharedTreeEncoder.d.ts +3 -3
- package/dist/SharedTreeEncoder.d.ts.map +1 -1
- package/dist/SharedTreeEncoder.js +36 -36
- package/dist/SharedTreeEncoder.js.map +1 -1
- package/dist/StringInterner.js +1 -1
- package/dist/StringInterner.js.map +1 -1
- package/dist/Summary.js +1 -1
- package/dist/Summary.js.map +1 -1
- package/dist/SummaryBackCompatibility.js +8 -8
- package/dist/SummaryBackCompatibility.js.map +1 -1
- package/dist/Transaction.js +1 -1
- package/dist/Transaction.js.map +1 -1
- package/dist/TransactionInternal.js +17 -17
- package/dist/TransactionInternal.js.map +1 -1
- package/dist/TreeCompressor.d.ts.map +1 -1
- package/dist/TreeCompressor.js +6 -8
- package/dist/TreeCompressor.js.map +1 -1
- package/dist/TreeNodeHandle.js +4 -4
- package/dist/TreeNodeHandle.js.map +1 -1
- package/dist/TreeView.js +7 -7
- package/dist/TreeView.js.map +1 -1
- package/dist/TreeViewUtilities.js +2 -2
- package/dist/TreeViewUtilities.js.map +1 -1
- package/dist/UndoRedoHandler.js +1 -1
- package/dist/UndoRedoHandler.js.map +1 -1
- package/dist/UuidUtilities.d.ts +30 -0
- package/dist/UuidUtilities.d.ts.map +1 -0
- package/dist/UuidUtilities.js +106 -0
- package/dist/UuidUtilities.js.map +1 -0
- package/dist/id-compressor/AppendOnlySortedMap.d.ts +52 -28
- package/dist/id-compressor/AppendOnlySortedMap.d.ts.map +1 -1
- package/dist/id-compressor/AppendOnlySortedMap.js +167 -90
- package/dist/id-compressor/AppendOnlySortedMap.js.map +1 -1
- package/dist/id-compressor/IdCompressor.d.ts +43 -42
- package/dist/id-compressor/IdCompressor.d.ts.map +1 -1
- package/dist/id-compressor/IdCompressor.js +179 -177
- package/dist/id-compressor/IdCompressor.js.map +1 -1
- package/dist/id-compressor/IdRange.js +1 -1
- package/dist/id-compressor/IdRange.js.map +1 -1
- package/dist/id-compressor/NumericUuid.d.ts +6 -14
- package/dist/id-compressor/NumericUuid.d.ts.map +1 -1
- package/dist/id-compressor/NumericUuid.js +15 -76
- package/dist/id-compressor/NumericUuid.js.map +1 -1
- package/dist/id-compressor/SessionIdNormalizer.d.ts +122 -0
- package/dist/id-compressor/SessionIdNormalizer.d.ts.map +1 -0
- package/dist/id-compressor/SessionIdNormalizer.js +418 -0
- package/dist/id-compressor/SessionIdNormalizer.js.map +1 -0
- package/dist/id-compressor/persisted-types/0.0.1.d.ts +6 -13
- package/dist/id-compressor/persisted-types/0.0.1.d.ts.map +1 -1
- package/dist/id-compressor/persisted-types/0.0.1.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/persisted-types/0.1.1.d.ts +1 -6
- package/dist/persisted-types/0.1.1.d.ts.map +1 -1
- package/dist/persisted-types/0.1.1.js +3 -3
- package/dist/persisted-types/0.1.1.js.map +1 -1
- package/lib/ChangeTypes.d.ts +1 -6
- package/lib/ChangeTypes.d.ts.map +1 -1
- package/lib/Checkout.js.map +1 -1
- package/lib/Common.d.ts +21 -3
- package/lib/Common.d.ts.map +1 -1
- package/lib/Common.js +25 -3
- package/lib/Common.js.map +1 -1
- package/lib/EditLog.js +2 -1
- package/lib/EditLog.js.map +1 -1
- package/lib/EditUtilities.js.map +1 -1
- package/lib/Forest.js.map +1 -1
- package/lib/HistoryEditFactory.js.map +1 -1
- package/lib/Identifiers.d.ts +4 -0
- package/lib/Identifiers.d.ts.map +1 -1
- package/lib/Identifiers.js.map +1 -1
- package/lib/LogViewer.d.ts +1 -5
- package/lib/LogViewer.d.ts.map +1 -1
- package/lib/LogViewer.js +5 -13
- package/lib/LogViewer.js.map +1 -1
- package/lib/MergeHealth.js.map +1 -1
- package/lib/NodeIdUtilities.js.map +1 -1
- package/lib/RevisionValueCache.d.ts +13 -10
- package/lib/RevisionValueCache.d.ts.map +1 -1
- package/lib/RevisionValueCache.js +10 -7
- package/lib/RevisionValueCache.js.map +1 -1
- package/lib/RevisionView.js.map +1 -1
- package/lib/SharedTree.d.ts +93 -31
- package/lib/SharedTree.d.ts.map +1 -1
- package/lib/SharedTree.js +107 -78
- package/lib/SharedTree.js.map +1 -1
- package/lib/SharedTreeEncoder.d.ts +3 -3
- package/lib/SharedTreeEncoder.d.ts.map +1 -1
- package/lib/SharedTreeEncoder.js +4 -4
- package/lib/SharedTreeEncoder.js.map +1 -1
- package/lib/StringInterner.js.map +1 -1
- package/lib/Summary.js.map +1 -1
- package/lib/TreeCompressor.d.ts.map +1 -1
- package/lib/TreeCompressor.js +1 -3
- package/lib/TreeCompressor.js.map +1 -1
- package/lib/TreeNodeHandle.js.map +1 -1
- package/lib/TreeView.js.map +1 -1
- package/lib/TreeViewUtilities.js.map +1 -1
- package/lib/UuidUtilities.d.ts +30 -0
- package/lib/UuidUtilities.d.ts.map +1 -0
- package/lib/UuidUtilities.js +98 -0
- package/lib/UuidUtilities.js.map +1 -0
- package/lib/id-compressor/AppendOnlySortedMap.d.ts +52 -28
- package/lib/id-compressor/AppendOnlySortedMap.d.ts.map +1 -1
- package/lib/id-compressor/AppendOnlySortedMap.js +165 -88
- package/lib/id-compressor/AppendOnlySortedMap.js.map +1 -1
- package/lib/id-compressor/IdCompressor.d.ts +43 -42
- package/lib/id-compressor/IdCompressor.d.ts.map +1 -1
- package/lib/id-compressor/IdCompressor.js +97 -95
- package/lib/id-compressor/IdCompressor.js.map +1 -1
- package/lib/id-compressor/NumericUuid.d.ts +6 -14
- package/lib/id-compressor/NumericUuid.d.ts.map +1 -1
- package/lib/id-compressor/NumericUuid.js +11 -70
- package/lib/id-compressor/NumericUuid.js.map +1 -1
- package/lib/id-compressor/SessionIdNormalizer.d.ts +122 -0
- package/lib/id-compressor/SessionIdNormalizer.d.ts.map +1 -0
- package/lib/id-compressor/SessionIdNormalizer.js +414 -0
- package/lib/id-compressor/SessionIdNormalizer.js.map +1 -0
- package/lib/id-compressor/persisted-types/0.0.1.d.ts +6 -13
- package/lib/id-compressor/persisted-types/0.0.1.d.ts.map +1 -1
- package/lib/id-compressor/persisted-types/0.0.1.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/persisted-types/0.1.1.d.ts +1 -6
- package/lib/persisted-types/0.1.1.d.ts.map +1 -1
- package/lib/persisted-types/0.1.1.js.map +1 -1
- package/lib/test/AppendOnlySortedMap.perf.tests.d.ts +6 -0
- package/lib/test/AppendOnlySortedMap.perf.tests.d.ts.map +1 -0
- package/lib/test/AppendOnlySortedMap.perf.tests.js +49 -0
- package/lib/test/AppendOnlySortedMap.perf.tests.js.map +1 -0
- package/lib/test/AppendOnlySortedMap.tests.js +56 -14
- package/lib/test/AppendOnlySortedMap.tests.js.map +1 -1
- package/lib/test/Checkout.tests.js +2 -2
- package/lib/test/Checkout.tests.js.map +1 -1
- package/lib/test/Forest.tests.js.map +1 -1
- package/lib/test/IdCompressor.perf.tests.js +8 -2
- package/lib/test/IdCompressor.perf.tests.js.map +1 -1
- package/lib/test/IdCompressor.tests.js +75 -24
- package/lib/test/IdCompressor.tests.js.map +1 -1
- package/lib/test/LogViewer.tests.js +3 -5
- package/lib/test/LogViewer.tests.js.map +1 -1
- package/lib/test/NumericUuid.perf.tests.js +4 -4
- package/lib/test/NumericUuid.perf.tests.js.map +1 -1
- package/lib/test/NumericUuid.tests.js +5 -4
- package/lib/test/NumericUuid.tests.js.map +1 -1
- package/lib/test/RevisionValueCache.tests.js.map +1 -1
- package/lib/test/RevisionView.tests.js.map +1 -1
- package/lib/test/SessionIdNormalizer.tests.d.ts +6 -0
- package/lib/test/SessionIdNormalizer.tests.d.ts.map +1 -0
- package/lib/test/SessionIdNormalizer.tests.js +299 -0
- package/lib/test/SessionIdNormalizer.tests.js.map +1 -0
- package/lib/test/Summary.tests.js +1 -1
- package/lib/test/Summary.tests.js.map +1 -1
- package/lib/test/TreeCompression.tests.js +1 -1
- package/lib/test/TreeCompression.tests.js.map +1 -1
- package/lib/test/Virtualization.tests.js +1 -1
- package/lib/test/Virtualization.tests.js.map +1 -1
- package/lib/test/fuzz/Generators.d.ts +3 -14
- package/lib/test/fuzz/Generators.d.ts.map +1 -1
- package/lib/test/fuzz/Generators.js +60 -151
- package/lib/test/fuzz/Generators.js.map +1 -1
- package/lib/test/fuzz/SharedTreeFuzzTests.d.ts +10 -7
- package/lib/test/fuzz/SharedTreeFuzzTests.d.ts.map +1 -1
- package/lib/test/fuzz/SharedTreeFuzzTests.js +94 -104
- package/lib/test/fuzz/SharedTreeFuzzTests.js.map +1 -1
- package/lib/test/fuzz/Types.d.ts +2 -9
- package/lib/test/fuzz/Types.d.ts.map +1 -1
- package/lib/test/fuzz/Types.js +1 -1
- package/lib/test/fuzz/Types.js.map +1 -1
- package/lib/test/utilities/IdCompressorTestUtilities.d.ts +57 -11
- package/lib/test/utilities/IdCompressorTestUtilities.d.ts.map +1 -1
- package/lib/test/utilities/IdCompressorTestUtilities.js +112 -98
- package/lib/test/utilities/IdCompressorTestUtilities.js.map +1 -1
- package/lib/test/utilities/PendingLocalStateTests.d.ts.map +1 -1
- package/lib/test/utilities/PendingLocalStateTests.js +2 -1
- package/lib/test/utilities/PendingLocalStateTests.js.map +1 -1
- package/lib/test/utilities/SharedTreeTests.d.ts.map +1 -1
- package/lib/test/utilities/SharedTreeTests.js +30 -1
- package/lib/test/utilities/SharedTreeTests.js.map +1 -1
- package/lib/test/utilities/SharedTreeVersioningTests.d.ts.map +1 -1
- package/lib/test/utilities/SharedTreeVersioningTests.js +20 -0
- package/lib/test/utilities/SharedTreeVersioningTests.js.map +1 -1
- package/lib/test/utilities/SummaryLoadPerfTests.d.ts.map +1 -1
- package/lib/test/utilities/SummaryLoadPerfTests.js +6 -3
- package/lib/test/utilities/SummaryLoadPerfTests.js.map +1 -1
- package/lib/test/utilities/TestNode.js.map +1 -1
- package/lib/test/utilities/TestUtilities.d.ts +9 -1
- package/lib/test/utilities/TestUtilities.d.ts.map +1 -1
- package/lib/test/utilities/TestUtilities.js +27 -13
- package/lib/test/utilities/TestUtilities.js.map +1 -1
- package/package.json +19 -17
- package/src/Common.ts +42 -4
- package/src/EditLog.ts +1 -1
- package/src/Identifiers.ts +5 -0
- package/src/LogViewer.ts +4 -20
- package/src/RevisionValueCache.ts +11 -8
- package/src/SharedTree.ts +222 -75
- package/src/SharedTreeEncoder.ts +17 -11
- package/src/TreeCompressor.ts +2 -4
- package/src/UuidUtilities.ts +123 -0
- package/src/id-compressor/AppendOnlySortedMap.ts +183 -94
- package/src/id-compressor/IdCompressor.ts +144 -132
- package/src/id-compressor/NumericUuid.ts +11 -80
- package/src/id-compressor/SessionIdNormalizer.ts +497 -0
- package/src/id-compressor/persisted-types/0.0.1.ts +12 -15
- package/src/index.ts +5 -0
package/dist/EditUtilities.js
CHANGED
|
@@ -36,7 +36,7 @@ exports.newEdit = newEdit;
|
|
|
36
36
|
* Generates a new edit object from the supplied changes.
|
|
37
37
|
*/
|
|
38
38
|
function newEditId() {
|
|
39
|
-
return uuid_1.v4();
|
|
39
|
+
return (0, uuid_1.v4)();
|
|
40
40
|
}
|
|
41
41
|
exports.newEditId = newEditId;
|
|
42
42
|
/**
|
|
@@ -56,9 +56,9 @@ function convertTreeNodes(root, convert, isPlaceholder) {
|
|
|
56
56
|
// `convertedRoot` might be the same as `root`, in which case stash the children of `root` before wiping them from `convertedRoot`
|
|
57
57
|
const rootTraits = root === convertedRoot ? { traits: root.traits } : root;
|
|
58
58
|
convertedRoot.traits = {};
|
|
59
|
-
const pendingNodes = [{ childIterator: RevisionView_1.iterateChildren(rootTraits)[Symbol.iterator](), newNode: convertedRoot }];
|
|
59
|
+
const pendingNodes = [{ childIterator: (0, RevisionView_1.iterateChildren)(rootTraits)[Symbol.iterator](), newNode: convertedRoot }];
|
|
60
60
|
while (pendingNodes.length > 0) {
|
|
61
|
-
const { childIterator, newNode } = (_a = pendingNodes[pendingNodes.length - 1]) !== null && _a !== void 0 ? _a : Common_1.fail('Undefined node');
|
|
61
|
+
const { childIterator, newNode } = (_a = pendingNodes[pendingNodes.length - 1]) !== null && _a !== void 0 ? _a : (0, Common_1.fail)('Undefined node');
|
|
62
62
|
const { value, done } = childIterator.next();
|
|
63
63
|
if (done === true) {
|
|
64
64
|
pendingNodes.pop();
|
|
@@ -71,7 +71,7 @@ function convertTreeNodes(root, convert, isPlaceholder) {
|
|
|
71
71
|
if (child.traits !== undefined) {
|
|
72
72
|
const childTraits = child === convertedChild ? { traits: child.traits } : child;
|
|
73
73
|
pendingNodes.push({
|
|
74
|
-
childIterator: RevisionView_1.iterateChildren(childTraits)[Symbol.iterator](),
|
|
74
|
+
childIterator: (0, RevisionView_1.iterateChildren)(childTraits)[Symbol.iterator](),
|
|
75
75
|
newNode: convertedChild,
|
|
76
76
|
});
|
|
77
77
|
}
|
|
@@ -101,9 +101,9 @@ function walkTree(tree, visitors, isPlaceholder) {
|
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
103
|
nodeVisitor === null || nodeVisitor === void 0 ? void 0 : nodeVisitor(tree);
|
|
104
|
-
const childIterators = [RevisionView_1.iterateChildren(tree)[Symbol.iterator]()];
|
|
104
|
+
const childIterators = [(0, RevisionView_1.iterateChildren)(tree)[Symbol.iterator]()];
|
|
105
105
|
while (childIterators.length > 0) {
|
|
106
|
-
const childIterator = (_a = childIterators[childIterators.length - 1]) !== null && _a !== void 0 ? _a : Common_1.fail('Undefined node');
|
|
106
|
+
const childIterator = (_a = childIterators[childIterators.length - 1]) !== null && _a !== void 0 ? _a : (0, Common_1.fail)('Undefined node');
|
|
107
107
|
const { value, done } = childIterator.next();
|
|
108
108
|
if (done === true) {
|
|
109
109
|
childIterators.pop();
|
|
@@ -115,7 +115,7 @@ function walkTree(tree, visitors, isPlaceholder) {
|
|
|
115
115
|
}
|
|
116
116
|
else {
|
|
117
117
|
nodeVisitor === null || nodeVisitor === void 0 ? void 0 : nodeVisitor(child);
|
|
118
|
-
childIterators.push(RevisionView_1.iterateChildren(child)[Symbol.iterator]());
|
|
118
|
+
childIterators.push((0, RevisionView_1.iterateChildren)(child)[Symbol.iterator]());
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
}
|
|
@@ -148,7 +148,7 @@ function deepCompareNodes(a, b, comparator = compareNodes) {
|
|
|
148
148
|
if (childrenA.length !== childrenB.length) {
|
|
149
149
|
return false;
|
|
150
150
|
}
|
|
151
|
-
const traitsEqual = Common_1.compareArrays(childrenA, childrenB, (childA, childB) => {
|
|
151
|
+
const traitsEqual = (0, Common_1.compareArrays)(childrenA, childrenB, (childA, childB) => {
|
|
152
152
|
if (typeof childA === 'number' || typeof childB === 'number') {
|
|
153
153
|
// Check if children are DetachedSequenceIds
|
|
154
154
|
return childA === childB;
|
|
@@ -177,7 +177,7 @@ function compareNodes(a, b) {
|
|
|
177
177
|
if (a.definition !== b.definition) {
|
|
178
178
|
return false;
|
|
179
179
|
}
|
|
180
|
-
if (!PayloadUtilities_1.comparePayloads(a.payload, b.payload)) {
|
|
180
|
+
if (!(0, PayloadUtilities_1.comparePayloads)(a.payload, b.payload)) {
|
|
181
181
|
return false;
|
|
182
182
|
}
|
|
183
183
|
return true;
|
|
@@ -187,8 +187,8 @@ exports.compareNodes = compareNodes;
|
|
|
187
187
|
* Compare two views such that semantically equivalent node IDs are considered equal.
|
|
188
188
|
*/
|
|
189
189
|
function areRevisionViewsSemanticallyEqual(treeViewA, idConverterA, treeViewB, idConverterB) {
|
|
190
|
-
const treeA = SerializationUtilities_1.getChangeNode_0_0_2FromView(treeViewA, idConverterA);
|
|
191
|
-
const treeB = SerializationUtilities_1.getChangeNode_0_0_2FromView(treeViewB, idConverterB);
|
|
190
|
+
const treeA = (0, SerializationUtilities_1.getChangeNode_0_0_2FromView)(treeViewA, idConverterA);
|
|
191
|
+
const treeB = (0, SerializationUtilities_1.getChangeNode_0_0_2FromView)(treeViewB, idConverterB);
|
|
192
192
|
if (!deepCompareNodes(treeA, treeB)) {
|
|
193
193
|
return false;
|
|
194
194
|
}
|
|
@@ -294,7 +294,7 @@ function validateStableRange(view, range) {
|
|
|
294
294
|
if (!compareTraits(startTraitLocation, endTraitLocation)) {
|
|
295
295
|
return { result: RangeValidationResultKind.PlacesInDifferentTraits };
|
|
296
296
|
}
|
|
297
|
-
const { start: startPlace, end: endPlace } = TreeViewUtilities_1.rangeFromStableRange(view, {
|
|
297
|
+
const { start: startPlace, end: endPlace } = (0, TreeViewUtilities_1.rangeFromStableRange)(view, {
|
|
298
298
|
start: validatedStart,
|
|
299
299
|
end: validatedEnd,
|
|
300
300
|
});
|
|
@@ -331,7 +331,7 @@ function compareTraits(traitA, traitB) {
|
|
|
331
331
|
* @param placeToInsert - the location to insert the nodes.
|
|
332
332
|
*/
|
|
333
333
|
function insertIntoTrait(view, nodesToInsert, placeToInsert) {
|
|
334
|
-
return view.attachRange(nodesToInsert, TreeViewUtilities_1.placeFromStablePlace(view, placeToInsert));
|
|
334
|
+
return view.attachRange(nodesToInsert, (0, TreeViewUtilities_1.placeFromStablePlace)(view, placeToInsert));
|
|
335
335
|
}
|
|
336
336
|
exports.insertIntoTrait = insertIntoTrait;
|
|
337
337
|
/**
|
|
@@ -339,7 +339,7 @@ exports.insertIntoTrait = insertIntoTrait;
|
|
|
339
339
|
* @param rangeToDetach - the range of nodes to detach
|
|
340
340
|
*/
|
|
341
341
|
function detachRange(view, rangeToDetach) {
|
|
342
|
-
return view.detachRange(TreeViewUtilities_1.rangeFromStableRange(view, rangeToDetach));
|
|
342
|
+
return view.detachRange((0, TreeViewUtilities_1.rangeFromStableRange)(view, rangeToDetach));
|
|
343
343
|
}
|
|
344
344
|
exports.detachRange = detachRange;
|
|
345
345
|
/**
|
|
@@ -347,8 +347,8 @@ exports.detachRange = detachRange;
|
|
|
347
347
|
*/
|
|
348
348
|
function deepCloneStablePlace(place) {
|
|
349
349
|
const clone = { side: place.side };
|
|
350
|
-
Common_1.copyPropertyIfDefined(place, clone, 'referenceSibling');
|
|
351
|
-
Common_1.copyPropertyIfDefined(place, clone, 'referenceTrait');
|
|
350
|
+
(0, Common_1.copyPropertyIfDefined)(place, clone, 'referenceSibling');
|
|
351
|
+
(0, Common_1.copyPropertyIfDefined)(place, clone, 'referenceTrait');
|
|
352
352
|
return clone;
|
|
353
353
|
}
|
|
354
354
|
exports.deepCloneStablePlace = deepCloneStablePlace;
|
|
@@ -366,7 +366,7 @@ function internalizeBuildNode(nodeData, nodeIdContext) {
|
|
|
366
366
|
definition: nodeData.definition,
|
|
367
367
|
identifier: (_a = nodeData.identifier) !== null && _a !== void 0 ? _a : nodeIdContext.generateNodeId(),
|
|
368
368
|
};
|
|
369
|
-
Common_1.copyPropertyIfDefined(nodeData, output, 'payload');
|
|
369
|
+
(0, Common_1.copyPropertyIfDefined)(nodeData, output, 'payload');
|
|
370
370
|
return output;
|
|
371
371
|
}
|
|
372
372
|
exports.internalizeBuildNode = internalizeBuildNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditUtilities.js","sourceRoot":"","sources":["../src/EditUtilities.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { v4 as uuidv4 } from 'uuid';\nimport { compareArrays, copyPropertyIfDefined, fail, Mutable } from './Common';\nimport { Definition, DetachedSequenceId, EditId, NodeId, StableNodeId, TraitLabel } from './Identifiers';\nimport { NodeIdContext, NodeIdConverter } from './NodeIdUtilities';\nimport {\n\tBuildNodeInternal,\n\tChangeInternal,\n\tChangeNode,\n\tChangeNode_0_0_2,\n\tEdit,\n\tHasTraits,\n\tNodeData,\n\tSide,\n\tStablePlaceInternal,\n\tStableRangeInternal,\n\tTraitLocationInternal,\n\tTraitMap,\n\tTreeNode,\n\tTreeNodeSequence,\n} from './persisted-types';\nimport { TraitLocation, TreeView } from './TreeView';\nimport { BuildNode, BuildTreeNode, Change, HasVariadicTraits, StablePlace, StableRange } from './ChangeTypes';\nimport { placeFromStablePlace, rangeFromStableRange } from './TreeViewUtilities';\nimport { iterateChildren, TransactionView } from './RevisionView';\nimport { getChangeNode_0_0_2FromView } from './SerializationUtilities';\nimport { comparePayloads } from './PayloadUtilities';\n\n/**\n * Functions for constructing and comparing Edits.\n */\n\n/**\n * Returns true if the provided Edits have equivalent properties.\n */\nexport function compareEdits(editIdA: EditId, editIdB: EditId): boolean {\n\t// TODO #45414: We should also be deep comparing the list of changes in the edit. This is not straightforward.\n\t// We can use our edit validation code when we write it since it will need to do deep walks of the changes.\n\treturn editIdA === editIdB;\n}\n\n/**\n * Generates a new edit object from the supplied changes.\n */\nexport function newEdit<TEdit>(changes: readonly TEdit[]): Edit<TEdit> {\n\treturn { id: newEditId(), changes };\n}\n\n/**\n * Generates a new edit object from the supplied changes.\n */\nexport function newEditId(): EditId {\n\treturn uuidv4() as EditId;\n}\n\n/**\n * A node type that does not require its children to be specified\n */\nexport type NoTraits<TChild extends HasVariadicTraits<unknown>> = Omit<TChild, keyof HasVariadicTraits<TChild>>;\n\n/**\n * Transform an input tree into an isomorphic output tree\n * @param tree - the input tree\n * @param convert - a conversion function that will run on each node in the input tree to produce the output tree.\n */\nexport function convertTreeNodes<TIn extends HasVariadicTraits<TIn>, TOut extends HasTraits<TOut>>(\n\troot: TIn,\n\tconvert: (node: TIn) => NoTraits<TOut>\n): TOut;\n\n/**\n * Transform an input tree into an isomorphic output tree\n * @param tree - the input tree\n * @param convert - a conversion function that will run on each (non-placeholder) node in the input tree to produce the output tree.\n * @param isPlaceholder - a predicate which determines if a node is a placeholder\n */\nexport function convertTreeNodes<\n\tTIn extends HasVariadicTraits<TIn | TPlaceholder>,\n\tTOut extends HasTraits<TOut | TPlaceholder>,\n\tTPlaceholder\n>(\n\troot: TIn | TPlaceholder,\n\tconvert: (node: TIn) => NoTraits<TOut>,\n\tisPlaceholder: (node: TIn | TPlaceholder) => node is TPlaceholder\n): TOut | TPlaceholder;\n\n/**\n * Transform an input tree into an isomorphic output tree\n * @param tree - the input tree\n * @param convert - a conversion function that will run on each (non-placeholder) node in the input tree to produce the output tree.\n * Returning undefined means that conversion for the given node was impossible, at which time the entire tree conversion will be aborted\n * and return undefined.\n * @param isPlaceholder - a predicate which determines if the given node is of type TPlaceholder\n */\nexport function convertTreeNodes<\n\tTIn extends HasVariadicTraits<TIn | TPlaceholder>,\n\tTOut extends HasTraits<TOut | TPlaceholder>,\n\tTPlaceholder\n>(\n\troot: TIn | TPlaceholder,\n\tconvert: (node: TIn) => NoTraits<TOut>,\n\tisPlaceholder?: (node: TIn | TPlaceholder) => node is TPlaceholder\n): TOut | TPlaceholder {\n\tif (isKnownType(root, isPlaceholder)) {\n\t\treturn root;\n\t}\n\n\tconst convertedRoot = convert(root) as TOut;\n\t// `convertedRoot` might be the same as `root`, in which case stash the children of `root` before wiping them from `convertedRoot`\n\tconst rootTraits = (root as unknown as TOut) === convertedRoot ? { traits: root.traits } : root;\n\t(convertedRoot as Mutable<TOut>).traits = {};\n\tconst pendingNodes: {\n\t\tchildIterator: Iterator<[TraitLabel, TIn | TPlaceholder]>;\n\t\tnewNode: Mutable<TOut>;\n\t}[] = [{ childIterator: iterateChildren(rootTraits)[Symbol.iterator](), newNode: convertedRoot }];\n\n\twhile (pendingNodes.length > 0) {\n\t\tconst { childIterator, newNode } = pendingNodes[pendingNodes.length - 1] ?? fail('Undefined node');\n\t\tconst { value, done } = childIterator.next();\n\t\tif (done === true) {\n\t\t\tpendingNodes.pop();\n\t\t} else {\n\t\t\tconst [traitLabel, child] = value as [TraitLabel, TIn | TPlaceholder];\n\t\t\tlet convertedChild: TOut | TPlaceholder;\n\t\t\tif (!isKnownType(child, isPlaceholder)) {\n\t\t\t\tconvertedChild = convert(child) as TOut;\n\t\t\t\tif (child.traits !== undefined) {\n\t\t\t\t\tconst childTraits =\n\t\t\t\t\t\t(child as unknown as TOut) === convertedChild ? { traits: child.traits } : child;\n\t\t\t\t\tpendingNodes.push({\n\t\t\t\t\t\tchildIterator: iterateChildren(childTraits)[Symbol.iterator](),\n\t\t\t\t\t\tnewNode: convertedChild,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t(convertedChild as Mutable<TOut>).traits = {};\n\t\t\t} else {\n\t\t\t\tconvertedChild = child;\n\t\t\t}\n\t\t\tconst newTraits = newNode.traits as Mutable<TraitMap<TOut | TPlaceholder>>;\n\t\t\tlet newTrait = newTraits[traitLabel];\n\t\t\tif (newTrait === undefined) {\n\t\t\t\tnewTrait = [];\n\t\t\t\tnewTraits[traitLabel] = newTrait;\n\t\t\t}\n\t\t\t(newTrait as (TOut | TPlaceholder)[]).push(convertedChild);\n\t\t}\n\t}\n\n\treturn convertedRoot;\n}\n\n/**\n * Visits an input tree in a depth-first pre-order traversal.\n * @param tree - the input tree\n * @param visitor - callback invoked for each node in the tree.\n */\nexport function walkTree<TIn extends HasVariadicTraits<TIn>>(tree: TIn, visitor: (node: TIn) => void): void;\n\n/**\n * Visits an input tree containing placeholders in a depth-first pre-order traversal.\n * @param tree - the input tree\n * @param visitor - callback invoked for each node in the tree. Must return true if the given node is a TPlaceholder.\n */\nexport function walkTree<TIn extends HasVariadicTraits<TIn | TPlaceholder>, TPlaceholder = never>(\n\ttree: TIn | TPlaceholder,\n\tvisitors:\n\t\t| ((node: TIn) => void)\n\t\t| { nodeVisitor?: (node: TIn) => void; placeholderVisitor?: (placeholder: TPlaceholder) => void },\n\tisPlaceholder: (node: TIn | TPlaceholder) => node is TPlaceholder\n): void;\n\nexport function walkTree<TIn extends HasVariadicTraits<TIn | TPlaceholder>, TPlaceholder = never>(\n\ttree: TIn | TPlaceholder,\n\tvisitors:\n\t\t| ((node: TIn) => void)\n\t\t| { nodeVisitor?: (node: TIn) => void; placeholderVisitor?: (placeholder: TPlaceholder) => void },\n\tisPlaceholder?: (node: TIn | TPlaceholder) => node is TPlaceholder\n): void {\n\tconst nodeVisitor = typeof visitors === 'function' ? visitors : visitors.nodeVisitor;\n\tconst placeholderVisitor = typeof visitors === 'object' ? visitors.placeholderVisitor : undefined;\n\tif (isKnownType(tree, isPlaceholder)) {\n\t\tplaceholderVisitor?.(tree);\n\t\treturn;\n\t}\n\tnodeVisitor?.(tree);\n\n\tconst childIterators: Iterator<[TraitLabel, TIn | TPlaceholder]>[] = [iterateChildren(tree)[Symbol.iterator]()];\n\n\twhile (childIterators.length > 0) {\n\t\tconst childIterator = childIterators[childIterators.length - 1] ?? fail('Undefined node');\n\t\tconst { value, done } = childIterator.next();\n\t\tif (done === true) {\n\t\t\tchildIterators.pop();\n\t\t} else {\n\t\t\tconst [_, child] = value as [TraitLabel, TIn | TPlaceholder];\n\t\t\tif (isKnownType(child, isPlaceholder)) {\n\t\t\t\tplaceholderVisitor?.(child);\n\t\t\t} else {\n\t\t\t\tnodeVisitor?.(child);\n\t\t\t\tchildIterators.push(iterateChildren(child)[Symbol.iterator]());\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Useful for collapsing type checks in `convertTreeNodes` into a single line\nfunction isKnownType<T, Type extends T>(value: T, isType?: (value: T) => value is Type): value is Type {\n\treturn isType?.(value) ?? false;\n}\n\n/**\n * Check if two trees are equivalent, meaning they have the same descendants with the same properties.\n *\n * See {@link comparePayloads} for payload comparison semantics.\n */\nexport function deepCompareNodes(\n\ta: ChangeNode | ChangeNode_0_0_2,\n\tb: ChangeNode | ChangeNode_0_0_2,\n\tcomparator: (\n\t\ta: NodeData<NodeId> | NodeData<StableNodeId>,\n\t\tb: NodeData<NodeId> | NodeData<StableNodeId>\n\t) => boolean = compareNodes\n): boolean {\n\tif (a === b) {\n\t\treturn true;\n\t}\n\n\tif (!comparator(a, b)) {\n\t\treturn false;\n\t}\n\n\tconst traitsA = Object.entries(a.traits);\n\tconst traitsB = Object.entries(b.traits);\n\n\tif (traitsA.length !== traitsB.length) {\n\t\treturn false;\n\t}\n\n\tfor (const [traitLabel, childrenA] of traitsA) {\n\t\tconst childrenB = b.traits[traitLabel];\n\n\t\tif (childrenA.length !== childrenB.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst traitsEqual = compareArrays<ChangeNode | ChangeNode_0_0_2>(childrenA, childrenB, (childA, childB) => {\n\t\t\tif (typeof childA === 'number' || typeof childB === 'number') {\n\t\t\t\t// Check if children are DetachedSequenceIds\n\t\t\t\treturn childA === childB;\n\t\t\t}\n\n\t\t\treturn deepCompareNodes(childA, childB);\n\t\t});\n\n\t\tif (!traitsEqual) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/*\n * Returns true if two nodes have equivalent data and payloads, otherwise false.\n * Does not compare children\n * @param nodes - two or more nodes to compare\n */\nexport function compareNodes(\n\ta: NodeData<NodeId> | NodeData<StableNodeId>,\n\tb: NodeData<NodeId> | NodeData<StableNodeId>\n): boolean {\n\tif (a === b) {\n\t\treturn true;\n\t}\n\n\tif (a.identifier !== b.identifier) {\n\t\treturn false;\n\t}\n\n\tif (a.definition !== b.definition) {\n\t\treturn false;\n\t}\n\n\tif (!comparePayloads(a.payload, b.payload)) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Compare two views such that semantically equivalent node IDs are considered equal.\n */\nexport function areRevisionViewsSemanticallyEqual(\n\ttreeViewA: TreeView,\n\tidConverterA: NodeIdConverter,\n\ttreeViewB: TreeView,\n\tidConverterB: NodeIdConverter\n): boolean {\n\tconst treeA = getChangeNode_0_0_2FromView(treeViewA, idConverterA);\n\tconst treeB = getChangeNode_0_0_2FromView(treeViewB, idConverterB);\n\tif (!deepCompareNodes(treeA, treeB)) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Create a sequence of changes that resets the contents of `trait`.\n * @public\n */\nexport function setTrait(trait: TraitLocation, nodes: BuildNode | TreeNodeSequence<BuildNode>): Change[] {\n\tconst id = 0 as DetachedSequenceId;\n\tconst traitContents = StableRange.all(trait);\n\treturn [Change.detach(traitContents), Change.build(nodes, id), Change.insert(id, traitContents.start)];\n}\n\n/**\n * Create a sequence of changes that resets the contents of `trait`.\n * @internal\n */\nexport function setTraitInternal(\n\ttrait: TraitLocationInternal,\n\tnodes: TreeNodeSequence<BuildNodeInternal>\n): ChangeInternal[] {\n\tconst id = 0 as DetachedSequenceId;\n\tconst traitContents = StableRangeInternal.all(trait);\n\treturn [\n\t\tChangeInternal.detach(traitContents),\n\t\tChangeInternal.build(nodes, id),\n\t\tChangeInternal.insert(id, traitContents.start),\n\t];\n}\n\n/**\n * Check the validity of the given `StablePlace`\n * @param view - the `TreeView` within which to validate the given place\n * @param place - the `StablePlace` to check\n */\nexport function validateStablePlace(\n\tview: TreeView,\n\tplace: StablePlaceInternal\n):\n\t| {\n\t\t\tresult: PlaceValidationResult.Valid;\n\t\t\tside: Side;\n\t\t\treferenceSibling: NodeId;\n\t\t\treferenceTrait?: never;\n\t }\n\t| {\n\t\t\tresult: PlaceValidationResult.Valid;\n\t\t\tside: Side;\n\t\t\treferenceSibling?: never;\n\t\t\treferenceTrait: TraitLocation;\n\t }\n\t| { result: Exclude<PlaceValidationResult, PlaceValidationResult.Valid> } {\n\t/* A StablePlace is valid if the following conditions are met:\n\t * 1. A sibling or trait is defined.\n\t * 2. If a sibling is defined, both it and its parent exist in the `TreeView`.\n\t * 3. If a trait is defined, its parent node exists in the `TreeView`.\n\t * 4. If a sibling and a trait location are both specified, the sibling needs to actually be in that trait.\n\t */\n\tconst { referenceSibling, referenceTrait } = place;\n\n\t// A well-formed `StablePlace` specifies exactly one of `referenceSibling` and `referenceTrait`.\n\tif (\n\t\t(referenceSibling === undefined && referenceTrait === undefined) ||\n\t\t(referenceSibling !== undefined && referenceTrait !== undefined)\n\t) {\n\t\treturn { result: PlaceValidationResult.Malformed };\n\t}\n\n\tif (referenceSibling !== undefined) {\n\t\tif (!view.hasNode(referenceSibling)) {\n\t\t\treturn { result: PlaceValidationResult.MissingSibling };\n\t\t}\n\n\t\t// Detached nodes and the root are invalid anchors.\n\t\tif (view.tryGetTraitLabel(referenceSibling) === undefined) {\n\t\t\treturn { result: PlaceValidationResult.SiblingIsRootOrDetached };\n\t\t}\n\n\t\treturn { result: PlaceValidationResult.Valid, side: place.side, referenceSibling };\n\t}\n\n\tif (referenceTrait === undefined) {\n\t\treturn { result: PlaceValidationResult.MissingParent };\n\t}\n\n\tif (!view.hasNode(referenceTrait.parent)) {\n\t\treturn { result: PlaceValidationResult.MissingParent };\n\t}\n\n\treturn { result: PlaceValidationResult.Valid, side: place.side, referenceTrait };\n}\n\n/**\n * The result of validating a place.\n */\nexport enum PlaceValidationResult {\n\tValid = 'Valid',\n\tMalformed = 'Malformed',\n\tSiblingIsRootOrDetached = 'SiblingIsRootOrDetached',\n\tMissingSibling = 'MissingSibling',\n\tMissingParent = 'MissingParent',\n}\n\n/**\n * The result of validating a bad place.\n */\nexport type BadPlaceValidationResult = Exclude<PlaceValidationResult, PlaceValidationResult.Valid>;\n\n/**\n * Check the validity of the given `StableRange`\n * @param view - the `TreeView` within which to validate the given range\n * @param range - the `StableRange` to check\n */\nexport function validateStableRange(\n\tview: TreeView,\n\trange: StableRangeInternal\n):\n\t| { result: RangeValidationResultKind.Valid; start: StablePlaceInternal; end: StablePlaceInternal }\n\t| { result: Exclude<RangeValidationResult, RangeValidationResultKind.Valid> } {\n\t/* A StableRange is valid if the following conditions are met:\n\t * 1. Its start and end places are valid.\n\t * 2. Its start and end places are within the same trait.\n\t * 3. Its start place is before its end place.\n\t */\n\tconst { start, end } = range;\n\n\tconst validatedStart = validateStablePlace(view, start);\n\tif (validatedStart.result !== PlaceValidationResult.Valid) {\n\t\treturn {\n\t\t\tresult: { kind: RangeValidationResultKind.BadPlace, place: start, placeFailure: validatedStart.result },\n\t\t};\n\t}\n\n\tconst validatedEnd = validateStablePlace(view, end);\n\tif (validatedEnd.result !== PlaceValidationResult.Valid) {\n\t\treturn { result: { kind: RangeValidationResultKind.BadPlace, place: end, placeFailure: validatedEnd.result } };\n\t}\n\n\tconst startTraitLocation = validatedStart.referenceTrait || view.getTraitLocation(validatedStart.referenceSibling);\n\tconst endTraitLocation = validatedEnd.referenceTrait || view.getTraitLocation(validatedEnd.referenceSibling);\n\tif (!compareTraits(startTraitLocation, endTraitLocation)) {\n\t\treturn { result: RangeValidationResultKind.PlacesInDifferentTraits };\n\t}\n\n\tconst { start: startPlace, end: endPlace } = rangeFromStableRange(view, {\n\t\tstart: validatedStart,\n\t\tend: validatedEnd,\n\t});\n\tconst startIndex = view.findIndexWithinTrait(startPlace);\n\tconst endIndex = view.findIndexWithinTrait(endPlace);\n\n\tif (startIndex > endIndex) {\n\t\treturn { result: RangeValidationResultKind.Inverted };\n\t}\n\n\treturn { result: RangeValidationResultKind.Valid, start: validatedStart, end: validatedEnd };\n}\n\n/**\n * The kinds of result of validating a range.\n */\nexport enum RangeValidationResultKind {\n\tValid = 'Valid',\n\tBadPlace = 'BadPlace',\n\tPlacesInDifferentTraits = 'PlacesInDifferentTraits',\n\tInverted = 'Inverted',\n}\n\n/**\n * The result of validating a range.\n */\nexport type RangeValidationResult =\n\t| RangeValidationResultKind.Valid\n\t| RangeValidationResultKind.PlacesInDifferentTraits\n\t| RangeValidationResultKind.Inverted\n\t| {\n\t\t\tkind: RangeValidationResultKind.BadPlace;\n\t\t\tplace: StablePlaceInternal;\n\t\t\tplaceFailure: BadPlaceValidationResult;\n\t };\n\n/**\n * The result of validating a bad range.\n */\nexport type BadRangeValidationResult = Exclude<RangeValidationResult, RangeValidationResultKind.Valid>;\n\n/**\n * Check if two TraitLocations are equal.\n */\nfunction compareTraits(traitA: TraitLocation, traitB: TraitLocation): boolean {\n\tif (traitA.label !== traitB.label || traitA.parent !== traitB.parent) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Parents a set of nodes in a specified location within a trait.\n * @param nodesToInsert - the nodes to parent in the specified place. The nodes must already be present in the TreeView.\n * @param placeToInsert - the location to insert the nodes.\n */\nexport function insertIntoTrait(\n\tview: TransactionView,\n\tnodesToInsert: readonly NodeId[],\n\tplaceToInsert: StablePlace\n): TransactionView {\n\treturn view.attachRange(nodesToInsert, placeFromStablePlace(view, placeToInsert));\n}\n\n/**\n * Detaches a range of nodes from their parent. The detached nodes remain in the TreeView.\n * @param rangeToDetach - the range of nodes to detach\n */\nexport function detachRange(\n\tview: TransactionView,\n\trangeToDetach: StableRange\n): { view: TransactionView; detached: readonly NodeId[] } {\n\treturn view.detachRange(rangeFromStableRange(view, rangeToDetach));\n}\n\n/**\n * Deeply clone the given StablePlace\n */\nexport function deepCloneStablePlace(place: StablePlace): StablePlace {\n\tconst clone: StablePlace = { side: place.side };\n\tcopyPropertyIfDefined(place, clone, 'referenceSibling');\n\tcopyPropertyIfDefined(place, clone, 'referenceTrait');\n\treturn clone;\n}\n\n/**\n * Deeply clone the given StableRange\n */\nexport function deepCloneStableRange(range: StableRange): StableRange {\n\treturn { start: deepCloneStablePlace(range.start), end: deepCloneStablePlace(range.end) };\n}\n\n/** Convert a node used in a Build change into its internal representation */\nexport function internalizeBuildNode(\n\tnodeData: BuildTreeNode,\n\tnodeIdContext: NodeIdContext\n): Omit<TreeNode<BuildNodeInternal, NodeId>, 'traits'> {\n\tconst output = {\n\t\tdefinition: nodeData.definition as Definition,\n\t\tidentifier: nodeData.identifier ?? nodeIdContext.generateNodeId(),\n\t};\n\tcopyPropertyIfDefined(nodeData, output, 'payload');\n\treturn output;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"EditUtilities.js","sourceRoot":"","sources":["../src/EditUtilities.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { v4 as uuidv4 } from 'uuid';\nimport { compareArrays, copyPropertyIfDefined, fail, Mutable } from './Common';\nimport { Definition, DetachedSequenceId, EditId, NodeId, StableNodeId, TraitLabel } from './Identifiers';\nimport { NodeIdContext, NodeIdConverter } from './NodeIdUtilities';\nimport {\n\tBuildNodeInternal,\n\tChangeInternal,\n\tChangeNode,\n\tChangeNode_0_0_2,\n\tEdit,\n\tHasTraits,\n\tNodeData,\n\tSide,\n\tStablePlaceInternal,\n\tStableRangeInternal,\n\tTraitLocationInternal,\n\tTraitMap,\n\tTreeNode,\n\tTreeNodeSequence,\n} from './persisted-types';\nimport { TraitLocation, TreeView } from './TreeView';\nimport { BuildNode, BuildTreeNode, Change, HasVariadicTraits, StablePlace, StableRange } from './ChangeTypes';\nimport { placeFromStablePlace, rangeFromStableRange } from './TreeViewUtilities';\nimport { iterateChildren, TransactionView } from './RevisionView';\nimport { getChangeNode_0_0_2FromView } from './SerializationUtilities';\nimport { comparePayloads } from './PayloadUtilities';\n\n/**\n * Functions for constructing and comparing Edits.\n */\n\n/**\n * Returns true if the provided Edits have equivalent properties.\n */\nexport function compareEdits(editIdA: EditId, editIdB: EditId): boolean {\n\t// TODO #45414: We should also be deep comparing the list of changes in the edit. This is not straightforward.\n\t// We can use our edit validation code when we write it since it will need to do deep walks of the changes.\n\treturn editIdA === editIdB;\n}\n\n/**\n * Generates a new edit object from the supplied changes.\n */\nexport function newEdit<TEdit>(changes: readonly TEdit[]): Edit<TEdit> {\n\treturn { id: newEditId(), changes };\n}\n\n/**\n * Generates a new edit object from the supplied changes.\n */\nexport function newEditId(): EditId {\n\treturn uuidv4() as EditId;\n}\n\n/**\n * A node type that does not require its children to be specified\n */\nexport type NoTraits<TChild extends HasVariadicTraits<unknown>> = Omit<TChild, keyof HasVariadicTraits<TChild>>;\n\n/**\n * Transform an input tree into an isomorphic output tree\n * @param tree - the input tree\n * @param convert - a conversion function that will run on each node in the input tree to produce the output tree.\n */\nexport function convertTreeNodes<TIn extends HasVariadicTraits<TIn>, TOut extends HasTraits<TOut>>(\n\troot: TIn,\n\tconvert: (node: TIn) => NoTraits<TOut>\n): TOut;\n\n/**\n * Transform an input tree into an isomorphic output tree\n * @param tree - the input tree\n * @param convert - a conversion function that will run on each (non-placeholder) node in the input tree to produce the output tree.\n * @param isPlaceholder - a predicate which determines if a node is a placeholder\n */\nexport function convertTreeNodes<\n\tTIn extends HasVariadicTraits<TIn | TPlaceholder>,\n\tTOut extends HasTraits<TOut | TPlaceholder>,\n\tTPlaceholder\n>(\n\troot: TIn | TPlaceholder,\n\tconvert: (node: TIn) => NoTraits<TOut>,\n\tisPlaceholder: (node: TIn | TPlaceholder) => node is TPlaceholder\n): TOut | TPlaceholder;\n\n/**\n * Transform an input tree into an isomorphic output tree\n * @param tree - the input tree\n * @param convert - a conversion function that will run on each (non-placeholder) node in the input tree to produce the output tree.\n * Returning undefined means that conversion for the given node was impossible, at which time the entire tree conversion will be aborted\n * and return undefined.\n * @param isPlaceholder - a predicate which determines if the given node is of type TPlaceholder\n */\nexport function convertTreeNodes<\n\tTIn extends HasVariadicTraits<TIn | TPlaceholder>,\n\tTOut extends HasTraits<TOut | TPlaceholder>,\n\tTPlaceholder\n>(\n\troot: TIn | TPlaceholder,\n\tconvert: (node: TIn) => NoTraits<TOut>,\n\tisPlaceholder?: (node: TIn | TPlaceholder) => node is TPlaceholder\n): TOut | TPlaceholder {\n\tif (isKnownType(root, isPlaceholder)) {\n\t\treturn root;\n\t}\n\n\tconst convertedRoot = convert(root) as TOut;\n\t// `convertedRoot` might be the same as `root`, in which case stash the children of `root` before wiping them from `convertedRoot`\n\tconst rootTraits = (root as unknown as TOut) === convertedRoot ? { traits: root.traits } : root;\n\t(convertedRoot as Mutable<TOut>).traits = {};\n\tconst pendingNodes: {\n\t\tchildIterator: Iterator<[TraitLabel, TIn | TPlaceholder]>;\n\t\tnewNode: Mutable<TOut>;\n\t}[] = [{ childIterator: iterateChildren(rootTraits)[Symbol.iterator](), newNode: convertedRoot }];\n\n\twhile (pendingNodes.length > 0) {\n\t\tconst { childIterator, newNode } = pendingNodes[pendingNodes.length - 1] ?? fail('Undefined node');\n\t\tconst { value, done } = childIterator.next();\n\t\tif (done === true) {\n\t\t\tpendingNodes.pop();\n\t\t} else {\n\t\t\tconst [traitLabel, child] = value as [TraitLabel, TIn | TPlaceholder];\n\t\t\tlet convertedChild: TOut | TPlaceholder;\n\t\t\tif (!isKnownType(child, isPlaceholder)) {\n\t\t\t\tconvertedChild = convert(child) as TOut;\n\t\t\t\tif (child.traits !== undefined) {\n\t\t\t\t\tconst childTraits =\n\t\t\t\t\t\t(child as unknown as TOut) === convertedChild ? { traits: child.traits } : child;\n\t\t\t\t\tpendingNodes.push({\n\t\t\t\t\t\tchildIterator: iterateChildren(childTraits)[Symbol.iterator](),\n\t\t\t\t\t\tnewNode: convertedChild,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t(convertedChild as Mutable<TOut>).traits = {};\n\t\t\t} else {\n\t\t\t\tconvertedChild = child;\n\t\t\t}\n\t\t\tconst newTraits = newNode.traits as Mutable<TraitMap<TOut | TPlaceholder>>;\n\t\t\tlet newTrait = newTraits[traitLabel];\n\t\t\tif (newTrait === undefined) {\n\t\t\t\tnewTrait = [];\n\t\t\t\tnewTraits[traitLabel] = newTrait;\n\t\t\t}\n\t\t\t(newTrait as (TOut | TPlaceholder)[]).push(convertedChild);\n\t\t}\n\t}\n\n\treturn convertedRoot;\n}\n\n/**\n * Visits an input tree in a depth-first pre-order traversal.\n * @param tree - the input tree\n * @param visitor - callback invoked for each node in the tree.\n */\nexport function walkTree<TIn extends HasVariadicTraits<TIn>>(tree: TIn, visitor: (node: TIn) => void): void;\n\n/**\n * Visits an input tree containing placeholders in a depth-first pre-order traversal.\n * @param tree - the input tree\n * @param visitor - callback invoked for each node in the tree. Must return true if the given node is a TPlaceholder.\n */\nexport function walkTree<TIn extends HasVariadicTraits<TIn | TPlaceholder>, TPlaceholder = never>(\n\ttree: TIn | TPlaceholder,\n\tvisitors:\n\t\t| ((node: TIn) => void)\n\t\t| { nodeVisitor?: (node: TIn) => void; placeholderVisitor?: (placeholder: TPlaceholder) => void },\n\tisPlaceholder: (node: TIn | TPlaceholder) => node is TPlaceholder\n): void;\n\nexport function walkTree<TIn extends HasVariadicTraits<TIn | TPlaceholder>, TPlaceholder = never>(\n\ttree: TIn | TPlaceholder,\n\tvisitors:\n\t\t| ((node: TIn) => void)\n\t\t| { nodeVisitor?: (node: TIn) => void; placeholderVisitor?: (placeholder: TPlaceholder) => void },\n\tisPlaceholder?: (node: TIn | TPlaceholder) => node is TPlaceholder\n): void {\n\tconst nodeVisitor = typeof visitors === 'function' ? visitors : visitors.nodeVisitor;\n\tconst placeholderVisitor = typeof visitors === 'object' ? visitors.placeholderVisitor : undefined;\n\tif (isKnownType(tree, isPlaceholder)) {\n\t\tplaceholderVisitor?.(tree);\n\t\treturn;\n\t}\n\tnodeVisitor?.(tree);\n\n\tconst childIterators: Iterator<[TraitLabel, TIn | TPlaceholder]>[] = [iterateChildren(tree)[Symbol.iterator]()];\n\n\twhile (childIterators.length > 0) {\n\t\tconst childIterator = childIterators[childIterators.length - 1] ?? fail('Undefined node');\n\t\tconst { value, done } = childIterator.next();\n\t\tif (done === true) {\n\t\t\tchildIterators.pop();\n\t\t} else {\n\t\t\tconst [_, child] = value as [TraitLabel, TIn | TPlaceholder];\n\t\t\tif (isKnownType(child, isPlaceholder)) {\n\t\t\t\tplaceholderVisitor?.(child);\n\t\t\t} else {\n\t\t\t\tnodeVisitor?.(child);\n\t\t\t\tchildIterators.push(iterateChildren(child)[Symbol.iterator]());\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Useful for collapsing type checks in `convertTreeNodes` into a single line\nfunction isKnownType<T, Type extends T>(value: T, isType?: (value: T) => value is Type): value is Type {\n\treturn isType?.(value) ?? false;\n}\n\n/**\n * Check if two trees are equivalent, meaning they have the same descendants with the same properties.\n *\n * See {@link comparePayloads} for payload comparison semantics.\n */\nexport function deepCompareNodes(\n\ta: ChangeNode | ChangeNode_0_0_2,\n\tb: ChangeNode | ChangeNode_0_0_2,\n\tcomparator: (\n\t\ta: NodeData<NodeId> | NodeData<StableNodeId>,\n\t\tb: NodeData<NodeId> | NodeData<StableNodeId>\n\t) => boolean = compareNodes\n): boolean {\n\tif (a === b) {\n\t\treturn true;\n\t}\n\n\tif (!comparator(a, b)) {\n\t\treturn false;\n\t}\n\n\tconst traitsA = Object.entries(a.traits);\n\tconst traitsB = Object.entries(b.traits);\n\n\tif (traitsA.length !== traitsB.length) {\n\t\treturn false;\n\t}\n\n\tfor (const [traitLabel, childrenA] of traitsA) {\n\t\tconst childrenB = b.traits[traitLabel];\n\n\t\tif (childrenA.length !== childrenB.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst traitsEqual = compareArrays<ChangeNode | ChangeNode_0_0_2>(childrenA, childrenB, (childA, childB) => {\n\t\t\tif (typeof childA === 'number' || typeof childB === 'number') {\n\t\t\t\t// Check if children are DetachedSequenceIds\n\t\t\t\treturn childA === childB;\n\t\t\t}\n\n\t\t\treturn deepCompareNodes(childA, childB);\n\t\t});\n\n\t\tif (!traitsEqual) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/*\n * Returns true if two nodes have equivalent data and payloads, otherwise false.\n * Does not compare children\n * @param nodes - two or more nodes to compare\n */\nexport function compareNodes(\n\ta: NodeData<NodeId> | NodeData<StableNodeId>,\n\tb: NodeData<NodeId> | NodeData<StableNodeId>\n): boolean {\n\tif (a === b) {\n\t\treturn true;\n\t}\n\n\tif (a.identifier !== b.identifier) {\n\t\treturn false;\n\t}\n\n\tif (a.definition !== b.definition) {\n\t\treturn false;\n\t}\n\n\tif (!comparePayloads(a.payload, b.payload)) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Compare two views such that semantically equivalent node IDs are considered equal.\n */\nexport function areRevisionViewsSemanticallyEqual(\n\ttreeViewA: TreeView,\n\tidConverterA: NodeIdConverter,\n\ttreeViewB: TreeView,\n\tidConverterB: NodeIdConverter\n): boolean {\n\tconst treeA = getChangeNode_0_0_2FromView(treeViewA, idConverterA);\n\tconst treeB = getChangeNode_0_0_2FromView(treeViewB, idConverterB);\n\tif (!deepCompareNodes(treeA, treeB)) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Create a sequence of changes that resets the contents of `trait`.\n * @public\n */\nexport function setTrait(trait: TraitLocation, nodes: BuildNode | TreeNodeSequence<BuildNode>): Change[] {\n\tconst id = 0 as DetachedSequenceId;\n\tconst traitContents = StableRange.all(trait);\n\treturn [Change.detach(traitContents), Change.build(nodes, id), Change.insert(id, traitContents.start)];\n}\n\n/**\n * Create a sequence of changes that resets the contents of `trait`.\n * @internal\n */\nexport function setTraitInternal(\n\ttrait: TraitLocationInternal,\n\tnodes: TreeNodeSequence<BuildNodeInternal>\n): ChangeInternal[] {\n\tconst id = 0 as DetachedSequenceId;\n\tconst traitContents = StableRangeInternal.all(trait);\n\treturn [\n\t\tChangeInternal.detach(traitContents),\n\t\tChangeInternal.build(nodes, id),\n\t\tChangeInternal.insert(id, traitContents.start),\n\t];\n}\n\n/**\n * Check the validity of the given `StablePlace`\n * @param view - the `TreeView` within which to validate the given place\n * @param place - the `StablePlace` to check\n */\nexport function validateStablePlace(\n\tview: TreeView,\n\tplace: StablePlaceInternal\n):\n\t| {\n\t\t\tresult: PlaceValidationResult.Valid;\n\t\t\tside: Side;\n\t\t\treferenceSibling: NodeId;\n\t\t\treferenceTrait?: never;\n\t }\n\t| {\n\t\t\tresult: PlaceValidationResult.Valid;\n\t\t\tside: Side;\n\t\t\treferenceSibling?: never;\n\t\t\treferenceTrait: TraitLocation;\n\t }\n\t| { result: Exclude<PlaceValidationResult, PlaceValidationResult.Valid> } {\n\t/* A StablePlace is valid if the following conditions are met:\n\t * 1. A sibling or trait is defined.\n\t * 2. If a sibling is defined, both it and its parent exist in the `TreeView`.\n\t * 3. If a trait is defined, its parent node exists in the `TreeView`.\n\t * 4. If a sibling and a trait location are both specified, the sibling needs to actually be in that trait.\n\t */\n\tconst { referenceSibling, referenceTrait } = place;\n\n\t// A well-formed `StablePlace` specifies exactly one of `referenceSibling` and `referenceTrait`.\n\tif (\n\t\t(referenceSibling === undefined && referenceTrait === undefined) ||\n\t\t(referenceSibling !== undefined && referenceTrait !== undefined)\n\t) {\n\t\treturn { result: PlaceValidationResult.Malformed };\n\t}\n\n\tif (referenceSibling !== undefined) {\n\t\tif (!view.hasNode(referenceSibling)) {\n\t\t\treturn { result: PlaceValidationResult.MissingSibling };\n\t\t}\n\n\t\t// Detached nodes and the root are invalid anchors.\n\t\tif (view.tryGetTraitLabel(referenceSibling) === undefined) {\n\t\t\treturn { result: PlaceValidationResult.SiblingIsRootOrDetached };\n\t\t}\n\n\t\treturn { result: PlaceValidationResult.Valid, side: place.side, referenceSibling };\n\t}\n\n\tif (referenceTrait === undefined) {\n\t\treturn { result: PlaceValidationResult.MissingParent };\n\t}\n\n\tif (!view.hasNode(referenceTrait.parent)) {\n\t\treturn { result: PlaceValidationResult.MissingParent };\n\t}\n\n\treturn { result: PlaceValidationResult.Valid, side: place.side, referenceTrait };\n}\n\n/**\n * The result of validating a place.\n */\nexport enum PlaceValidationResult {\n\tValid = 'Valid',\n\tMalformed = 'Malformed',\n\tSiblingIsRootOrDetached = 'SiblingIsRootOrDetached',\n\tMissingSibling = 'MissingSibling',\n\tMissingParent = 'MissingParent',\n}\n\n/**\n * The result of validating a bad place.\n */\nexport type BadPlaceValidationResult = Exclude<PlaceValidationResult, PlaceValidationResult.Valid>;\n\n/**\n * Check the validity of the given `StableRange`\n * @param view - the `TreeView` within which to validate the given range\n * @param range - the `StableRange` to check\n */\nexport function validateStableRange(\n\tview: TreeView,\n\trange: StableRangeInternal\n):\n\t| { result: RangeValidationResultKind.Valid; start: StablePlaceInternal; end: StablePlaceInternal }\n\t| { result: Exclude<RangeValidationResult, RangeValidationResultKind.Valid> } {\n\t/* A StableRange is valid if the following conditions are met:\n\t * 1. Its start and end places are valid.\n\t * 2. Its start and end places are within the same trait.\n\t * 3. Its start place is before its end place.\n\t */\n\tconst { start, end } = range;\n\n\tconst validatedStart = validateStablePlace(view, start);\n\tif (validatedStart.result !== PlaceValidationResult.Valid) {\n\t\treturn {\n\t\t\tresult: { kind: RangeValidationResultKind.BadPlace, place: start, placeFailure: validatedStart.result },\n\t\t};\n\t}\n\n\tconst validatedEnd = validateStablePlace(view, end);\n\tif (validatedEnd.result !== PlaceValidationResult.Valid) {\n\t\treturn { result: { kind: RangeValidationResultKind.BadPlace, place: end, placeFailure: validatedEnd.result } };\n\t}\n\n\tconst startTraitLocation = validatedStart.referenceTrait || view.getTraitLocation(validatedStart.referenceSibling);\n\tconst endTraitLocation = validatedEnd.referenceTrait || view.getTraitLocation(validatedEnd.referenceSibling);\n\tif (!compareTraits(startTraitLocation, endTraitLocation)) {\n\t\treturn { result: RangeValidationResultKind.PlacesInDifferentTraits };\n\t}\n\n\tconst { start: startPlace, end: endPlace } = rangeFromStableRange(view, {\n\t\tstart: validatedStart,\n\t\tend: validatedEnd,\n\t});\n\tconst startIndex = view.findIndexWithinTrait(startPlace);\n\tconst endIndex = view.findIndexWithinTrait(endPlace);\n\n\tif (startIndex > endIndex) {\n\t\treturn { result: RangeValidationResultKind.Inverted };\n\t}\n\n\treturn { result: RangeValidationResultKind.Valid, start: validatedStart, end: validatedEnd };\n}\n\n/**\n * The kinds of result of validating a range.\n */\nexport enum RangeValidationResultKind {\n\tValid = 'Valid',\n\tBadPlace = 'BadPlace',\n\tPlacesInDifferentTraits = 'PlacesInDifferentTraits',\n\tInverted = 'Inverted',\n}\n\n/**\n * The result of validating a range.\n */\nexport type RangeValidationResult =\n\t| RangeValidationResultKind.Valid\n\t| RangeValidationResultKind.PlacesInDifferentTraits\n\t| RangeValidationResultKind.Inverted\n\t| {\n\t\t\tkind: RangeValidationResultKind.BadPlace;\n\t\t\tplace: StablePlaceInternal;\n\t\t\tplaceFailure: BadPlaceValidationResult;\n\t };\n\n/**\n * The result of validating a bad range.\n */\nexport type BadRangeValidationResult = Exclude<RangeValidationResult, RangeValidationResultKind.Valid>;\n\n/**\n * Check if two TraitLocations are equal.\n */\nfunction compareTraits(traitA: TraitLocation, traitB: TraitLocation): boolean {\n\tif (traitA.label !== traitB.label || traitA.parent !== traitB.parent) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Parents a set of nodes in a specified location within a trait.\n * @param nodesToInsert - the nodes to parent in the specified place. The nodes must already be present in the TreeView.\n * @param placeToInsert - the location to insert the nodes.\n */\nexport function insertIntoTrait(\n\tview: TransactionView,\n\tnodesToInsert: readonly NodeId[],\n\tplaceToInsert: StablePlace\n): TransactionView {\n\treturn view.attachRange(nodesToInsert, placeFromStablePlace(view, placeToInsert));\n}\n\n/**\n * Detaches a range of nodes from their parent. The detached nodes remain in the TreeView.\n * @param rangeToDetach - the range of nodes to detach\n */\nexport function detachRange(\n\tview: TransactionView,\n\trangeToDetach: StableRange\n): { view: TransactionView; detached: readonly NodeId[] } {\n\treturn view.detachRange(rangeFromStableRange(view, rangeToDetach));\n}\n\n/**\n * Deeply clone the given StablePlace\n */\nexport function deepCloneStablePlace(place: StablePlace): StablePlace {\n\tconst clone: StablePlace = { side: place.side };\n\tcopyPropertyIfDefined(place, clone, 'referenceSibling');\n\tcopyPropertyIfDefined(place, clone, 'referenceTrait');\n\treturn clone;\n}\n\n/**\n * Deeply clone the given StableRange\n */\nexport function deepCloneStableRange(range: StableRange): StableRange {\n\treturn { start: deepCloneStablePlace(range.start), end: deepCloneStablePlace(range.end) };\n}\n\n/** Convert a node used in a Build change into its internal representation */\nexport function internalizeBuildNode(\n\tnodeData: BuildTreeNode,\n\tnodeIdContext: NodeIdContext\n): Omit<TreeNode<BuildNodeInternal, NodeId>, 'traits'> {\n\tconst output = {\n\t\tdefinition: nodeData.definition as Definition,\n\t\tidentifier: nodeData.identifier ?? nodeIdContext.generateNodeId(),\n\t};\n\tcopyPropertyIfDefined(nodeData, output, 'payload');\n\treturn output;\n}\n"]}
|
package/dist/Forest.js
CHANGED
|
@@ -20,7 +20,7 @@ function isParentedForestNode(node) {
|
|
|
20
20
|
const parentedNode = node;
|
|
21
21
|
const hasParent = parentedNode.parentId !== undefined;
|
|
22
22
|
const hasTraitParent = parentedNode.traitParent !== undefined;
|
|
23
|
-
Common_1.assert(hasParent === hasTraitParent, 'node must have either both parent and traitParent set or neither');
|
|
23
|
+
(0, Common_1.assert)(hasParent === hasTraitParent, 'node must have either both parent and traitParent set or neither');
|
|
24
24
|
return hasParent;
|
|
25
25
|
}
|
|
26
26
|
exports.isParentedForestNode = isParentedForestNode;
|
|
@@ -72,12 +72,12 @@ class Forest {
|
|
|
72
72
|
for (const node of newNodes) {
|
|
73
73
|
const { identifier } = node;
|
|
74
74
|
for (const [traitLabel, trait] of node.traits) {
|
|
75
|
-
Common_1.assert(trait.length > 0, 'any trait arrays present in a node must be non-empty');
|
|
75
|
+
(0, Common_1.assert)(trait.length > 0, 'any trait arrays present in a node must be non-empty');
|
|
76
76
|
for (const childId of trait) {
|
|
77
77
|
const child = mutableNodes.get(childId);
|
|
78
78
|
if (child !== undefined) {
|
|
79
79
|
// A child already exists in the forest, and its parent is now being added
|
|
80
|
-
Common_1.assert(!isParentedForestNode(child), 'can not give a child multiple parents');
|
|
80
|
+
(0, Common_1.assert)(!isParentedForestNode(child), 'can not give a child multiple parents');
|
|
81
81
|
const parentedChild = {
|
|
82
82
|
definition: child.definition,
|
|
83
83
|
identifier: child.identifier,
|
|
@@ -85,7 +85,7 @@ class Forest {
|
|
|
85
85
|
parentId: identifier,
|
|
86
86
|
traitParent: traitLabel,
|
|
87
87
|
};
|
|
88
|
-
Common_1.copyPropertyIfDefined(child, parentedChild, 'payload');
|
|
88
|
+
(0, Common_1.copyPropertyIfDefined)(child, parentedChild, 'payload');
|
|
89
89
|
// Overwrite the existing child with its parented version
|
|
90
90
|
mutableNodes.set(childId, parentedChild);
|
|
91
91
|
}
|
|
@@ -99,11 +99,11 @@ class Forest {
|
|
|
99
99
|
// Now add each node to the forest and apply any parentage information that was recorded above
|
|
100
100
|
for (const node of newNodes) {
|
|
101
101
|
const parentData = childToParent.get(node.identifier);
|
|
102
|
-
Common_1.assert(!mutableNodes.has(node.identifier), 'can not add node with already existing id');
|
|
102
|
+
(0, Common_1.assert)(!mutableNodes.has(node.identifier), 'can not add node with already existing id');
|
|
103
103
|
if (parentData !== undefined) {
|
|
104
104
|
// This is a child whom we haven't added yet, but whose parent we already added above. Supply the recorded parentage info.
|
|
105
105
|
const child = Object.assign({ definition: node.definition, identifier: node.identifier, traits: node.traits }, parentData);
|
|
106
|
-
Common_1.copyPropertyIfDefined(node, child, 'payload');
|
|
106
|
+
(0, Common_1.copyPropertyIfDefined)(node, child, 'payload');
|
|
107
107
|
mutableNodes.set(node.identifier, child);
|
|
108
108
|
}
|
|
109
109
|
else {
|
|
@@ -125,13 +125,13 @@ class Forest {
|
|
|
125
125
|
*/
|
|
126
126
|
attachRangeOfChildren(parentId, label, index, childIds) {
|
|
127
127
|
var _a;
|
|
128
|
-
Common_1.assert(index >= 0, 'invalid attach index');
|
|
128
|
+
(0, Common_1.assert)(index >= 0, 'invalid attach index');
|
|
129
129
|
const parentNode = this.nodes.get(parentId);
|
|
130
|
-
Common_1.assert(parentNode, 'can not insert children under node that does not exist');
|
|
130
|
+
(0, Common_1.assert)(parentNode, 'can not insert children under node that does not exist');
|
|
131
131
|
const mutableNodes = this.nodes.clone();
|
|
132
132
|
const traits = new Map(parentNode.traits);
|
|
133
133
|
const trait = (_a = traits.get(label)) !== null && _a !== void 0 ? _a : [];
|
|
134
|
-
Common_1.assert(index <= trait.length, 'invalid attach index');
|
|
134
|
+
(0, Common_1.assert)(index <= trait.length, 'invalid attach index');
|
|
135
135
|
// If there is nothing to insert, return early.
|
|
136
136
|
// This is good for performance, but also avoids an edge case where an empty trait could be created (which is an error).
|
|
137
137
|
if (childIds.length === 0) {
|
|
@@ -142,7 +142,7 @@ class Forest {
|
|
|
142
142
|
mutableNodes.set(parentId, Object.assign(Object.assign({}, parentNode), { traits }));
|
|
143
143
|
for (const childId of childIds) {
|
|
144
144
|
mutableNodes.editRange(childId, childId, true, (_, n) => {
|
|
145
|
-
Common_1.assert(!isParentedForestNode(n), 'can not attach node that already has a parent');
|
|
145
|
+
(0, Common_1.assert)(!isParentedForestNode(n), 'can not attach node that already has a parent');
|
|
146
146
|
const breakVal = {
|
|
147
147
|
value: Object.assign(Object.assign({}, n), { parentId, traitParent: label }),
|
|
148
148
|
};
|
|
@@ -164,16 +164,16 @@ class Forest {
|
|
|
164
164
|
*/
|
|
165
165
|
detachRangeOfChildren(parentId, label, startIndex, endIndex) {
|
|
166
166
|
var _a;
|
|
167
|
-
Common_1.assert(startIndex >= 0 && endIndex >= startIndex, 'invalid detach index range');
|
|
167
|
+
(0, Common_1.assert)(startIndex >= 0 && endIndex >= startIndex, 'invalid detach index range');
|
|
168
168
|
const parentNode = this.nodes.get(parentId);
|
|
169
|
-
Common_1.assert(parentNode, 'can not detach children under node that does not exist');
|
|
169
|
+
(0, Common_1.assert)(parentNode, 'can not detach children under node that does not exist');
|
|
170
170
|
if (startIndex === endIndex) {
|
|
171
171
|
return { forest: this, detached: [] };
|
|
172
172
|
}
|
|
173
173
|
const mutableNodes = this.nodes.clone();
|
|
174
174
|
const traits = new Map(parentNode.traits);
|
|
175
175
|
const trait = (_a = traits.get(label)) !== null && _a !== void 0 ? _a : [];
|
|
176
|
-
Common_1.assert(endIndex <= trait.length, 'invalid detach index range');
|
|
176
|
+
(0, Common_1.assert)(endIndex <= trait.length, 'invalid detach index range');
|
|
177
177
|
const detached = trait.slice(startIndex, endIndex);
|
|
178
178
|
const newChildren = [...trait.slice(0, startIndex), ...trait.slice(endIndex)];
|
|
179
179
|
const deleteTrait = newChildren.length === 0;
|
|
@@ -193,7 +193,7 @@ class Forest {
|
|
|
193
193
|
traits: n.traits,
|
|
194
194
|
},
|
|
195
195
|
};
|
|
196
|
-
Common_1.copyPropertyIfDefined(n, breakVal.value, 'payload');
|
|
196
|
+
(0, Common_1.copyPropertyIfDefined)(n, breakVal.value, 'payload');
|
|
197
197
|
return breakVal;
|
|
198
198
|
});
|
|
199
199
|
}
|
|
@@ -213,7 +213,7 @@ class Forest {
|
|
|
213
213
|
// eslint-disable-next-line @rushstack/no-new-null
|
|
214
214
|
setValue(nodeId, value) {
|
|
215
215
|
const node = this.nodes.get(nodeId);
|
|
216
|
-
Common_1.assert(node, 'can not replace payload for node that does not exist');
|
|
216
|
+
(0, Common_1.assert)(node, 'can not replace payload for node that does not exist');
|
|
217
217
|
const mutableNodes = this.nodes.clone();
|
|
218
218
|
const newNode = Object.assign({}, node);
|
|
219
219
|
if (value !== null) {
|
|
@@ -239,7 +239,7 @@ class Forest {
|
|
|
239
239
|
*/
|
|
240
240
|
get(id) {
|
|
241
241
|
var _a;
|
|
242
|
-
return (_a = this.nodes.get(id)) !== null && _a !== void 0 ? _a : Common_1.fail('NodeId not found');
|
|
242
|
+
return (_a = this.nodes.get(id)) !== null && _a !== void 0 ? _a : (0, Common_1.fail)('NodeId not found');
|
|
243
243
|
}
|
|
244
244
|
/**
|
|
245
245
|
* @returns the node associated with `id`, or undefined if there is none
|
|
@@ -264,8 +264,8 @@ class Forest {
|
|
|
264
264
|
}
|
|
265
265
|
deleteRecursive(mutableNodes, id, deleteChildren) {
|
|
266
266
|
var _a;
|
|
267
|
-
const node = (_a = mutableNodes.get(id)) !== null && _a !== void 0 ? _a : Common_1.fail('node to delete must exist');
|
|
268
|
-
Common_1.assert(!isParentedForestNode(node), 'deleted nodes must be unparented');
|
|
267
|
+
const node = (_a = mutableNodes.get(id)) !== null && _a !== void 0 ? _a : (0, Common_1.fail)('node to delete must exist');
|
|
268
|
+
(0, Common_1.assert)(!isParentedForestNode(node), 'deleted nodes must be unparented');
|
|
269
269
|
mutableNodes.delete(id);
|
|
270
270
|
for (const trait of node.traits.values()) {
|
|
271
271
|
for (const childId of trait) {
|
|
@@ -277,7 +277,7 @@ class Forest {
|
|
|
277
277
|
traits: n.traits,
|
|
278
278
|
},
|
|
279
279
|
};
|
|
280
|
-
Common_1.copyPropertyIfDefined(n, breakVal.value, 'payload');
|
|
280
|
+
(0, Common_1.copyPropertyIfDefined)(n, breakVal.value, 'payload');
|
|
281
281
|
return breakVal;
|
|
282
282
|
});
|
|
283
283
|
if (deleteChildren) {
|
|
@@ -297,18 +297,18 @@ class Forest {
|
|
|
297
297
|
if (isParentedForestNode(node)) {
|
|
298
298
|
const parent = this.get(node.parentId);
|
|
299
299
|
const trait = parent.traits.get(node.traitParent);
|
|
300
|
-
Common_1.assert(trait !== undefined);
|
|
301
|
-
Common_1.assert(trait.indexOf(node.identifier) >= 0, 'node is parented incorrectly');
|
|
300
|
+
(0, Common_1.assert)(trait !== undefined);
|
|
301
|
+
(0, Common_1.assert)(trait.indexOf(node.identifier) >= 0, 'node is parented incorrectly');
|
|
302
302
|
}
|
|
303
303
|
for (const trait of node.traits.values()) {
|
|
304
|
-
Common_1.assert(trait.length > 0, 'trait is present but empty');
|
|
304
|
+
(0, Common_1.assert)(trait.length > 0, 'trait is present but empty');
|
|
305
305
|
for (const childId of trait) {
|
|
306
306
|
const child = this.nodes.get(childId);
|
|
307
|
-
Common_1.assert(child, 'child in trait is not in forest');
|
|
308
|
-
Common_1.assert(isParentedForestNode(child), 'child is not parented');
|
|
309
|
-
Common_1.assert(child.parentId === node.identifier, 'child parent pointer is incorrect');
|
|
310
|
-
Common_1.assert(!checkedChildren.has(childId), 'the item tree tree must not contain cycles or multi-parented nodes');
|
|
311
|
-
Common_1.assert(((_a = child.parentId) !== null && _a !== void 0 ? _a : Common_1.fail('each node must have associated metadata')) === nodeId, 'cached parent is incorrect');
|
|
307
|
+
(0, Common_1.assert)(child, 'child in trait is not in forest');
|
|
308
|
+
(0, Common_1.assert)(isParentedForestNode(child), 'child is not parented');
|
|
309
|
+
(0, Common_1.assert)(child.parentId === node.identifier, 'child parent pointer is incorrect');
|
|
310
|
+
(0, Common_1.assert)(!checkedChildren.has(childId), 'the item tree tree must not contain cycles or multi-parented nodes');
|
|
311
|
+
(0, Common_1.assert)(((_a = child.parentId) !== null && _a !== void 0 ? _a : (0, Common_1.fail)('each node must have associated metadata')) === nodeId, 'cached parent is incorrect');
|
|
312
312
|
checkedChildren.add(childId);
|
|
313
313
|
}
|
|
314
314
|
}
|
|
@@ -320,9 +320,9 @@ class Forest {
|
|
|
320
320
|
getParent(id) {
|
|
321
321
|
const child = this.nodes.get(id);
|
|
322
322
|
if (child === undefined) {
|
|
323
|
-
Common_1.fail('NodeId not found');
|
|
323
|
+
(0, Common_1.fail)('NodeId not found');
|
|
324
324
|
}
|
|
325
|
-
Common_1.assert(isParentedForestNode(child), 'Node is not parented');
|
|
325
|
+
(0, Common_1.assert)(isParentedForestNode(child), 'Node is not parented');
|
|
326
326
|
return { parentId: child.parentId, traitParent: child.traitParent };
|
|
327
327
|
}
|
|
328
328
|
/**
|
|
@@ -351,7 +351,7 @@ class Forest {
|
|
|
351
351
|
if (forest.size !== this.size) {
|
|
352
352
|
return false;
|
|
353
353
|
}
|
|
354
|
-
return Common_1.compareBtrees(this.nodes, forest.nodes, compareForestNodes);
|
|
354
|
+
return (0, Common_1.compareBtrees)(this.nodes, forest.nodes, compareForestNodes);
|
|
355
355
|
}
|
|
356
356
|
/**
|
|
357
357
|
* Calculate the difference between two forests.
|
|
@@ -394,7 +394,7 @@ function compareForestNodes(nodeA, nodeB) {
|
|
|
394
394
|
if (nodeA.definition !== nodeB.definition) {
|
|
395
395
|
return false;
|
|
396
396
|
}
|
|
397
|
-
if (!PayloadUtilities_1.comparePayloads(nodeA.payload, nodeB.payload)) {
|
|
397
|
+
if (!(0, PayloadUtilities_1.comparePayloads)(nodeA.payload, nodeB.payload)) {
|
|
398
398
|
return false;
|
|
399
399
|
}
|
|
400
400
|
if (nodeA.traits.size !== nodeB.traits.size) {
|
package/dist/Forest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Forest.js","sourceRoot":"","sources":["../src/Forest.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport BTree from 'sorted-btree';\nimport { fail, assert, copyPropertyIfDefined, compareBtrees, compareFiniteNumbers } from './Common';\nimport { NodeId, TraitLabel } from './Identifiers';\nimport { comparePayloads } from './PayloadUtilities';\nimport { NodeData, Payload } from './persisted-types';\n\n/**\n * A node that can be contained within a Forest\n *\n * @public\n */\nexport interface ForestNode extends NodeData<NodeId> {\n\treadonly traits: ReadonlyMap<TraitLabel, readonly NodeId[]>;\n}\n\n/**\n * A node within a Forest that has a parent (and is therefore not the root node)\n *\n * @public\n */\nexport interface ParentedForestNode extends ForestNode, ParentData {}\n\n/**\n * Check whether or not the given node in a forest is parented\n *\n * @public\n */\nexport function isParentedForestNode(node: ForestNode): node is ParentedForestNode {\n\tconst parentedNode = node as ForestNode & Partial<ParentedForestNode>;\n\tconst hasParent = parentedNode.parentId !== undefined;\n\tconst hasTraitParent = parentedNode.traitParent !== undefined;\n\tassert(hasParent === hasTraitParent, 'node must have either both parent and traitParent set or neither');\n\treturn hasParent;\n}\n\n/**\n * Information about a ForestNode's parent\n *\n * @public\n */\nexport interface ParentData {\n\treadonly parentId: NodeId;\n\treadonly traitParent: TraitLabel;\n}\n\n/**\n * Differences from one forest to another.\n */\nexport interface Delta<NodeId> {\n\t/**\n\t * Nodes whose content changed.\n\t */\n\treadonly changed: readonly NodeId[];\n\t/**\n\t * Nodes that were added.\n\t */\n\treadonly added: readonly NodeId[];\n\t/**\n\t * Nodes that were removed.\n\t */\n\treadonly removed: readonly NodeId[];\n}\n\ninterface ForestState {\n\tnodes: BTree<NodeId, ForestNode>;\n\texpensiveValidation: boolean;\n}\n\n/**\n * An immutable forest of ForestNode.\n * Enforces single parenting, and allows querying the parent.\n *\n * @public\n */\nexport class Forest {\n\t/**\n\t * Contains the nodes in the forest.\n\t * Used as an immutable data-structure: must not be modified.\n\t */\n\tprivate readonly nodes: BTree<NodeId, ForestNode>;\n\n\t/**\n\t * If true, consistency checks will be applied after forest operations.\n\t */\n\tprivate readonly expensiveValidation: boolean;\n\n\t/**\n\t * Caller must ensure provided BTrees are not modified.\n\t * Will not modify the BTrees.\n\t */\n\tprivate constructor(data: ForestState);\n\n\t/**\n\t * Construct a new forest without reusing nodes from a previous one.\n\t */\n\tprivate constructor(expensiveValidation: boolean);\n\n\tprivate constructor(data?: ForestState | boolean) {\n\t\tif (typeof data === 'object') {\n\t\t\tthis.nodes = data.nodes;\n\t\t\tthis.expensiveValidation = data.expensiveValidation;\n\t\t} else {\n\t\t\tthis.nodes = new BTree<NodeId, ForestNode>(undefined, compareFiniteNumbers);\n\t\t\tthis.expensiveValidation = data ?? false;\n\t\t}\n\t\tif (this.expensiveValidation) {\n\t\t\tthis.assertConsistent();\n\t\t}\n\t}\n\n\t/**\n\t * Creates a new Forest.\n\t */\n\tpublic static create(expensiveValidation = false): Forest {\n\t\treturn new Forest(expensiveValidation);\n\t}\n\n\t/**\n\t * Returns the number of nodes in the forest.\n\t */\n\tpublic get size(): number {\n\t\treturn this.nodes.size;\n\t}\n\n\t/**\n\t * Adds the supplied nodes to the forest. The nodes' IDs must be unique in the forest.\n\t * @param nodes - the sequence of nodes to add to the forest. If any of them have children which exist in the forest already, those\n\t * children will be parented. Any trait arrays present in a node must be non-empty. The nodes may be provided in any order.\n\t */\n\tpublic add(nodes: Iterable<ForestNode>): Forest {\n\t\tconst newNodes = [...nodes];\n\t\tconst mutableNodes = this.nodes.clone();\n\n\t\t// This method iterates through the supplied nodes in two passes, first looking only at children and second actually adding the\n\t\t// nodes. This allows nodes to be passed in any order, e.g. a parent followed by a child or a child followed by a parent.\n\n\t\tconst childToParent = new Map<NodeId, ParentData>(); // Temporarily records the parentage of children that don't exist yet\n\n\t\t// First, inspect the children of each node. If the child is already in the forest, update its parentage. If it is not in the\n\t\t// forest, it may be about to be added in the second loop below so record its parentage temporarily for when that happens.\n\t\tfor (const node of newNodes) {\n\t\t\tconst { identifier } = node;\n\t\t\tfor (const [traitLabel, trait] of node.traits) {\n\t\t\t\tassert(trait.length > 0, 'any trait arrays present in a node must be non-empty');\n\t\t\t\tfor (const childId of trait) {\n\t\t\t\t\tconst child = mutableNodes.get(childId);\n\t\t\t\t\tif (child !== undefined) {\n\t\t\t\t\t\t// A child already exists in the forest, and its parent is now being added\n\t\t\t\t\t\tassert(!isParentedForestNode(child), 'can not give a child multiple parents');\n\t\t\t\t\t\tconst parentedChild = {\n\t\t\t\t\t\t\tdefinition: child.definition,\n\t\t\t\t\t\t\tidentifier: child.identifier,\n\t\t\t\t\t\t\ttraits: child.traits,\n\t\t\t\t\t\t\tparentId: identifier,\n\t\t\t\t\t\t\ttraitParent: traitLabel,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tcopyPropertyIfDefined(child, parentedChild, 'payload');\n\t\t\t\t\t\t// Overwrite the existing child with its parented version\n\t\t\t\t\t\tmutableNodes.set(childId, parentedChild);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// The child hasn't been added yet, so record its parentage to use when it is added below\n\t\t\t\t\t\tchildToParent.set(childId, { parentId: identifier, traitParent: traitLabel });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Now add each node to the forest and apply any parentage information that was recorded above\n\t\tfor (const node of newNodes) {\n\t\t\tconst parentData = childToParent.get(node.identifier);\n\t\t\tassert(!mutableNodes.has(node.identifier), 'can not add node with already existing id');\n\t\t\tif (parentData !== undefined) {\n\t\t\t\t// This is a child whom we haven't added yet, but whose parent we already added above. Supply the recorded parentage info.\n\t\t\t\tconst child = {\n\t\t\t\t\tdefinition: node.definition,\n\t\t\t\t\tidentifier: node.identifier,\n\t\t\t\t\ttraits: node.traits,\n\t\t\t\t\t...parentData,\n\t\t\t\t};\n\t\t\t\tcopyPropertyIfDefined(node, child, 'payload');\n\t\t\t\tmutableNodes.set(node.identifier, child);\n\t\t\t} else {\n\t\t\t\t// This is a node that has no parent. Add it with no parentage information.\n\t\t\t\tmutableNodes.set(node.identifier, node);\n\t\t\t}\n\t\t}\n\n\t\treturn new Forest({\n\t\t\tnodes: mutableNodes,\n\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t});\n\t}\n\n\t/**\n\t * Parents a set of nodes already in the forest at a specified location within a trait.\n\t * @param parentId - the id of the parent under which to insert the new nodes\n\t * @param label - the label of the trait under which to insert the new nodes\n\t * @param index - the index in the trait after which to insert the new nodes\n\t * @param childIds - the ids of the nodes to insert\n\t */\n\tpublic attachRangeOfChildren(\n\t\tparentId: NodeId,\n\t\tlabel: TraitLabel,\n\t\tindex: number,\n\t\tchildIds: readonly NodeId[]\n\t): Forest {\n\t\tassert(index >= 0, 'invalid attach index');\n\t\tconst parentNode = this.nodes.get(parentId);\n\t\tassert(parentNode, 'can not insert children under node that does not exist');\n\t\tconst mutableNodes = this.nodes.clone();\n\t\tconst traits = new Map(parentNode.traits);\n\t\tconst trait = traits.get(label) ?? [];\n\t\tassert(index <= trait.length, 'invalid attach index');\n\n\t\t// If there is nothing to insert, return early.\n\t\t// This is good for performance, but also avoids an edge case where an empty trait could be created (which is an error).\n\t\tif (childIds.length === 0) {\n\t\t\treturn this;\n\t\t}\n\t\tconst newChildren = [...trait.slice(0, index), ...childIds, ...trait.slice(index)];\n\t\ttraits.set(label, newChildren);\n\t\tmutableNodes.set(parentId, { ...parentNode, traits });\n\n\t\tfor (const childId of childIds) {\n\t\t\tmutableNodes.editRange(childId, childId, true, (_, n) => {\n\t\t\t\tassert(!isParentedForestNode(n), 'can not attach node that already has a parent');\n\t\t\t\tconst breakVal: { value: ParentedForestNode } = {\n\t\t\t\t\tvalue: {\n\t\t\t\t\t\t...n,\n\t\t\t\t\t\tparentId,\n\t\t\t\t\t\ttraitParent: label,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\treturn breakVal;\n\t\t\t});\n\t\t}\n\n\t\treturn new Forest({\n\t\t\tnodes: mutableNodes,\n\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t});\n\t}\n\n\t/**\n\t * Detaches a range of nodes from their parent. The detached nodes remain in the `Forest`.\n\t * @param parentId - the id of the parent from which to detach the nodes\n\t * @param label - the label of the trait from which to detach the nodes\n\t * @param startIndex - the index of the first node in the range to detach\n\t * @param endIndex - the index after the last node in the range to detach\n\t * @returns a new `Forest` with the nodes detached, and a list of the ids of the nodes that were detached\n\t */\n\tpublic detachRangeOfChildren(\n\t\tparentId: NodeId,\n\t\tlabel: TraitLabel,\n\t\tstartIndex: number,\n\t\tendIndex: number\n\t): { forest: Forest; detached: readonly NodeId[] } {\n\t\tassert(startIndex >= 0 && endIndex >= startIndex, 'invalid detach index range');\n\t\tconst parentNode = this.nodes.get(parentId);\n\t\tassert(parentNode, 'can not detach children under node that does not exist');\n\t\tif (startIndex === endIndex) {\n\t\t\treturn { forest: this, detached: [] };\n\t\t}\n\n\t\tconst mutableNodes = this.nodes.clone();\n\t\tconst traits = new Map(parentNode.traits);\n\t\tconst trait = traits.get(label) ?? [];\n\t\tassert(endIndex <= trait.length, 'invalid detach index range');\n\t\tconst detached: NodeId[] = trait.slice(startIndex, endIndex);\n\t\tconst newChildren = [...trait.slice(0, startIndex), ...trait.slice(endIndex)];\n\t\tconst deleteTrait = newChildren.length === 0;\n\t\tif (deleteTrait) {\n\t\t\ttraits.delete(label);\n\t\t} else {\n\t\t\ttraits.set(label, newChildren);\n\t\t}\n\n\t\tmutableNodes.set(parentId, { ...parentNode, traits });\n\t\tfor (const childId of detached) {\n\t\t\tmutableNodes.editRange(childId, childId, true, (_, n) => {\n\t\t\t\tconst breakVal: { value: ForestNode } = {\n\t\t\t\t\tvalue: {\n\t\t\t\t\t\tdefinition: n.definition,\n\t\t\t\t\t\tidentifier: n.identifier,\n\t\t\t\t\t\ttraits: n.traits,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tcopyPropertyIfDefined(n, breakVal.value, 'payload');\n\t\t\t\treturn breakVal;\n\t\t\t});\n\t\t}\n\n\t\treturn {\n\t\t\tforest: new Forest({\n\t\t\t\tnodes: mutableNodes,\n\t\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t\t}),\n\t\t\tdetached,\n\t\t};\n\t}\n\n\t/**\n\t * Replaces a node's value. The node must exist in this `Forest`.\n\t * @param nodeId - the id of the node\n\t * @param value - the new value\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic setValue(nodeId: NodeId, value: Payload | null): Forest {\n\t\tconst node = this.nodes.get(nodeId);\n\t\tassert(node, 'can not replace payload for node that does not exist');\n\t\tconst mutableNodes = this.nodes.clone();\n\t\tconst newNode = { ...node };\n\t\tif (value !== null) {\n\t\t\tnewNode.payload = value;\n\t\t} else {\n\t\t\tdelete newNode.payload;\n\t\t}\n\t\tmutableNodes.set(nodeId, newNode);\n\t\treturn new Forest({\n\t\t\tnodes: mutableNodes,\n\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t});\n\t}\n\n\t/**\n\t * @returns true if the node associated with `id` exists in this forest, otherwise false\n\t */\n\tpublic has(id: NodeId): boolean {\n\t\treturn this.nodes.has(id);\n\t}\n\n\t/**\n\t * @returns the node associated with `id`. Should not be used if there is no node with the provided id.\n\t */\n\tpublic get(id: NodeId): ForestNode {\n\t\treturn this.nodes.get(id) ?? fail('NodeId not found');\n\t}\n\n\t/**\n\t * @returns the node associated with `id`, or undefined if there is none\n\t */\n\tpublic tryGet(id: NodeId): ForestNode | undefined {\n\t\treturn this.nodes.get(id);\n\t}\n\n\t/**\n\t * Deletes every node in ids (each of which must be unparented)\n\t * @param ids - The IDs of the nodes to delete.\n\t * @param deleteChildren - If true, recursively deletes descendants. Otherwise, leaves children unparented.\n\t */\n\tpublic delete(ids: Iterable<NodeId>, deleteChildren: boolean): Forest {\n\t\tconst mutableNodes = this.nodes.clone();\n\t\tfor (const id of ids) {\n\t\t\tthis.deleteRecursive(mutableNodes, id, deleteChildren);\n\t\t}\n\n\t\treturn new Forest({\n\t\t\tnodes: mutableNodes,\n\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t});\n\t}\n\n\tprivate deleteRecursive(mutableNodes: BTree<NodeId, ForestNode>, id: NodeId, deleteChildren: boolean): void {\n\t\tconst node = mutableNodes.get(id) ?? fail('node to delete must exist');\n\t\tassert(!isParentedForestNode(node), 'deleted nodes must be unparented');\n\t\tmutableNodes.delete(id);\n\t\tfor (const trait of node.traits.values()) {\n\t\t\tfor (const childId of trait) {\n\t\t\t\tmutableNodes.editRange(childId, childId, true, (_, n) => {\n\t\t\t\t\tconst breakVal: { value: ForestNode } = {\n\t\t\t\t\t\tvalue: {\n\t\t\t\t\t\t\tdefinition: n.definition,\n\t\t\t\t\t\t\tidentifier: n.identifier,\n\t\t\t\t\t\t\ttraits: n.traits,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tcopyPropertyIfDefined(n, breakVal.value, 'payload');\n\t\t\t\t\treturn breakVal;\n\t\t\t\t});\n\n\t\t\t\tif (deleteChildren) {\n\t\t\t\t\tthis.deleteRecursive(mutableNodes, childId, deleteChildren);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks that the metadata is correct, and the items form a forest.\n\t * This is an expensive O(map size) operation.\n\t */\n\tpublic assertConsistent(): void {\n\t\tconst checkedChildren = new Set<NodeId>([]);\n\t\tfor (const [nodeId, node] of this.nodes.entries(undefined, [])) {\n\t\t\tif (isParentedForestNode(node)) {\n\t\t\t\tconst parent = this.get(node.parentId);\n\t\t\t\tconst trait = parent.traits.get(node.traitParent);\n\t\t\t\tassert(trait !== undefined);\n\t\t\t\tassert(trait.indexOf(node.identifier) >= 0, 'node is parented incorrectly');\n\t\t\t}\n\n\t\t\tfor (const trait of node.traits.values()) {\n\t\t\t\tassert(trait.length > 0, 'trait is present but empty');\n\t\t\t\tfor (const childId of trait) {\n\t\t\t\t\tconst child = this.nodes.get(childId);\n\t\t\t\t\tassert(child, 'child in trait is not in forest');\n\t\t\t\t\tassert(isParentedForestNode(child), 'child is not parented');\n\t\t\t\t\tassert(child.parentId === node.identifier, 'child parent pointer is incorrect');\n\t\t\t\t\tassert(\n\t\t\t\t\t\t!checkedChildren.has(childId),\n\t\t\t\t\t\t'the item tree tree must not contain cycles or multi-parented nodes'\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\t(child.parentId ?? fail('each node must have associated metadata')) === nodeId,\n\t\t\t\t\t\t'cached parent is incorrect'\n\t\t\t\t\t);\n\t\t\t\t\tcheckedChildren.add(childId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * @returns the parent of `id`. Should not be used if there is no node with id or if id refers to the root node.\n\t */\n\tpublic getParent(id: NodeId): ParentData {\n\t\tconst child = this.nodes.get(id);\n\t\tif (child === undefined) {\n\t\t\tfail('NodeId not found');\n\t\t}\n\n\t\tassert(isParentedForestNode(child), 'Node is not parented');\n\t\treturn { parentId: child.parentId, traitParent: child.traitParent };\n\t}\n\n\t/**\n\t * @returns undefined iff root, otherwise the parent of `id`.\n\t */\n\tpublic tryGetParent(id: NodeId): ParentData | undefined {\n\t\tconst child = this.nodes.get(id);\n\t\tif (child === undefined || !isParentedForestNode(child)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tparentId: child.parentId,\n\t\t\ttraitParent: child.traitParent,\n\t\t};\n\t}\n\n\t/**\n\t * Compares two forests for equality.\n\t * @param forest - the other forest to compare to this one\n\t * @param comparator - a function which returns true if two objects of type ForestNode are equivalent, false otherwise\n\t * @returns true iff the forests are equal.\n\t */\n\tpublic equals(forest: Forest): boolean {\n\t\tif (this === forest || this.nodes === forest.nodes) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (forest.size !== this.size) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn compareBtrees(this.nodes, forest.nodes, compareForestNodes);\n\t}\n\n\t/**\n\t * Calculate the difference between two forests.\n\t * @param forest - the other forest to compare to this one\n\t * @param comparator - a function which returns true if two objects of type ForestNode are equivalent, false otherwise\n\t * @returns A {@link Delta} listing which nodes must be changed, added, and removed to get from `this` to `forest`.\n\t */\n\tpublic delta(forest: Forest): Delta<NodeId> {\n\t\tconst changed: NodeId[] = [];\n\t\tconst removed: NodeId[] = [];\n\t\tconst added: NodeId[] = [];\n\t\tthis.nodes.diffAgainst(\n\t\t\tforest.nodes,\n\t\t\t(id) => {\n\t\t\t\tremoved.push(id);\n\t\t\t},\n\t\t\t(id) => {\n\t\t\t\tadded.push(id);\n\t\t\t},\n\t\t\t(id, nodeThis, nodeOther) => {\n\t\t\t\tif (!compareForestNodes(nodeThis, nodeOther)) {\n\t\t\t\t\tchanged.push(id);\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t\treturn {\n\t\t\tchanged,\n\t\t\tadded,\n\t\t\tremoved,\n\t\t};\n\t}\n}\n\n/**\n * @returns true iff two `ForestNodes` are equivalent.\n * May return false for nodes they contain equivalent payloads encoded differently.\n */\nexport function compareForestNodes(nodeA: ForestNode, nodeB: ForestNode): boolean {\n\tif (nodeA === nodeB) {\n\t\treturn true;\n\t}\n\n\tif (nodeA.identifier !== nodeB.identifier) {\n\t\treturn false;\n\t}\n\n\tif (nodeA.definition !== nodeB.definition) {\n\t\treturn false;\n\t}\n\n\tif (!comparePayloads(nodeA.payload, nodeB.payload)) {\n\t\treturn false;\n\t}\n\n\tif (nodeA.traits.size !== nodeB.traits.size) {\n\t\treturn false;\n\t}\n\n\tfor (const traitA of nodeA.traits) {\n\t\tconst [traitLabelA, nodeSequenceA] = traitA;\n\t\tconst nodeSequenceB = nodeB.traits.get(traitLabelA);\n\t\tif (!nodeSequenceB) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (nodeSequenceA.length !== nodeSequenceB.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (let i = 0; i < nodeSequenceA.length; i++) {\n\t\t\tif (nodeSequenceA[i] !== nodeSequenceB[i]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Forest.js","sourceRoot":"","sources":["../src/Forest.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AAEH,gEAAiC;AACjC,qCAAoG;AAEpG,yDAAqD;AAmBrD;;;;GAIG;AACH,SAAgB,oBAAoB,CAAC,IAAgB;IACpD,MAAM,YAAY,GAAG,IAAgD,CAAC;IACtE,MAAM,SAAS,GAAG,YAAY,CAAC,QAAQ,KAAK,SAAS,CAAC;IACtD,MAAM,cAAc,GAAG,YAAY,CAAC,WAAW,KAAK,SAAS,CAAC;IAC9D,IAAA,eAAM,EAAC,SAAS,KAAK,cAAc,EAAE,kEAAkE,CAAC,CAAC;IACzG,OAAO,SAAS,CAAC;AAClB,CAAC;AAND,oDAMC;AAmCD;;;;;GAKG;AACH,MAAa,MAAM;IAuBlB,YAAoB,IAA4B;QAC/C,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;YAC7B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YACxB,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,CAAC;SACpD;aAAM;YACN,IAAI,CAAC,KAAK,GAAG,IAAI,sBAAK,CAAqB,SAAS,EAAE,6BAAoB,CAAC,CAAC;YAC5E,IAAI,CAAC,mBAAmB,GAAG,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,KAAK,CAAC;SACzC;QACD,IAAI,IAAI,CAAC,mBAAmB,EAAE;YAC7B,IAAI,CAAC,gBAAgB,EAAE,CAAC;SACxB;IACF,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,MAAM,CAAC,mBAAmB,GAAG,KAAK;QAC/C,OAAO,IAAI,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,IAAW,IAAI;QACd,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACxB,CAAC;IAED;;;;OAIG;IACI,GAAG,CAAC,KAA2B;QACrC,MAAM,QAAQ,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;QAC5B,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAExC,+HAA+H;QAC/H,yHAAyH;QAEzH,MAAM,aAAa,GAAG,IAAI,GAAG,EAAsB,CAAC,CAAC,qEAAqE;QAE1H,6HAA6H;QAC7H,0HAA0H;QAC1H,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE;YAC5B,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;YAC5B,KAAK,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE;gBAC9C,IAAA,eAAM,EAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,sDAAsD,CAAC,CAAC;gBACjF,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE;oBAC5B,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;oBACxC,IAAI,KAAK,KAAK,SAAS,EAAE;wBACxB,0EAA0E;wBAC1E,IAAA,eAAM,EAAC,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,uCAAuC,CAAC,CAAC;wBAC9E,MAAM,aAAa,GAAG;4BACrB,UAAU,EAAE,KAAK,CAAC,UAAU;4BAC5B,UAAU,EAAE,KAAK,CAAC,UAAU;4BAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;4BACpB,QAAQ,EAAE,UAAU;4BACpB,WAAW,EAAE,UAAU;yBACvB,CAAC;wBACF,IAAA,8BAAqB,EAAC,KAAK,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;wBACvD,yDAAyD;wBACzD,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;qBACzC;yBAAM;wBACN,yFAAyF;wBACzF,aAAa,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;qBAC9E;iBACD;aACD;SACD;QAED,8FAA8F;QAC9F,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE;YAC5B,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACtD,IAAA,eAAM,EAAC,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,2CAA2C,CAAC,CAAC;YACxF,IAAI,UAAU,KAAK,SAAS,EAAE;gBAC7B,0HAA0H;gBAC1H,MAAM,KAAK,mBACV,UAAU,EAAE,IAAI,CAAC,UAAU,EAC3B,UAAU,EAAE,IAAI,CAAC,UAAU,EAC3B,MAAM,EAAE,IAAI,CAAC,MAAM,IAChB,UAAU,CACb,CAAC;gBACF,IAAA,8BAAqB,EAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;gBAC9C,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;aACzC;iBAAM;gBACN,2EAA2E;gBAC3E,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;aACxC;SACD;QAED,OAAO,IAAI,MAAM,CAAC;YACjB,KAAK,EAAE,YAAY;YACnB,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;SAC7C,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACI,qBAAqB,CAC3B,QAAgB,EAChB,KAAiB,EACjB,KAAa,EACb,QAA2B;;QAE3B,IAAA,eAAM,EAAC,KAAK,IAAI,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAA,eAAM,EAAC,UAAU,EAAE,wDAAwD,CAAC,CAAC;QAC7E,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAA,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,mCAAI,EAAE,CAAC;QACtC,IAAA,eAAM,EAAC,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;QAEtD,+CAA+C;QAC/C,wHAAwH;QACxH,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;YAC1B,OAAO,IAAI,CAAC;SACZ;QACD,MAAM,WAAW,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,QAAQ,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QACnF,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAC/B,YAAY,CAAC,GAAG,CAAC,QAAQ,kCAAO,UAAU,KAAE,MAAM,IAAG,CAAC;QAEtD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;YAC/B,YAAY,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;gBACvD,IAAA,eAAM,EAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,+CAA+C,CAAC,CAAC;gBAClF,MAAM,QAAQ,GAAkC;oBAC/C,KAAK,kCACD,CAAC,KACJ,QAAQ,EACR,WAAW,EAAE,KAAK,GAClB;iBACD,CAAC;gBACF,OAAO,QAAQ,CAAC;YACjB,CAAC,CAAC,CAAC;SACH;QAED,OAAO,IAAI,MAAM,CAAC;YACjB,KAAK,EAAE,YAAY;YACnB,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;SAC7C,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACI,qBAAqB,CAC3B,QAAgB,EAChB,KAAiB,EACjB,UAAkB,EAClB,QAAgB;;QAEhB,IAAA,eAAM,EAAC,UAAU,IAAI,CAAC,IAAI,QAAQ,IAAI,UAAU,EAAE,4BAA4B,CAAC,CAAC;QAChF,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAA,eAAM,EAAC,UAAU,EAAE,wDAAwD,CAAC,CAAC;QAC7E,IAAI,UAAU,KAAK,QAAQ,EAAE;YAC5B,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;SACtC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAA,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,mCAAI,EAAE,CAAC;QACtC,IAAA,eAAM,EAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAAC;QAC/D,MAAM,QAAQ,GAAa,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC7D,MAAM,WAAW,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC9E,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC;QAC7C,IAAI,WAAW,EAAE;YAChB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;SACrB;aAAM;YACN,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;SAC/B;QAED,YAAY,CAAC,GAAG,CAAC,QAAQ,kCAAO,UAAU,KAAE,MAAM,IAAG,CAAC;QACtD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;YAC/B,YAAY,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;gBACvD,MAAM,QAAQ,GAA0B;oBACvC,KAAK,EAAE;wBACN,UAAU,EAAE,CAAC,CAAC,UAAU;wBACxB,UAAU,EAAE,CAAC,CAAC,UAAU;wBACxB,MAAM,EAAE,CAAC,CAAC,MAAM;qBAChB;iBACD,CAAC;gBACF,IAAA,8BAAqB,EAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;gBACpD,OAAO,QAAQ,CAAC;YACjB,CAAC,CAAC,CAAC;SACH;QAED,OAAO;YACN,MAAM,EAAE,IAAI,MAAM,CAAC;gBAClB,KAAK,EAAE,YAAY;gBACnB,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;aAC7C,CAAC;YACF,QAAQ;SACR,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,kDAAkD;IAC3C,QAAQ,CAAC,MAAc,EAAE,KAAqB;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpC,IAAA,eAAM,EAAC,IAAI,EAAE,sDAAsD,CAAC,CAAC;QACrE,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,OAAO,qBAAQ,IAAI,CAAE,CAAC;QAC5B,IAAI,KAAK,KAAK,IAAI,EAAE;YACnB,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC;SACxB;aAAM;YACN,OAAO,OAAO,CAAC,OAAO,CAAC;SACvB;QACD,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,OAAO,IAAI,MAAM,CAAC;YACjB,KAAK,EAAE,YAAY;YACnB,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;SAC7C,CAAC,CAAC;IACJ,CAAC;IAED;;OAEG;IACI,GAAG,CAAC,EAAU;QACpB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED;;OAEG;IACI,GAAG,CAAC,EAAU;;QACpB,OAAO,MAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,mCAAI,IAAA,aAAI,EAAC,kBAAkB,CAAC,CAAC;IACvD,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,EAAU;QACvB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,GAAqB,EAAE,cAAuB;QAC3D,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE;YACrB,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,EAAE,EAAE,cAAc,CAAC,CAAC;SACvD;QAED,OAAO,IAAI,MAAM,CAAC;YACjB,KAAK,EAAE,YAAY;YACnB,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;SAC7C,CAAC,CAAC;IACJ,CAAC;IAEO,eAAe,CAAC,YAAuC,EAAE,EAAU,EAAE,cAAuB;;QACnG,MAAM,IAAI,GAAG,MAAA,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,mCAAI,IAAA,aAAI,EAAC,2BAA2B,CAAC,CAAC;QACvE,IAAA,eAAM,EAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,kCAAkC,CAAC,CAAC;QACxE,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE;YACzC,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE;gBAC5B,YAAY,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;oBACvD,MAAM,QAAQ,GAA0B;wBACvC,KAAK,EAAE;4BACN,UAAU,EAAE,CAAC,CAAC,UAAU;4BACxB,UAAU,EAAE,CAAC,CAAC,UAAU;4BACxB,MAAM,EAAE,CAAC,CAAC,MAAM;yBAChB;qBACD,CAAC;oBACF,IAAA,8BAAqB,EAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;oBACpD,OAAO,QAAQ,CAAC;gBACjB,CAAC,CAAC,CAAC;gBAEH,IAAI,cAAc,EAAE;oBACnB,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;iBAC5D;aACD;SACD;IACF,CAAC;IAED;;;OAGG;IACI,gBAAgB;;QACtB,MAAM,eAAe,GAAG,IAAI,GAAG,CAAS,EAAE,CAAC,CAAC;QAC5C,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE;YAC/D,IAAI,oBAAoB,CAAC,IAAI,CAAC,EAAE;gBAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACvC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBAClD,IAAA,eAAM,EAAC,KAAK,KAAK,SAAS,CAAC,CAAC;gBAC5B,IAAA,eAAM,EAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,8BAA8B,CAAC,CAAC;aAC5E;YAED,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE;gBACzC,IAAA,eAAM,EAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,4BAA4B,CAAC,CAAC;gBACvD,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE;oBAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;oBACtC,IAAA,eAAM,EAAC,KAAK,EAAE,iCAAiC,CAAC,CAAC;oBACjD,IAAA,eAAM,EAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,uBAAuB,CAAC,CAAC;oBAC7D,IAAA,eAAM,EAAC,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,UAAU,EAAE,mCAAmC,CAAC,CAAC;oBAChF,IAAA,eAAM,EACL,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,EAC7B,oEAAoE,CACpE,CAAC;oBACF,IAAA,eAAM,EACL,CAAC,MAAA,KAAK,CAAC,QAAQ,mCAAI,IAAA,aAAI,EAAC,yCAAyC,CAAC,CAAC,KAAK,MAAM,EAC9E,4BAA4B,CAC5B,CAAC;oBACF,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;iBAC7B;aACD;SACD;IACF,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,EAAU;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACjC,IAAI,KAAK,KAAK,SAAS,EAAE;YACxB,IAAA,aAAI,EAAC,kBAAkB,CAAC,CAAC;SACzB;QAED,IAAA,eAAM,EAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAC5D,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;IACrE,CAAC;IAED;;OAEG;IACI,YAAY,CAAC,EAAU;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACjC,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE;YACxD,OAAO,SAAS,CAAC;SACjB;QAED,OAAO;YACN,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,WAAW,EAAE,KAAK,CAAC,WAAW;SAC9B,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,MAAc;QAC3B,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,EAAE;YACnD,OAAO,IAAI,CAAC;SACZ;QAED,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE;YAC9B,OAAO,KAAK,CAAC;SACb;QAED,OAAO,IAAA,sBAAa,EAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;IACpE,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,MAAc;QAC1B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,WAAW,CACrB,MAAM,CAAC,KAAK,EACZ,CAAC,EAAE,EAAE,EAAE;YACN,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC,EACD,CAAC,EAAE,EAAE,EAAE;YACN,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB,CAAC,EACD,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;YAC3B,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE;gBAC7C,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;aACjB;QACF,CAAC,CACD,CAAC;QACF,OAAO;YACN,OAAO;YACP,KAAK;YACL,OAAO;SACP,CAAC;IACH,CAAC;CACD;AAxaD,wBAwaC;AAED;;;GAGG;AACH,SAAgB,kBAAkB,CAAC,KAAiB,EAAE,KAAiB;IACtE,IAAI,KAAK,KAAK,KAAK,EAAE;QACpB,OAAO,IAAI,CAAC;KACZ;IAED,IAAI,KAAK,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU,EAAE;QAC1C,OAAO,KAAK,CAAC;KACb;IAED,IAAI,KAAK,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU,EAAE;QAC1C,OAAO,KAAK,CAAC;KACb;IAED,IAAI,CAAC,IAAA,kCAAe,EAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE;QACnD,OAAO,KAAK,CAAC;KACb;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE;QAC5C,OAAO,KAAK,CAAC;KACb;IAED,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,MAAM,EAAE;QAClC,MAAM,CAAC,WAAW,EAAE,aAAa,CAAC,GAAG,MAAM,CAAC;QAC5C,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACpD,IAAI,CAAC,aAAa,EAAE;YACnB,OAAO,KAAK,CAAC;SACb;QAED,IAAI,aAAa,CAAC,MAAM,KAAK,aAAa,CAAC,MAAM,EAAE;YAClD,OAAO,KAAK,CAAC;SACb;QAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC9C,IAAI,aAAa,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,EAAE;gBAC1C,OAAO,KAAK,CAAC;aACb;SACD;KACD;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAxCD,gDAwCC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport BTree from 'sorted-btree';\nimport { fail, assert, copyPropertyIfDefined, compareBtrees, compareFiniteNumbers } from './Common';\nimport { NodeId, TraitLabel } from './Identifiers';\nimport { comparePayloads } from './PayloadUtilities';\nimport { NodeData, Payload } from './persisted-types';\n\n/**\n * A node that can be contained within a Forest\n *\n * @public\n */\nexport interface ForestNode extends NodeData<NodeId> {\n\treadonly traits: ReadonlyMap<TraitLabel, readonly NodeId[]>;\n}\n\n/**\n * A node within a Forest that has a parent (and is therefore not the root node)\n *\n * @public\n */\nexport interface ParentedForestNode extends ForestNode, ParentData {}\n\n/**\n * Check whether or not the given node in a forest is parented\n *\n * @public\n */\nexport function isParentedForestNode(node: ForestNode): node is ParentedForestNode {\n\tconst parentedNode = node as ForestNode & Partial<ParentedForestNode>;\n\tconst hasParent = parentedNode.parentId !== undefined;\n\tconst hasTraitParent = parentedNode.traitParent !== undefined;\n\tassert(hasParent === hasTraitParent, 'node must have either both parent and traitParent set or neither');\n\treturn hasParent;\n}\n\n/**\n * Information about a ForestNode's parent\n *\n * @public\n */\nexport interface ParentData {\n\treadonly parentId: NodeId;\n\treadonly traitParent: TraitLabel;\n}\n\n/**\n * Differences from one forest to another.\n */\nexport interface Delta<NodeId> {\n\t/**\n\t * Nodes whose content changed.\n\t */\n\treadonly changed: readonly NodeId[];\n\t/**\n\t * Nodes that were added.\n\t */\n\treadonly added: readonly NodeId[];\n\t/**\n\t * Nodes that were removed.\n\t */\n\treadonly removed: readonly NodeId[];\n}\n\ninterface ForestState {\n\tnodes: BTree<NodeId, ForestNode>;\n\texpensiveValidation: boolean;\n}\n\n/**\n * An immutable forest of ForestNode.\n * Enforces single parenting, and allows querying the parent.\n *\n * @public\n */\nexport class Forest {\n\t/**\n\t * Contains the nodes in the forest.\n\t * Used as an immutable data-structure: must not be modified.\n\t */\n\tprivate readonly nodes: BTree<NodeId, ForestNode>;\n\n\t/**\n\t * If true, consistency checks will be applied after forest operations.\n\t */\n\tprivate readonly expensiveValidation: boolean;\n\n\t/**\n\t * Caller must ensure provided BTrees are not modified.\n\t * Will not modify the BTrees.\n\t */\n\tprivate constructor(data: ForestState);\n\n\t/**\n\t * Construct a new forest without reusing nodes from a previous one.\n\t */\n\tprivate constructor(expensiveValidation: boolean);\n\n\tprivate constructor(data?: ForestState | boolean) {\n\t\tif (typeof data === 'object') {\n\t\t\tthis.nodes = data.nodes;\n\t\t\tthis.expensiveValidation = data.expensiveValidation;\n\t\t} else {\n\t\t\tthis.nodes = new BTree<NodeId, ForestNode>(undefined, compareFiniteNumbers);\n\t\t\tthis.expensiveValidation = data ?? false;\n\t\t}\n\t\tif (this.expensiveValidation) {\n\t\t\tthis.assertConsistent();\n\t\t}\n\t}\n\n\t/**\n\t * Creates a new Forest.\n\t */\n\tpublic static create(expensiveValidation = false): Forest {\n\t\treturn new Forest(expensiveValidation);\n\t}\n\n\t/**\n\t * Returns the number of nodes in the forest.\n\t */\n\tpublic get size(): number {\n\t\treturn this.nodes.size;\n\t}\n\n\t/**\n\t * Adds the supplied nodes to the forest. The nodes' IDs must be unique in the forest.\n\t * @param nodes - the sequence of nodes to add to the forest. If any of them have children which exist in the forest already, those\n\t * children will be parented. Any trait arrays present in a node must be non-empty. The nodes may be provided in any order.\n\t */\n\tpublic add(nodes: Iterable<ForestNode>): Forest {\n\t\tconst newNodes = [...nodes];\n\t\tconst mutableNodes = this.nodes.clone();\n\n\t\t// This method iterates through the supplied nodes in two passes, first looking only at children and second actually adding the\n\t\t// nodes. This allows nodes to be passed in any order, e.g. a parent followed by a child or a child followed by a parent.\n\n\t\tconst childToParent = new Map<NodeId, ParentData>(); // Temporarily records the parentage of children that don't exist yet\n\n\t\t// First, inspect the children of each node. If the child is already in the forest, update its parentage. If it is not in the\n\t\t// forest, it may be about to be added in the second loop below so record its parentage temporarily for when that happens.\n\t\tfor (const node of newNodes) {\n\t\t\tconst { identifier } = node;\n\t\t\tfor (const [traitLabel, trait] of node.traits) {\n\t\t\t\tassert(trait.length > 0, 'any trait arrays present in a node must be non-empty');\n\t\t\t\tfor (const childId of trait) {\n\t\t\t\t\tconst child = mutableNodes.get(childId);\n\t\t\t\t\tif (child !== undefined) {\n\t\t\t\t\t\t// A child already exists in the forest, and its parent is now being added\n\t\t\t\t\t\tassert(!isParentedForestNode(child), 'can not give a child multiple parents');\n\t\t\t\t\t\tconst parentedChild = {\n\t\t\t\t\t\t\tdefinition: child.definition,\n\t\t\t\t\t\t\tidentifier: child.identifier,\n\t\t\t\t\t\t\ttraits: child.traits,\n\t\t\t\t\t\t\tparentId: identifier,\n\t\t\t\t\t\t\ttraitParent: traitLabel,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tcopyPropertyIfDefined(child, parentedChild, 'payload');\n\t\t\t\t\t\t// Overwrite the existing child with its parented version\n\t\t\t\t\t\tmutableNodes.set(childId, parentedChild);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// The child hasn't been added yet, so record its parentage to use when it is added below\n\t\t\t\t\t\tchildToParent.set(childId, { parentId: identifier, traitParent: traitLabel });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Now add each node to the forest and apply any parentage information that was recorded above\n\t\tfor (const node of newNodes) {\n\t\t\tconst parentData = childToParent.get(node.identifier);\n\t\t\tassert(!mutableNodes.has(node.identifier), 'can not add node with already existing id');\n\t\t\tif (parentData !== undefined) {\n\t\t\t\t// This is a child whom we haven't added yet, but whose parent we already added above. Supply the recorded parentage info.\n\t\t\t\tconst child = {\n\t\t\t\t\tdefinition: node.definition,\n\t\t\t\t\tidentifier: node.identifier,\n\t\t\t\t\ttraits: node.traits,\n\t\t\t\t\t...parentData,\n\t\t\t\t};\n\t\t\t\tcopyPropertyIfDefined(node, child, 'payload');\n\t\t\t\tmutableNodes.set(node.identifier, child);\n\t\t\t} else {\n\t\t\t\t// This is a node that has no parent. Add it with no parentage information.\n\t\t\t\tmutableNodes.set(node.identifier, node);\n\t\t\t}\n\t\t}\n\n\t\treturn new Forest({\n\t\t\tnodes: mutableNodes,\n\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t});\n\t}\n\n\t/**\n\t * Parents a set of nodes already in the forest at a specified location within a trait.\n\t * @param parentId - the id of the parent under which to insert the new nodes\n\t * @param label - the label of the trait under which to insert the new nodes\n\t * @param index - the index in the trait after which to insert the new nodes\n\t * @param childIds - the ids of the nodes to insert\n\t */\n\tpublic attachRangeOfChildren(\n\t\tparentId: NodeId,\n\t\tlabel: TraitLabel,\n\t\tindex: number,\n\t\tchildIds: readonly NodeId[]\n\t): Forest {\n\t\tassert(index >= 0, 'invalid attach index');\n\t\tconst parentNode = this.nodes.get(parentId);\n\t\tassert(parentNode, 'can not insert children under node that does not exist');\n\t\tconst mutableNodes = this.nodes.clone();\n\t\tconst traits = new Map(parentNode.traits);\n\t\tconst trait = traits.get(label) ?? [];\n\t\tassert(index <= trait.length, 'invalid attach index');\n\n\t\t// If there is nothing to insert, return early.\n\t\t// This is good for performance, but also avoids an edge case where an empty trait could be created (which is an error).\n\t\tif (childIds.length === 0) {\n\t\t\treturn this;\n\t\t}\n\t\tconst newChildren = [...trait.slice(0, index), ...childIds, ...trait.slice(index)];\n\t\ttraits.set(label, newChildren);\n\t\tmutableNodes.set(parentId, { ...parentNode, traits });\n\n\t\tfor (const childId of childIds) {\n\t\t\tmutableNodes.editRange(childId, childId, true, (_, n) => {\n\t\t\t\tassert(!isParentedForestNode(n), 'can not attach node that already has a parent');\n\t\t\t\tconst breakVal: { value: ParentedForestNode } = {\n\t\t\t\t\tvalue: {\n\t\t\t\t\t\t...n,\n\t\t\t\t\t\tparentId,\n\t\t\t\t\t\ttraitParent: label,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\treturn breakVal;\n\t\t\t});\n\t\t}\n\n\t\treturn new Forest({\n\t\t\tnodes: mutableNodes,\n\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t});\n\t}\n\n\t/**\n\t * Detaches a range of nodes from their parent. The detached nodes remain in the `Forest`.\n\t * @param parentId - the id of the parent from which to detach the nodes\n\t * @param label - the label of the trait from which to detach the nodes\n\t * @param startIndex - the index of the first node in the range to detach\n\t * @param endIndex - the index after the last node in the range to detach\n\t * @returns a new `Forest` with the nodes detached, and a list of the ids of the nodes that were detached\n\t */\n\tpublic detachRangeOfChildren(\n\t\tparentId: NodeId,\n\t\tlabel: TraitLabel,\n\t\tstartIndex: number,\n\t\tendIndex: number\n\t): { forest: Forest; detached: readonly NodeId[] } {\n\t\tassert(startIndex >= 0 && endIndex >= startIndex, 'invalid detach index range');\n\t\tconst parentNode = this.nodes.get(parentId);\n\t\tassert(parentNode, 'can not detach children under node that does not exist');\n\t\tif (startIndex === endIndex) {\n\t\t\treturn { forest: this, detached: [] };\n\t\t}\n\n\t\tconst mutableNodes = this.nodes.clone();\n\t\tconst traits = new Map(parentNode.traits);\n\t\tconst trait = traits.get(label) ?? [];\n\t\tassert(endIndex <= trait.length, 'invalid detach index range');\n\t\tconst detached: NodeId[] = trait.slice(startIndex, endIndex);\n\t\tconst newChildren = [...trait.slice(0, startIndex), ...trait.slice(endIndex)];\n\t\tconst deleteTrait = newChildren.length === 0;\n\t\tif (deleteTrait) {\n\t\t\ttraits.delete(label);\n\t\t} else {\n\t\t\ttraits.set(label, newChildren);\n\t\t}\n\n\t\tmutableNodes.set(parentId, { ...parentNode, traits });\n\t\tfor (const childId of detached) {\n\t\t\tmutableNodes.editRange(childId, childId, true, (_, n) => {\n\t\t\t\tconst breakVal: { value: ForestNode } = {\n\t\t\t\t\tvalue: {\n\t\t\t\t\t\tdefinition: n.definition,\n\t\t\t\t\t\tidentifier: n.identifier,\n\t\t\t\t\t\ttraits: n.traits,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tcopyPropertyIfDefined(n, breakVal.value, 'payload');\n\t\t\t\treturn breakVal;\n\t\t\t});\n\t\t}\n\n\t\treturn {\n\t\t\tforest: new Forest({\n\t\t\t\tnodes: mutableNodes,\n\t\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t\t}),\n\t\t\tdetached,\n\t\t};\n\t}\n\n\t/**\n\t * Replaces a node's value. The node must exist in this `Forest`.\n\t * @param nodeId - the id of the node\n\t * @param value - the new value\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic setValue(nodeId: NodeId, value: Payload | null): Forest {\n\t\tconst node = this.nodes.get(nodeId);\n\t\tassert(node, 'can not replace payload for node that does not exist');\n\t\tconst mutableNodes = this.nodes.clone();\n\t\tconst newNode = { ...node };\n\t\tif (value !== null) {\n\t\t\tnewNode.payload = value;\n\t\t} else {\n\t\t\tdelete newNode.payload;\n\t\t}\n\t\tmutableNodes.set(nodeId, newNode);\n\t\treturn new Forest({\n\t\t\tnodes: mutableNodes,\n\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t});\n\t}\n\n\t/**\n\t * @returns true if the node associated with `id` exists in this forest, otherwise false\n\t */\n\tpublic has(id: NodeId): boolean {\n\t\treturn this.nodes.has(id);\n\t}\n\n\t/**\n\t * @returns the node associated with `id`. Should not be used if there is no node with the provided id.\n\t */\n\tpublic get(id: NodeId): ForestNode {\n\t\treturn this.nodes.get(id) ?? fail('NodeId not found');\n\t}\n\n\t/**\n\t * @returns the node associated with `id`, or undefined if there is none\n\t */\n\tpublic tryGet(id: NodeId): ForestNode | undefined {\n\t\treturn this.nodes.get(id);\n\t}\n\n\t/**\n\t * Deletes every node in ids (each of which must be unparented)\n\t * @param ids - The IDs of the nodes to delete.\n\t * @param deleteChildren - If true, recursively deletes descendants. Otherwise, leaves children unparented.\n\t */\n\tpublic delete(ids: Iterable<NodeId>, deleteChildren: boolean): Forest {\n\t\tconst mutableNodes = this.nodes.clone();\n\t\tfor (const id of ids) {\n\t\t\tthis.deleteRecursive(mutableNodes, id, deleteChildren);\n\t\t}\n\n\t\treturn new Forest({\n\t\t\tnodes: mutableNodes,\n\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t});\n\t}\n\n\tprivate deleteRecursive(mutableNodes: BTree<NodeId, ForestNode>, id: NodeId, deleteChildren: boolean): void {\n\t\tconst node = mutableNodes.get(id) ?? fail('node to delete must exist');\n\t\tassert(!isParentedForestNode(node), 'deleted nodes must be unparented');\n\t\tmutableNodes.delete(id);\n\t\tfor (const trait of node.traits.values()) {\n\t\t\tfor (const childId of trait) {\n\t\t\t\tmutableNodes.editRange(childId, childId, true, (_, n) => {\n\t\t\t\t\tconst breakVal: { value: ForestNode } = {\n\t\t\t\t\t\tvalue: {\n\t\t\t\t\t\t\tdefinition: n.definition,\n\t\t\t\t\t\t\tidentifier: n.identifier,\n\t\t\t\t\t\t\ttraits: n.traits,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tcopyPropertyIfDefined(n, breakVal.value, 'payload');\n\t\t\t\t\treturn breakVal;\n\t\t\t\t});\n\n\t\t\t\tif (deleteChildren) {\n\t\t\t\t\tthis.deleteRecursive(mutableNodes, childId, deleteChildren);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks that the metadata is correct, and the items form a forest.\n\t * This is an expensive O(map size) operation.\n\t */\n\tpublic assertConsistent(): void {\n\t\tconst checkedChildren = new Set<NodeId>([]);\n\t\tfor (const [nodeId, node] of this.nodes.entries(undefined, [])) {\n\t\t\tif (isParentedForestNode(node)) {\n\t\t\t\tconst parent = this.get(node.parentId);\n\t\t\t\tconst trait = parent.traits.get(node.traitParent);\n\t\t\t\tassert(trait !== undefined);\n\t\t\t\tassert(trait.indexOf(node.identifier) >= 0, 'node is parented incorrectly');\n\t\t\t}\n\n\t\t\tfor (const trait of node.traits.values()) {\n\t\t\t\tassert(trait.length > 0, 'trait is present but empty');\n\t\t\t\tfor (const childId of trait) {\n\t\t\t\t\tconst child = this.nodes.get(childId);\n\t\t\t\t\tassert(child, 'child in trait is not in forest');\n\t\t\t\t\tassert(isParentedForestNode(child), 'child is not parented');\n\t\t\t\t\tassert(child.parentId === node.identifier, 'child parent pointer is incorrect');\n\t\t\t\t\tassert(\n\t\t\t\t\t\t!checkedChildren.has(childId),\n\t\t\t\t\t\t'the item tree tree must not contain cycles or multi-parented nodes'\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\t(child.parentId ?? fail('each node must have associated metadata')) === nodeId,\n\t\t\t\t\t\t'cached parent is incorrect'\n\t\t\t\t\t);\n\t\t\t\t\tcheckedChildren.add(childId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * @returns the parent of `id`. Should not be used if there is no node with id or if id refers to the root node.\n\t */\n\tpublic getParent(id: NodeId): ParentData {\n\t\tconst child = this.nodes.get(id);\n\t\tif (child === undefined) {\n\t\t\tfail('NodeId not found');\n\t\t}\n\n\t\tassert(isParentedForestNode(child), 'Node is not parented');\n\t\treturn { parentId: child.parentId, traitParent: child.traitParent };\n\t}\n\n\t/**\n\t * @returns undefined iff root, otherwise the parent of `id`.\n\t */\n\tpublic tryGetParent(id: NodeId): ParentData | undefined {\n\t\tconst child = this.nodes.get(id);\n\t\tif (child === undefined || !isParentedForestNode(child)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tparentId: child.parentId,\n\t\t\ttraitParent: child.traitParent,\n\t\t};\n\t}\n\n\t/**\n\t * Compares two forests for equality.\n\t * @param forest - the other forest to compare to this one\n\t * @param comparator - a function which returns true if two objects of type ForestNode are equivalent, false otherwise\n\t * @returns true iff the forests are equal.\n\t */\n\tpublic equals(forest: Forest): boolean {\n\t\tif (this === forest || this.nodes === forest.nodes) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (forest.size !== this.size) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn compareBtrees(this.nodes, forest.nodes, compareForestNodes);\n\t}\n\n\t/**\n\t * Calculate the difference between two forests.\n\t * @param forest - the other forest to compare to this one\n\t * @param comparator - a function which returns true if two objects of type ForestNode are equivalent, false otherwise\n\t * @returns A {@link Delta} listing which nodes must be changed, added, and removed to get from `this` to `forest`.\n\t */\n\tpublic delta(forest: Forest): Delta<NodeId> {\n\t\tconst changed: NodeId[] = [];\n\t\tconst removed: NodeId[] = [];\n\t\tconst added: NodeId[] = [];\n\t\tthis.nodes.diffAgainst(\n\t\t\tforest.nodes,\n\t\t\t(id) => {\n\t\t\t\tremoved.push(id);\n\t\t\t},\n\t\t\t(id) => {\n\t\t\t\tadded.push(id);\n\t\t\t},\n\t\t\t(id, nodeThis, nodeOther) => {\n\t\t\t\tif (!compareForestNodes(nodeThis, nodeOther)) {\n\t\t\t\t\tchanged.push(id);\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t\treturn {\n\t\t\tchanged,\n\t\t\tadded,\n\t\t\tremoved,\n\t\t};\n\t}\n}\n\n/**\n * @returns true iff two `ForestNodes` are equivalent.\n * May return false for nodes they contain equivalent payloads encoded differently.\n */\nexport function compareForestNodes(nodeA: ForestNode, nodeB: ForestNode): boolean {\n\tif (nodeA === nodeB) {\n\t\treturn true;\n\t}\n\n\tif (nodeA.identifier !== nodeB.identifier) {\n\t\treturn false;\n\t}\n\n\tif (nodeA.definition !== nodeB.definition) {\n\t\treturn false;\n\t}\n\n\tif (!comparePayloads(nodeA.payload, nodeB.payload)) {\n\t\treturn false;\n\t}\n\n\tif (nodeA.traits.size !== nodeB.traits.size) {\n\t\treturn false;\n\t}\n\n\tfor (const traitA of nodeA.traits) {\n\t\tconst [traitLabelA, nodeSequenceA] = traitA;\n\t\tconst nodeSequenceB = nodeB.traits.get(traitLabelA);\n\t\tif (!nodeSequenceB) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (nodeSequenceA.length !== nodeSequenceB.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (let i = 0; i < nodeSequenceA.length; i++) {\n\t\t\tif (nodeSequenceA[i] !== nodeSequenceB[i]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n}\n"]}
|