@fluidframework/tree 2.32.0 → 2.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +53 -0
- package/api-report/tree.alpha.api.md +169 -192
- package/api-report/tree.beta.api.md +135 -164
- package/api-report/tree.legacy.alpha.api.md +138 -167
- package/api-report/tree.legacy.public.api.md +135 -164
- package/api-report/tree.public.api.md +135 -164
- package/dist/alpha.d.ts +3 -11
- package/dist/beta.d.ts +2 -11
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/schema-stored/index.d.ts +1 -1
- package/dist/core/schema-stored/index.d.ts.map +1 -1
- package/dist/core/schema-stored/index.js +1 -2
- package/dist/core/schema-stored/index.js.map +1 -1
- package/dist/core/schema-stored/schema.d.ts +4 -11
- package/dist/core/schema-stored/schema.d.ts.map +1 -1
- package/dist/core/schema-stored/schema.js +7 -14
- package/dist/core/schema-stored/schema.js.map +1 -1
- package/dist/core/tree/anchorSet.d.ts.map +1 -1
- package/dist/core/tree/anchorSet.js +31 -24
- package/dist/core/tree/anchorSet.js.map +1 -1
- package/dist/core/tree/deltaUtil.d.ts +1 -4
- package/dist/core/tree/deltaUtil.d.ts.map +1 -1
- package/dist/core/tree/deltaUtil.js +1 -13
- package/dist/core/tree/deltaUtil.js.map +1 -1
- package/dist/core/tree/visitDelta.d.ts +6 -29
- package/dist/core/tree/visitDelta.d.ts.map +1 -1
- package/dist/core/tree/visitDelta.js +11 -50
- package/dist/core/tree/visitDelta.js.map +1 -1
- package/dist/core/tree/visitorUtils.d.ts +12 -9
- package/dist/core/tree/visitorUtils.d.ts.map +1 -1
- package/dist/core/tree/visitorUtils.js +19 -32
- package/dist/core/tree/visitorUtils.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/chunkedForest.js +6 -11
- package/dist/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/compressedEncode.d.ts +1 -1
- package/dist/feature-libraries/chunked-forest/codec/compressedEncode.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/compressedEncode.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/nodeShape.d.ts +41 -5
- package/dist/feature-libraries/chunked-forest/codec/nodeShape.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/nodeShape.js +43 -26
- package/dist/feature-libraries/chunked-forest/codec/nodeShape.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/schemaBasedEncode.js +1 -1
- package/dist/feature-libraries/chunked-forest/codec/schemaBasedEncode.js.map +1 -1
- package/dist/feature-libraries/flex-tree/context.d.ts +5 -0
- package/dist/feature-libraries/flex-tree/context.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/context.js +4 -0
- package/dist/feature-libraries/flex-tree/context.js.map +1 -1
- package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts +8 -0
- package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/flexTreeTypes.js +8 -0
- package/dist/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
- package/dist/feature-libraries/indexing/anchorTreeIndex.d.ts.map +1 -1
- package/dist/feature-libraries/indexing/anchorTreeIndex.js +15 -22
- package/dist/feature-libraries/indexing/anchorTreeIndex.js.map +1 -1
- package/dist/feature-libraries/node-identifier/nodeIdentifierManager.d.ts.map +1 -1
- package/dist/feature-libraries/node-identifier/nodeIdentifierManager.js +29 -25
- package/dist/feature-libraries/node-identifier/nodeIdentifierManager.js.map +1 -1
- package/dist/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
- package/dist/feature-libraries/object-forest/objectForest.js +1 -7
- package/dist/feature-libraries/object-forest/objectForest.js.map +1 -1
- package/dist/feature-libraries/schema-index/codec.d.ts.map +1 -1
- package/dist/feature-libraries/schema-index/codec.js +1 -1
- package/dist/feature-libraries/schema-index/codec.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/internalTypes.d.ts +1 -1
- package/dist/internalTypes.d.ts.map +1 -1
- package/dist/internalTypes.js.map +1 -1
- package/dist/jsonDomainSchema.d.ts +6 -6
- package/dist/jsonDomainSchema.d.ts.map +1 -1
- package/dist/jsonDomainSchema.js.map +1 -1
- package/dist/legacy.d.ts +2 -11
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/public.d.ts +2 -11
- package/dist/serializableDomainSchema.d.ts +5 -5
- package/dist/shared-tree/checkoutFlexTreeView.d.ts +1 -0
- package/dist/shared-tree/checkoutFlexTreeView.d.ts.map +1 -1
- package/dist/shared-tree/checkoutFlexTreeView.js +4 -0
- package/dist/shared-tree/checkoutFlexTreeView.js.map +1 -1
- package/dist/shared-tree/index.d.ts +3 -2
- package/dist/shared-tree/index.d.ts.map +1 -1
- package/dist/shared-tree/index.js +2 -2
- package/dist/shared-tree/index.js.map +1 -1
- package/dist/shared-tree/sharedTree.d.ts +4 -35
- package/dist/shared-tree/sharedTree.d.ts.map +1 -1
- package/dist/shared-tree/sharedTree.js +4 -54
- package/dist/shared-tree/sharedTree.js.map +1 -1
- package/dist/simple-tree/api/index.d.ts +2 -1
- package/dist/simple-tree/api/index.d.ts.map +1 -1
- package/dist/simple-tree/api/index.js +3 -1
- package/dist/simple-tree/api/index.js.map +1 -1
- package/dist/simple-tree/api/schemaFactory.d.ts +28 -28
- package/dist/simple-tree/api/schemaFactory.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaFactory.js +11 -11
- package/dist/simple-tree/api/schemaFactory.js.map +1 -1
- package/dist/simple-tree/api/schemaFactoryAlpha.d.ts +6 -7
- package/dist/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaFactoryAlpha.js.map +1 -1
- package/dist/simple-tree/api/schemaFactoryRecursive.d.ts +24 -5
- package/dist/simple-tree/api/schemaFactoryRecursive.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaFactoryRecursive.js +14 -1
- package/dist/simple-tree/api/schemaFactoryRecursive.js.map +1 -1
- package/dist/simple-tree/api/testRecursiveDomain.d.ts +10 -10
- package/dist/simple-tree/api/tree.d.ts +1 -14
- package/dist/simple-tree/api/tree.d.ts.map +1 -1
- package/dist/simple-tree/api/tree.js.map +1 -1
- package/dist/simple-tree/api/typesUnsafe.d.ts +237 -220
- package/dist/simple-tree/api/typesUnsafe.d.ts.map +1 -1
- package/dist/simple-tree/api/typesUnsafe.js.map +1 -1
- package/dist/simple-tree/arrayNode.d.ts +2 -2
- package/dist/simple-tree/arrayNode.d.ts.map +1 -1
- package/dist/simple-tree/arrayNode.js.map +1 -1
- package/dist/simple-tree/core/treeNodeKernel.d.ts +9 -2
- package/dist/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
- package/dist/simple-tree/core/treeNodeKernel.js +39 -24
- package/dist/simple-tree/core/treeNodeKernel.js.map +1 -1
- package/dist/simple-tree/core/types.d.ts +14 -4
- package/dist/simple-tree/core/types.d.ts.map +1 -1
- package/dist/simple-tree/core/types.js +14 -4
- package/dist/simple-tree/core/types.js.map +1 -1
- package/dist/simple-tree/core/unhydratedFlexTree.d.ts +2 -1
- package/dist/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
- package/dist/simple-tree/core/unhydratedFlexTree.js +3 -0
- package/dist/simple-tree/core/unhydratedFlexTree.js.map +1 -1
- package/dist/simple-tree/index.d.ts +1 -1
- package/dist/simple-tree/index.d.ts.map +1 -1
- package/dist/simple-tree/index.js +3 -2
- package/dist/simple-tree/index.js.map +1 -1
- package/dist/simple-tree/objectNode.d.ts +9 -2
- package/dist/simple-tree/objectNode.d.ts.map +1 -1
- package/dist/simple-tree/objectNode.js +3 -0
- package/dist/simple-tree/objectNode.js.map +1 -1
- package/dist/simple-tree/schemaTypes.d.ts +10 -5
- package/dist/simple-tree/schemaTypes.d.ts.map +1 -1
- package/dist/simple-tree/schemaTypes.js +5 -2
- package/dist/simple-tree/schemaTypes.js.map +1 -1
- package/dist/tableSchema.d.ts +78 -26
- package/dist/tableSchema.d.ts.map +1 -1
- package/dist/tableSchema.js +53 -24
- package/dist/tableSchema.js.map +1 -1
- package/dist/treeFactory.d.ts +6 -12
- package/dist/treeFactory.d.ts.map +1 -1
- package/dist/treeFactory.js +56 -5
- package/dist/treeFactory.js.map +1 -1
- package/lib/alpha.d.ts +3 -11
- package/lib/beta.d.ts +2 -11
- package/lib/core/index.d.ts +1 -1
- package/lib/core/index.d.ts.map +1 -1
- package/lib/core/index.js +1 -1
- package/lib/core/index.js.map +1 -1
- package/lib/core/schema-stored/index.d.ts +1 -1
- package/lib/core/schema-stored/index.d.ts.map +1 -1
- package/lib/core/schema-stored/index.js +1 -1
- package/lib/core/schema-stored/index.js.map +1 -1
- package/lib/core/schema-stored/schema.d.ts +4 -11
- package/lib/core/schema-stored/schema.d.ts.map +1 -1
- package/lib/core/schema-stored/schema.js +6 -12
- package/lib/core/schema-stored/schema.js.map +1 -1
- package/lib/core/tree/anchorSet.d.ts.map +1 -1
- package/lib/core/tree/anchorSet.js +31 -24
- package/lib/core/tree/anchorSet.js.map +1 -1
- package/lib/core/tree/deltaUtil.d.ts +1 -4
- package/lib/core/tree/deltaUtil.d.ts.map +1 -1
- package/lib/core/tree/deltaUtil.js +0 -9
- package/lib/core/tree/deltaUtil.js.map +1 -1
- package/lib/core/tree/visitDelta.d.ts +6 -29
- package/lib/core/tree/visitDelta.d.ts.map +1 -1
- package/lib/core/tree/visitDelta.js +12 -51
- package/lib/core/tree/visitDelta.js.map +1 -1
- package/lib/core/tree/visitorUtils.d.ts +12 -9
- package/lib/core/tree/visitorUtils.d.ts.map +1 -1
- package/lib/core/tree/visitorUtils.js +19 -32
- package/lib/core/tree/visitorUtils.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/chunkedForest.js +6 -11
- package/lib/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/compressedEncode.d.ts +1 -1
- package/lib/feature-libraries/chunked-forest/codec/compressedEncode.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/compressedEncode.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/nodeShape.d.ts +41 -5
- package/lib/feature-libraries/chunked-forest/codec/nodeShape.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/nodeShape.js +43 -26
- package/lib/feature-libraries/chunked-forest/codec/nodeShape.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/schemaBasedEncode.js +1 -1
- package/lib/feature-libraries/chunked-forest/codec/schemaBasedEncode.js.map +1 -1
- package/lib/feature-libraries/flex-tree/context.d.ts +5 -0
- package/lib/feature-libraries/flex-tree/context.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/context.js +5 -1
- package/lib/feature-libraries/flex-tree/context.js.map +1 -1
- package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts +8 -0
- package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/flexTreeTypes.js +8 -0
- package/lib/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
- package/lib/feature-libraries/indexing/anchorTreeIndex.d.ts.map +1 -1
- package/lib/feature-libraries/indexing/anchorTreeIndex.js +15 -22
- package/lib/feature-libraries/indexing/anchorTreeIndex.js.map +1 -1
- package/lib/feature-libraries/node-identifier/nodeIdentifierManager.d.ts.map +1 -1
- package/lib/feature-libraries/node-identifier/nodeIdentifierManager.js +28 -24
- package/lib/feature-libraries/node-identifier/nodeIdentifierManager.js.map +1 -1
- package/lib/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
- package/lib/feature-libraries/object-forest/objectForest.js +1 -7
- package/lib/feature-libraries/object-forest/objectForest.js.map +1 -1
- package/lib/feature-libraries/schema-index/codec.d.ts.map +1 -1
- package/lib/feature-libraries/schema-index/codec.js +2 -2
- package/lib/feature-libraries/schema-index/codec.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/internalTypes.d.ts +1 -1
- package/lib/internalTypes.d.ts.map +1 -1
- package/lib/internalTypes.js.map +1 -1
- package/lib/jsonDomainSchema.d.ts +6 -6
- package/lib/jsonDomainSchema.d.ts.map +1 -1
- package/lib/jsonDomainSchema.js.map +1 -1
- package/lib/legacy.d.ts +2 -11
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/public.d.ts +2 -11
- package/lib/serializableDomainSchema.d.ts +5 -5
- package/lib/shared-tree/checkoutFlexTreeView.d.ts +1 -0
- package/lib/shared-tree/checkoutFlexTreeView.d.ts.map +1 -1
- package/lib/shared-tree/checkoutFlexTreeView.js +4 -0
- package/lib/shared-tree/checkoutFlexTreeView.js.map +1 -1
- package/lib/shared-tree/index.d.ts +3 -2
- package/lib/shared-tree/index.d.ts.map +1 -1
- package/lib/shared-tree/index.js +1 -1
- package/lib/shared-tree/index.js.map +1 -1
- package/lib/shared-tree/sharedTree.d.ts +4 -35
- package/lib/shared-tree/sharedTree.d.ts.map +1 -1
- package/lib/shared-tree/sharedTree.js +2 -51
- package/lib/shared-tree/sharedTree.js.map +1 -1
- package/lib/simple-tree/api/index.d.ts +2 -1
- package/lib/simple-tree/api/index.d.ts.map +1 -1
- package/lib/simple-tree/api/index.js +1 -0
- package/lib/simple-tree/api/index.js.map +1 -1
- package/lib/simple-tree/api/schemaFactory.d.ts +28 -28
- package/lib/simple-tree/api/schemaFactory.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaFactory.js +11 -11
- package/lib/simple-tree/api/schemaFactory.js.map +1 -1
- package/lib/simple-tree/api/schemaFactoryAlpha.d.ts +6 -7
- package/lib/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaFactoryAlpha.js.map +1 -1
- package/lib/simple-tree/api/schemaFactoryRecursive.d.ts +24 -5
- package/lib/simple-tree/api/schemaFactoryRecursive.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaFactoryRecursive.js +12 -0
- package/lib/simple-tree/api/schemaFactoryRecursive.js.map +1 -1
- package/lib/simple-tree/api/testRecursiveDomain.d.ts +10 -10
- package/lib/simple-tree/api/tree.d.ts +1 -14
- package/lib/simple-tree/api/tree.d.ts.map +1 -1
- package/lib/simple-tree/api/tree.js.map +1 -1
- package/lib/simple-tree/api/typesUnsafe.d.ts +237 -220
- package/lib/simple-tree/api/typesUnsafe.d.ts.map +1 -1
- package/lib/simple-tree/api/typesUnsafe.js.map +1 -1
- package/lib/simple-tree/arrayNode.d.ts +2 -2
- package/lib/simple-tree/arrayNode.d.ts.map +1 -1
- package/lib/simple-tree/arrayNode.js.map +1 -1
- package/lib/simple-tree/core/treeNodeKernel.d.ts +9 -2
- package/lib/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
- package/lib/simple-tree/core/treeNodeKernel.js +40 -25
- package/lib/simple-tree/core/treeNodeKernel.js.map +1 -1
- package/lib/simple-tree/core/types.d.ts +14 -4
- package/lib/simple-tree/core/types.d.ts.map +1 -1
- package/lib/simple-tree/core/types.js +14 -4
- package/lib/simple-tree/core/types.js.map +1 -1
- package/lib/simple-tree/core/unhydratedFlexTree.d.ts +2 -1
- package/lib/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
- package/lib/simple-tree/core/unhydratedFlexTree.js +3 -0
- package/lib/simple-tree/core/unhydratedFlexTree.js.map +1 -1
- package/lib/simple-tree/index.d.ts +1 -1
- package/lib/simple-tree/index.d.ts.map +1 -1
- package/lib/simple-tree/index.js +1 -1
- package/lib/simple-tree/index.js.map +1 -1
- package/lib/simple-tree/objectNode.d.ts +9 -2
- package/lib/simple-tree/objectNode.d.ts.map +1 -1
- package/lib/simple-tree/objectNode.js +4 -1
- package/lib/simple-tree/objectNode.js.map +1 -1
- package/lib/simple-tree/schemaTypes.d.ts +10 -5
- package/lib/simple-tree/schemaTypes.d.ts.map +1 -1
- package/lib/simple-tree/schemaTypes.js +5 -2
- package/lib/simple-tree/schemaTypes.js.map +1 -1
- package/lib/tableSchema.d.ts +78 -26
- package/lib/tableSchema.d.ts.map +1 -1
- package/lib/tableSchema.js +53 -24
- package/lib/tableSchema.js.map +1 -1
- package/lib/treeFactory.d.ts +6 -12
- package/lib/treeFactory.d.ts.map +1 -1
- package/lib/treeFactory.js +55 -3
- package/lib/treeFactory.js.map +1 -1
- package/lib/tsdoc-metadata.json +1 -1
- package/package.json +22 -23
- package/src/core/index.ts +0 -2
- package/src/core/schema-stored/index.ts +0 -2
- package/src/core/schema-stored/schema.ts +10 -29
- package/src/core/tree/anchorSet.ts +32 -24
- package/src/core/tree/deltaUtil.ts +1 -13
- package/src/core/tree/visitDelta.ts +24 -81
- package/src/core/tree/visitorUtils.ts +43 -53
- package/src/feature-libraries/chunked-forest/chunkedForest.ts +7 -22
- package/src/feature-libraries/chunked-forest/codec/compressedEncode.ts +1 -1
- package/src/feature-libraries/chunked-forest/codec/nodeShape.ts +45 -27
- package/src/feature-libraries/chunked-forest/codec/schemaBasedEncode.ts +1 -1
- package/src/feature-libraries/flex-tree/context.ts +11 -1
- package/src/feature-libraries/flex-tree/flexTreeTypes.ts +8 -0
- package/src/feature-libraries/indexing/anchorTreeIndex.ts +17 -28
- package/src/feature-libraries/node-identifier/nodeIdentifierManager.ts +39 -38
- package/src/feature-libraries/object-forest/objectForest.ts +1 -18
- package/src/feature-libraries/schema-index/codec.ts +1 -2
- package/src/index.ts +3 -11
- package/src/internalTypes.ts +0 -19
- package/src/jsonDomainSchema.ts +1 -3
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/checkoutFlexTreeView.ts +6 -0
- package/src/shared-tree/index.ts +8 -3
- package/src/shared-tree/sharedTree.ts +5 -133
- package/src/simple-tree/api/index.ts +2 -22
- package/src/simple-tree/api/schemaFactory.ts +40 -54
- package/src/simple-tree/api/schemaFactoryAlpha.ts +9 -14
- package/src/simple-tree/api/schemaFactoryRecursive.ts +25 -5
- package/src/simple-tree/api/tree.ts +1 -14
- package/src/simple-tree/api/typesUnsafe.ts +359 -341
- package/src/simple-tree/arrayNode.ts +2 -2
- package/src/simple-tree/core/treeNodeKernel.ts +46 -28
- package/src/simple-tree/core/types.ts +14 -4
- package/src/simple-tree/core/unhydratedFlexTree.ts +5 -1
- package/src/simple-tree/index.ts +2 -22
- package/src/simple-tree/objectNode.ts +13 -4
- package/src/simple-tree/schemaTypes.ts +11 -7
- package/src/tableSchema.ts +190 -63
- package/src/treeFactory.ts +151 -8
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { fail } from "@fluidframework/core-utils/internal";
|
|
7
|
-
import type { ErasedType } from "@fluidframework/core-interfaces";
|
|
8
7
|
import { DiscriminatedUnionDispatcher } from "../../codec/index.js";
|
|
9
8
|
import { type MakeNominal, brand, invertMap } from "../../util/index.js";
|
|
10
9
|
import {
|
|
@@ -148,24 +147,6 @@ export const storedEmptyFieldSchema: TreeFieldStoredSchema = {
|
|
|
148
147
|
*/
|
|
149
148
|
export const identifierFieldKindIdentifier = "Identifier";
|
|
150
149
|
|
|
151
|
-
/**
|
|
152
|
-
* Opaque type erased handle to the encoded representation of the contents of a stored schema.
|
|
153
|
-
*/
|
|
154
|
-
export interface ErasedTreeNodeSchemaDataFormat
|
|
155
|
-
extends ErasedType<"TreeNodeSchemaDataFormat"> {}
|
|
156
|
-
|
|
157
|
-
function toErasedTreeNodeSchemaDataFormat(
|
|
158
|
-
data: TreeNodeSchemaDataFormat,
|
|
159
|
-
): ErasedTreeNodeSchemaDataFormat {
|
|
160
|
-
return data as unknown as ErasedTreeNodeSchemaDataFormat;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
export function toTreeNodeSchemaDataFormat(
|
|
164
|
-
data: ErasedTreeNodeSchemaDataFormat,
|
|
165
|
-
): TreeNodeSchemaDataFormat {
|
|
166
|
-
return data as unknown as TreeNodeSchemaDataFormat;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
150
|
/**
|
|
170
151
|
*/
|
|
171
152
|
export abstract class TreeNodeStoredSchema {
|
|
@@ -177,7 +158,7 @@ export abstract class TreeNodeStoredSchema {
|
|
|
177
158
|
* This is uses an opaque type to avoid leaking these types out of the package,
|
|
178
159
|
* and is runtime validated by the codec.
|
|
179
160
|
*/
|
|
180
|
-
public abstract encode():
|
|
161
|
+
public abstract encode(): TreeNodeSchemaDataFormat;
|
|
181
162
|
|
|
182
163
|
/**
|
|
183
164
|
* Returns the schema for the provided field.
|
|
@@ -202,7 +183,7 @@ export class ObjectNodeStoredSchema extends TreeNodeStoredSchema {
|
|
|
202
183
|
super();
|
|
203
184
|
}
|
|
204
185
|
|
|
205
|
-
public override encode():
|
|
186
|
+
public override encode(): TreeNodeSchemaDataFormat {
|
|
206
187
|
const fieldsObject: Record<string, FieldSchemaFormat> = Object.create(null);
|
|
207
188
|
// Sort fields to ensure output is identical for for equivalent schema (since field order is not considered significant).
|
|
208
189
|
// This makes comparing schema easier, and ensures chunk reuse for schema summaries isn't needlessly broken.
|
|
@@ -216,9 +197,9 @@ export class ObjectNodeStoredSchema extends TreeNodeStoredSchema {
|
|
|
216
197
|
),
|
|
217
198
|
});
|
|
218
199
|
}
|
|
219
|
-
return
|
|
200
|
+
return {
|
|
220
201
|
object: fieldsObject,
|
|
221
|
-
}
|
|
202
|
+
};
|
|
222
203
|
}
|
|
223
204
|
|
|
224
205
|
public override getFieldSchema(field: FieldKey): TreeFieldStoredSchema {
|
|
@@ -241,10 +222,10 @@ export class MapNodeStoredSchema extends TreeNodeStoredSchema {
|
|
|
241
222
|
super();
|
|
242
223
|
}
|
|
243
224
|
|
|
244
|
-
public override encode():
|
|
245
|
-
return
|
|
225
|
+
public override encode(): TreeNodeSchemaDataFormat {
|
|
226
|
+
return {
|
|
246
227
|
map: encodeFieldSchema(this.mapFields),
|
|
247
|
-
}
|
|
228
|
+
};
|
|
248
229
|
}
|
|
249
230
|
|
|
250
231
|
public override getFieldSchema(field: FieldKey): TreeFieldStoredSchema {
|
|
@@ -271,10 +252,10 @@ export class LeafNodeStoredSchema extends TreeNodeStoredSchema {
|
|
|
271
252
|
super();
|
|
272
253
|
}
|
|
273
254
|
|
|
274
|
-
public override encode():
|
|
275
|
-
return
|
|
255
|
+
public override encode(): TreeNodeSchemaDataFormat {
|
|
256
|
+
return {
|
|
276
257
|
leaf: encodeValueSchema(this.leafValue),
|
|
277
|
-
}
|
|
258
|
+
};
|
|
278
259
|
}
|
|
279
260
|
|
|
280
261
|
public override getFieldSchema(field: FieldKey): TreeFieldStoredSchema {
|
|
@@ -730,25 +730,32 @@ export class AnchorSet implements AnchorLocator {
|
|
|
730
730
|
*/
|
|
731
731
|
bufferedEvents: [] as BufferedEvent[],
|
|
732
732
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
733
|
+
/**
|
|
734
|
+
* 'currentDepth' and 'depthThresholdForSubtreeChanged' serve to keep track of when do we need to emit
|
|
735
|
+
* subtreeChangedAfterBatch events.
|
|
736
|
+
* The algorithm works as follows:
|
|
737
|
+
*
|
|
738
|
+
* - Initialize both to 0.
|
|
739
|
+
* - As we walk the tree from the root towards the leaves, when we enter a node increment currentDepth by 1.
|
|
740
|
+
* - When we edit a node, set depthThresholdForSubtreeChanged = currentDepth.
|
|
741
|
+
* Intuitively, depthThresholdForSubtreeChanged means "as you walk the tree towards the root, when you exit a
|
|
742
|
+
* node at this depth you should emit a subtreeChangedAfterBatch event".
|
|
743
|
+
* - When we exit a node, if d === currentDepth then emit a subtreeChangedAfterBatch and decrement d by 1.
|
|
744
|
+
* Then decrement currentDepth unconditionally.
|
|
745
|
+
*
|
|
746
|
+
* Note that the event will be emitted when exiting a node that was edited (depthThresholdForSubtreeChanged will
|
|
747
|
+
* have been set to the current depth when the edit happened), it will be emitted when exiting a node that is the
|
|
748
|
+
* parent of a node that already emitted the event (because both depthThresholdForSubtreeChanged and currentDepth
|
|
749
|
+
* get decremented when exiting a node so they stay in sync), and if we're already emitting the event but start
|
|
750
|
+
* walking the tree back towards the leaves in a path where no edits happen, currentDepth will be increased again
|
|
751
|
+
* as we walk that path, depthThresholdForSubtreeChanged will not, and thus no event will be emitted when walking
|
|
752
|
+
* back up that path, until we get back to the depth where we were already emitting the event, and will continue
|
|
753
|
+
* emitting it on the way to the root.
|
|
754
|
+
*/
|
|
751
755
|
currentDepth: 0,
|
|
756
|
+
/**
|
|
757
|
+
* See {@link visitor.currentDepth}.
|
|
758
|
+
*/
|
|
752
759
|
depthThresholdForSubtreeChanged: 0,
|
|
753
760
|
|
|
754
761
|
free() {
|
|
@@ -909,16 +916,17 @@ export class AnchorSet implements AnchorLocator {
|
|
|
909
916
|
},
|
|
910
917
|
exitNode(index: number): void {
|
|
911
918
|
assert(this.parent !== undefined, 0x3ac /* Must have parent node */);
|
|
912
|
-
this.
|
|
913
|
-
|
|
914
|
-
|
|
919
|
+
if (this.depthThresholdForSubtreeChanged === this.currentDepth) {
|
|
920
|
+
this.maybeWithNode((p) => {
|
|
921
|
+
p.events.emit("subtreeChanged", p);
|
|
922
|
+
|
|
915
923
|
this.bufferedEvents.push({
|
|
916
924
|
node: p,
|
|
917
925
|
event: "subtreeChangedAfterBatch",
|
|
918
926
|
});
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
}
|
|
927
|
+
});
|
|
928
|
+
this.depthThresholdForSubtreeChanged--;
|
|
929
|
+
}
|
|
922
930
|
const parent = this.parent;
|
|
923
931
|
this.parentField = parent.parentField;
|
|
924
932
|
this.parent = parent.parent;
|
|
@@ -7,23 +7,11 @@ import type { Mutable } from "../../util/index.js";
|
|
|
7
7
|
import type { FieldKey } from "../schema-stored/index.js";
|
|
8
8
|
import type { TreeChunk } from "./chunk.js";
|
|
9
9
|
|
|
10
|
-
import type { DetachedNodeId, FieldChanges,
|
|
10
|
+
import type { DetachedNodeId, FieldChanges, Root } from "./delta.js";
|
|
11
11
|
import { rootFieldKey } from "./types.js";
|
|
12
12
|
|
|
13
13
|
export const emptyDelta: Root = {};
|
|
14
14
|
|
|
15
|
-
export function isAttachMark(mark: Mark): boolean {
|
|
16
|
-
return mark.attach !== undefined && mark.detach === undefined;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function isDetachMark(mark: Mark): boolean {
|
|
20
|
-
return mark.detach !== undefined && mark.attach === undefined;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function isReplaceMark(mark: Mark): boolean {
|
|
24
|
-
return mark.detach !== undefined && mark.attach !== undefined;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
15
|
export function deltaForRootInitialization(content: TreeChunk): Root {
|
|
28
16
|
if (content.topLevelLength === 0) {
|
|
29
17
|
return emptyDelta;
|
|
@@ -10,13 +10,7 @@ import type { FieldKey } from "../schema-stored/index.js";
|
|
|
10
10
|
|
|
11
11
|
import { mapCursorField, type ITreeCursorSynchronous } from "./cursor.js";
|
|
12
12
|
import type * as Delta from "./delta.js";
|
|
13
|
-
import {
|
|
14
|
-
areDetachedNodeIdsEqual,
|
|
15
|
-
isAttachMark,
|
|
16
|
-
isDetachMark,
|
|
17
|
-
isReplaceMark,
|
|
18
|
-
offsetDetachId,
|
|
19
|
-
} from "./deltaUtil.js";
|
|
13
|
+
import { areDetachedNodeIdsEqual, offsetDetachId } from "./deltaUtil.js";
|
|
20
14
|
import type { DetachedFieldIndex } from "./detachedFieldIndex.js";
|
|
21
15
|
import type { ForestRootId, Major, Minor } from "./detachedFieldIndexTypes.js";
|
|
22
16
|
import type { NodeIndex, PlaceIndex, Range } from "./pathTree.js";
|
|
@@ -32,24 +26,11 @@ import type { RevisionTag, TreeChunk } from "../index.js";
|
|
|
32
26
|
* 4. root destructions
|
|
33
27
|
*
|
|
34
28
|
* The core idea is that before content can be attached, it must first exist and be in a detached field.
|
|
35
|
-
* The detach pass is therefore responsible for making sure that all roots that needs to be attached during the
|
|
36
|
-
* attach pass are detached.
|
|
37
|
-
* In practice, this means the detach pass must:
|
|
38
|
-
* - Create all subtrees that need to be created
|
|
39
|
-
* - Detach all moved nodes
|
|
40
|
-
*
|
|
41
|
-
* In addition to that, the detach pass also detaches nodes that need removing, with the exception of nodes that get
|
|
42
|
-
* replaced. The reason for this exception is that we need to be able to communicate replaces as atomic operations.
|
|
43
|
-
* In order to do that, we need to wait until we are sure that the content to attach is available as a detached root.
|
|
44
|
-
* Replaces are therefore handled during the attach pass.
|
|
45
|
-
* Note that this could theoretically lead to a situation where, in the attach pass, one replace wants to attach
|
|
46
|
-
* a node that has yet to be detached by another replace. This does not occur in practice because we do not support
|
|
47
|
-
* editing operations that would lead to this situation.
|
|
48
29
|
*
|
|
49
30
|
* While the detach pass ensures that nodes to be attached are in a detached state, it does not guarantee that they
|
|
50
|
-
* reside in the correct
|
|
31
|
+
* reside in the correct detached field. That is the responsibility of the root transfers phase.
|
|
51
32
|
*
|
|
52
|
-
* The attach phase carries out attaches
|
|
33
|
+
* The attach phase carries out attaches.
|
|
53
34
|
*
|
|
54
35
|
* After the attach phase, roots destruction is carried out.
|
|
55
36
|
* This needs to happen last to allow modifications to detached roots to be applied before they are destroyed.
|
|
@@ -57,9 +38,6 @@ import type { RevisionTag, TreeChunk } from "../index.js";
|
|
|
57
38
|
* The details of the delta visit algorithm can impact how/when events are emitted by the objects that own the visitors.
|
|
58
39
|
* For example, as of 2024-03-27, the subtreeChanged event of an AnchorNode is emitted when exiting a node during a
|
|
59
40
|
* delta visit, and thus the two-pass nature of the algorithm means the event fires twice for any given change.
|
|
60
|
-
* This two-pass nature also means that the event may fire at a time where no change is visible in the tree. E.g.,
|
|
61
|
-
* if a node is being replaced, when the event fires during the detach pass no change in the tree has happened so the
|
|
62
|
-
* listener won't see any; then when it fires during the attach pass, the change will be visible in the event listener.
|
|
63
41
|
*/
|
|
64
42
|
|
|
65
43
|
/**
|
|
@@ -233,7 +211,7 @@ function transferRoots(
|
|
|
233
211
|
const oldField = detachedFieldIndex.toFieldKey(oldRootId);
|
|
234
212
|
const newField = detachedFieldIndex.toFieldKey(newRootId);
|
|
235
213
|
visitor.enterField(oldField);
|
|
236
|
-
visitor.detach({ start: 0, end: 1 }, newField, newId);
|
|
214
|
+
visitor.detach({ start: 0, end: 1 }, newField, newId, false);
|
|
237
215
|
visitor.exitField(oldField);
|
|
238
216
|
detachedFieldIndex.deleteEntry(oldId);
|
|
239
217
|
}
|
|
@@ -285,22 +263,15 @@ export interface DeltaVisitor {
|
|
|
285
263
|
* @param destination - The key for a new detached field.
|
|
286
264
|
* A field with this key must not already exist.
|
|
287
265
|
* @param id - The ID assigned to the first detached node as a result of the detach. The other nodes in the detached range are assigned subsequent IDs.
|
|
266
|
+
* @param isReplaced - Whether the detached content will be replaced by a later attach.
|
|
267
|
+
* This is not guaranteed to be true in all cases where it could be true,
|
|
268
|
+
* but it is guaranteed to be true in all cases where a later attach is needed to keep the data compliant with the schema.
|
|
288
269
|
*/
|
|
289
|
-
detach(
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
* @param newContentSource - The detached field to transfer the new nodes from.
|
|
295
|
-
* @param range - The bounds of the range of nodes to replace.
|
|
296
|
-
* @param oldContentDestination - The key for a new detached field to transfer the old nodes to.
|
|
297
|
-
* @param oldContentId - The ID assigned to the first replaced node as a result of the replace. The other nodes in the replaced range are assigned subsequent IDs.
|
|
298
|
-
*/
|
|
299
|
-
replace(
|
|
300
|
-
newContentSource: FieldKey,
|
|
301
|
-
range: Range,
|
|
302
|
-
oldContentDestination: FieldKey,
|
|
303
|
-
oldContentId: Delta.DetachedNodeId,
|
|
270
|
+
detach(
|
|
271
|
+
source: Range,
|
|
272
|
+
destination: FieldKey,
|
|
273
|
+
id: Delta.DetachedNodeId,
|
|
274
|
+
isReplaced: boolean,
|
|
304
275
|
): void;
|
|
305
276
|
|
|
306
277
|
/**
|
|
@@ -417,13 +388,8 @@ function visitNode(
|
|
|
417
388
|
|
|
418
389
|
/**
|
|
419
390
|
* Performs the following:
|
|
420
|
-
* - Performs all root creations
|
|
421
|
-
* - Collects all roots that may need a detach pass
|
|
422
391
|
* - Collects all roots that may need an attach pass
|
|
423
|
-
* -
|
|
424
|
-
* - Collects all destructions
|
|
425
|
-
* - Executes detaches (bottom-up) provided they are not part of a replace
|
|
426
|
-
* (because we want to wait until we are sure content to attach is available as a root)
|
|
392
|
+
* - Executes detaches (bottom-up)
|
|
427
393
|
*/
|
|
428
394
|
function detachPass(
|
|
429
395
|
fieldChanges: Delta.FieldChanges,
|
|
@@ -439,18 +405,18 @@ function detachPass(
|
|
|
439
405
|
);
|
|
440
406
|
visitNode(index, mark.fields, visitor, config);
|
|
441
407
|
}
|
|
442
|
-
if (
|
|
408
|
+
if (mark.detach !== undefined) {
|
|
443
409
|
for (let i = 0; i < mark.count; i += 1) {
|
|
444
|
-
|
|
445
|
-
const id = offsetDetachId(mark.detach!, i);
|
|
410
|
+
const id = offsetDetachId(mark.detach, i);
|
|
446
411
|
const root = config.detachedFieldIndex.createEntry(id, config.latestRevision);
|
|
447
412
|
if (mark.fields !== undefined) {
|
|
448
413
|
config.attachPassRoots.set(root, mark.fields);
|
|
449
414
|
}
|
|
450
415
|
const field = config.detachedFieldIndex.toFieldKey(root);
|
|
451
|
-
visitor.detach({ start: index, end: index + 1 }, field, id);
|
|
416
|
+
visitor.detach({ start: index, end: index + 1 }, field, id, mark.attach !== undefined);
|
|
452
417
|
}
|
|
453
|
-
}
|
|
418
|
+
}
|
|
419
|
+
if (mark.detach === undefined && mark.attach === undefined) {
|
|
454
420
|
index += mark.count;
|
|
455
421
|
}
|
|
456
422
|
}
|
|
@@ -534,8 +500,6 @@ function collectDestroys(
|
|
|
534
500
|
/**
|
|
535
501
|
* Preforms the following:
|
|
536
502
|
* - Executes attaches (top-down) applying nested changes on the attached nodes
|
|
537
|
-
* - Executes replaces (top-down) applying nested changes on the attached nodes
|
|
538
|
-
* - Collects detached roots (from replaces) that need an attach pass
|
|
539
503
|
*/
|
|
540
504
|
function attachPass(
|
|
541
505
|
fieldChanges: Delta.FieldChanges,
|
|
@@ -544,10 +508,9 @@ function attachPass(
|
|
|
544
508
|
): void {
|
|
545
509
|
let index = 0;
|
|
546
510
|
for (const mark of fieldChanges) {
|
|
547
|
-
if (
|
|
511
|
+
if (mark.attach !== undefined) {
|
|
548
512
|
for (let i = 0; i < mark.count; i += 1) {
|
|
549
|
-
|
|
550
|
-
const offsetAttachId = offsetDetachId(mark.attach!, i);
|
|
513
|
+
const offsetAttachId = offsetDetachId(mark.attach, i);
|
|
551
514
|
let sourceRoot = config.detachedFieldIndex.tryGetEntry(offsetAttachId);
|
|
552
515
|
if (sourceRoot === undefined) {
|
|
553
516
|
const tree = tryGetFromNestedMap(
|
|
@@ -567,28 +530,7 @@ function attachPass(
|
|
|
567
530
|
}
|
|
568
531
|
const sourceField = config.detachedFieldIndex.toFieldKey(sourceRoot);
|
|
569
532
|
const offsetIndex = index + i;
|
|
570
|
-
|
|
571
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
572
|
-
const destinationId = offsetDetachId(mark.detach!, i);
|
|
573
|
-
const rootDestination = config.detachedFieldIndex.createEntry(
|
|
574
|
-
destinationId,
|
|
575
|
-
config.latestRevision,
|
|
576
|
-
);
|
|
577
|
-
const destinationField = config.detachedFieldIndex.toFieldKey(rootDestination);
|
|
578
|
-
visitor.replace(
|
|
579
|
-
sourceField,
|
|
580
|
-
{ start: offsetIndex, end: offsetIndex + 1 },
|
|
581
|
-
destinationField,
|
|
582
|
-
destinationId,
|
|
583
|
-
);
|
|
584
|
-
// We may need to do a second pass on the detached nodes
|
|
585
|
-
if (mark.fields !== undefined) {
|
|
586
|
-
config.attachPassRoots.set(rootDestination, mark.fields);
|
|
587
|
-
}
|
|
588
|
-
} else {
|
|
589
|
-
// This a simple attach
|
|
590
|
-
visitor.attach(sourceField, 1, offsetIndex);
|
|
591
|
-
}
|
|
533
|
+
visitor.attach(sourceField, 1, offsetIndex);
|
|
592
534
|
config.detachedFieldIndex.deleteEntry(offsetAttachId);
|
|
593
535
|
const fields = config.attachPassRoots.get(sourceRoot);
|
|
594
536
|
if (fields !== undefined) {
|
|
@@ -596,10 +538,11 @@ function attachPass(
|
|
|
596
538
|
visitNode(offsetIndex, fields, visitor, config);
|
|
597
539
|
}
|
|
598
540
|
}
|
|
599
|
-
}
|
|
541
|
+
}
|
|
542
|
+
if (mark.detach === undefined && mark.fields !== undefined) {
|
|
600
543
|
visitNode(index, mark.fields, visitor, config);
|
|
601
544
|
}
|
|
602
|
-
if (
|
|
545
|
+
if (mark.detach === undefined || mark.attach !== undefined) {
|
|
603
546
|
index += mark.count;
|
|
604
547
|
}
|
|
605
548
|
}
|
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { assert } from "@fluidframework/core-utils/internal";
|
|
7
|
-
|
|
8
6
|
import type { ICodecOptions } from "../../codec/index.js";
|
|
9
7
|
import { type IdAllocator, idAllocatorFromMaxId } from "../../util/index.js";
|
|
10
8
|
import type { RevisionTag, RevisionTagCodec } from "../rebase/index.js";
|
|
@@ -51,41 +49,46 @@ export function announceDelta(
|
|
|
51
49
|
detachedFieldIndex: DetachedFieldIndex,
|
|
52
50
|
): void {
|
|
53
51
|
const visitor = deltaProcessor.acquireVisitor();
|
|
54
|
-
visitDelta(delta, combineVisitors([visitor]
|
|
52
|
+
visitDelta(delta, combineVisitors([visitor]), detachedFieldIndex, latestRevision);
|
|
55
53
|
visitor.free();
|
|
56
54
|
}
|
|
57
55
|
|
|
56
|
+
export interface CombinedVisitor extends DeltaVisitor {
|
|
57
|
+
readonly type: "Combined";
|
|
58
|
+
|
|
59
|
+
readonly visitors: readonly CombinableVisitor[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type CombinableVisitor =
|
|
63
|
+
| (DeltaVisitor & { type?: never })
|
|
64
|
+
| AnnouncedVisitor
|
|
65
|
+
| CombinedVisitor;
|
|
66
|
+
|
|
58
67
|
/**
|
|
68
|
+
* Combines multiple visitors into a single visitor.
|
|
59
69
|
* @param visitors - The returned visitor invokes the corresponding events for all these visitors, in order.
|
|
60
|
-
* @param announcedVisitors - Subset of `visitors` to also call {@link AnnouncedVisitor} methods on.
|
|
61
|
-
* This must be a subset of `visitors`: if not the visitor will not have its path correctly set when the events are triggered.
|
|
62
|
-
* When `visitors` are making changes to data, `announcedVisitors` can be used to get extra events before or after all the changes from all the visitors have been made.
|
|
63
|
-
* This can, for example, enable visitors to have access to the tree in these extra events despite multiple separate visitors updating different tree related data-structures.
|
|
64
70
|
* @returns a DeltaVisitor combining all `visitors`.
|
|
65
71
|
*/
|
|
66
|
-
export function combineVisitors(
|
|
67
|
-
visitors:
|
|
68
|
-
announcedVisitors
|
|
69
|
-
):
|
|
70
|
-
|
|
71
|
-
const set = new Set(visitors);
|
|
72
|
-
for (const item of announcedVisitors) {
|
|
73
|
-
assert(set.has(item), 0x8c8 /* AnnouncedVisitor would not get traversed */);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
72
|
+
export function combineVisitors(visitors: readonly CombinableVisitor[]): CombinedVisitor {
|
|
73
|
+
const allVisitors = visitors.flatMap((v) => (v.type === "Combined" ? v.visitors : [v]));
|
|
74
|
+
const announcedVisitors = allVisitors.filter(
|
|
75
|
+
(v): v is AnnouncedVisitor => v.type === "Announced",
|
|
76
|
+
);
|
|
76
77
|
return {
|
|
78
|
+
type: "Combined",
|
|
79
|
+
visitors: allVisitors,
|
|
77
80
|
free: () => visitors.forEach((v) => v.free()),
|
|
78
81
|
create: (...args) => {
|
|
79
|
-
|
|
82
|
+
allVisitors.forEach((v) => v.create(...args));
|
|
80
83
|
announcedVisitors.forEach((v) => v.afterCreate(...args));
|
|
81
84
|
},
|
|
82
85
|
destroy: (...args) => {
|
|
83
86
|
announcedVisitors.forEach((v) => v.beforeDestroy(...args));
|
|
84
|
-
|
|
87
|
+
allVisitors.forEach((v) => v.destroy(...args));
|
|
85
88
|
},
|
|
86
89
|
attach: (source: FieldKey, count: number, destination: PlaceIndex) => {
|
|
87
90
|
announcedVisitors.forEach((v) => v.beforeAttach(source, count, destination));
|
|
88
|
-
|
|
91
|
+
allVisitors.forEach((v) => v.attach(source, count, destination));
|
|
89
92
|
announcedVisitors.forEach((v) =>
|
|
90
93
|
v.afterAttach(source, {
|
|
91
94
|
start: destination,
|
|
@@ -93,33 +96,22 @@ export function combineVisitors(
|
|
|
93
96
|
}),
|
|
94
97
|
);
|
|
95
98
|
},
|
|
96
|
-
detach: (
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
);
|
|
102
|
-
},
|
|
103
|
-
replace: (
|
|
104
|
-
newContent: FieldKey,
|
|
105
|
-
oldContent: Range,
|
|
106
|
-
oldContentDestination: FieldKey,
|
|
107
|
-
oldContentId: DetachedNodeId,
|
|
99
|
+
detach: (
|
|
100
|
+
source: Range,
|
|
101
|
+
destination: FieldKey,
|
|
102
|
+
id: DetachedNodeId,
|
|
103
|
+
isReplaced: boolean,
|
|
108
104
|
) => {
|
|
105
|
+
announcedVisitors.forEach((v) => v.beforeDetach(source, destination, isReplaced));
|
|
106
|
+
allVisitors.forEach((v) => v.detach(source, destination, id, isReplaced));
|
|
109
107
|
announcedVisitors.forEach((v) =>
|
|
110
|
-
v.
|
|
111
|
-
);
|
|
112
|
-
visitors.forEach((v) =>
|
|
113
|
-
v.replace(newContent, oldContent, oldContentDestination, oldContentId),
|
|
114
|
-
);
|
|
115
|
-
announcedVisitors.forEach((v) =>
|
|
116
|
-
v.afterReplace(newContent, oldContent, oldContentDestination),
|
|
108
|
+
v.afterDetach(source.start, source.end - source.start, destination, isReplaced),
|
|
117
109
|
);
|
|
118
110
|
},
|
|
119
|
-
enterNode: (...args) =>
|
|
120
|
-
exitNode: (...args) =>
|
|
121
|
-
enterField: (...args) =>
|
|
122
|
-
exitField: (...args) =>
|
|
111
|
+
enterNode: (...args) => allVisitors.forEach((v) => v.enterNode(...args)),
|
|
112
|
+
exitNode: (...args) => allVisitors.forEach((v) => v.exitNode(...args)),
|
|
113
|
+
enterField: (...args) => allVisitors.forEach((v) => v.enterField(...args)),
|
|
114
|
+
exitField: (...args) => allVisitors.forEach((v) => v.exitField(...args)),
|
|
123
115
|
};
|
|
124
116
|
}
|
|
125
117
|
|
|
@@ -128,6 +120,7 @@ export function combineVisitors(
|
|
|
128
120
|
* Must be freed after use.
|
|
129
121
|
*/
|
|
130
122
|
export interface AnnouncedVisitor extends DeltaVisitor {
|
|
123
|
+
readonly type: "Announced";
|
|
131
124
|
/**
|
|
132
125
|
* A hook that is called after all nodes have been created.
|
|
133
126
|
*/
|
|
@@ -135,14 +128,13 @@ export interface AnnouncedVisitor extends DeltaVisitor {
|
|
|
135
128
|
beforeDestroy(field: FieldKey, count: number): void;
|
|
136
129
|
beforeAttach(source: FieldKey, count: number, destination: PlaceIndex): void;
|
|
137
130
|
afterAttach(source: FieldKey, destination: Range): void;
|
|
138
|
-
beforeDetach(source: Range, destination: FieldKey): void;
|
|
139
|
-
afterDetach(
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
131
|
+
beforeDetach(source: Range, destination: FieldKey, isReplaced: boolean): void;
|
|
132
|
+
afterDetach(
|
|
133
|
+
source: PlaceIndex,
|
|
134
|
+
count: number,
|
|
135
|
+
destination: FieldKey,
|
|
136
|
+
isReplaced: boolean,
|
|
144
137
|
): void;
|
|
145
|
-
afterReplace(newContentSource: FieldKey, newContent: Range, oldContent: FieldKey): void;
|
|
146
138
|
}
|
|
147
139
|
|
|
148
140
|
/**
|
|
@@ -154,6 +146,7 @@ export function createAnnouncedVisitor(
|
|
|
154
146
|
): AnnouncedVisitor {
|
|
155
147
|
const noOp = (): void => {};
|
|
156
148
|
return {
|
|
149
|
+
type: "Announced",
|
|
157
150
|
free: visitorFunctions.free ?? noOp,
|
|
158
151
|
create: visitorFunctions.create ?? noOp,
|
|
159
152
|
afterCreate: visitorFunctions.afterCreate ?? noOp,
|
|
@@ -165,9 +158,6 @@ export function createAnnouncedVisitor(
|
|
|
165
158
|
beforeDetach: visitorFunctions.beforeDetach ?? noOp,
|
|
166
159
|
detach: visitorFunctions.detach ?? noOp,
|
|
167
160
|
afterDetach: visitorFunctions.afterDetach ?? noOp,
|
|
168
|
-
beforeReplace: visitorFunctions.beforeReplace ?? noOp,
|
|
169
|
-
replace: visitorFunctions.replace ?? noOp,
|
|
170
|
-
afterReplace: visitorFunctions.afterReplace ?? noOp,
|
|
171
161
|
enterNode: visitorFunctions.enterNode ?? noOp,
|
|
172
162
|
exitNode: visitorFunctions.exitNode ?? noOp,
|
|
173
163
|
enterField: visitorFunctions.enterField ?? noOp,
|
|
@@ -183,6 +183,12 @@ export class ChunkedForest implements IEditableForest {
|
|
|
183
183
|
* If not specified, the detached range is destroyed.
|
|
184
184
|
*/
|
|
185
185
|
detachEdit(source: Range, destination: FieldKey | undefined): void {
|
|
186
|
+
// TODO: optimize this to perform in-place replace in uniform chunks when attach edits bring the chunk back to its original shape.
|
|
187
|
+
// This should result in 3 cases:
|
|
188
|
+
// 1. In-place update of uniform chunk. No allocations, no ref count changes, no new TreeChunks.
|
|
189
|
+
// 2. Uniform chunk is shared: copy it (and parent path as needed), and update the copy.
|
|
190
|
+
// 3. Fallback to detach then attach (Which will copy parents and convert to basic chunks as needed).
|
|
191
|
+
|
|
186
192
|
this.forest.#events.emit("beforeChange");
|
|
187
193
|
const parent = this.getParent();
|
|
188
194
|
const sourceField = parent.mutableChunk.fields.get(parent.key) ?? [];
|
|
@@ -209,24 +215,6 @@ export class ChunkedForest implements IEditableForest {
|
|
|
209
215
|
parent.mutableChunk.fields.delete(parent.key);
|
|
210
216
|
}
|
|
211
217
|
},
|
|
212
|
-
replace(
|
|
213
|
-
newContentSource: FieldKey,
|
|
214
|
-
range: Range,
|
|
215
|
-
oldContentDestination: FieldKey,
|
|
216
|
-
oldContentId: DeltaDetachedNodeId,
|
|
217
|
-
): void {
|
|
218
|
-
assert(
|
|
219
|
-
newContentSource !== oldContentDestination,
|
|
220
|
-
0x7b0 /* Replace detached source field and detached destination field must be different */,
|
|
221
|
-
);
|
|
222
|
-
// TODO: optimize this to: perform in-place replace in uniform chunks when possible.
|
|
223
|
-
// This should result in 3 cases:
|
|
224
|
-
// 1. In-place update of uniform chunk. No allocations, no ref count changes, no new TreeChunks.
|
|
225
|
-
// 2. Uniform chunk is shared: copy it (and parent path as needed), and update the copy.
|
|
226
|
-
// 3. Fallback to detach then attach (Which will copy parents and convert to basic chunks as needed).
|
|
227
|
-
this.detachEdit(range, oldContentDestination);
|
|
228
|
-
this.attachEdit(newContentSource, range.end - range.start, range.start);
|
|
229
|
-
},
|
|
230
218
|
enterNode(index: number): void {
|
|
231
219
|
assert(this.mutableChunk === undefined, 0x535 /* should be in field */);
|
|
232
220
|
const parent = this.getParent();
|
|
@@ -289,10 +277,7 @@ export class ChunkedForest implements IEditableForest {
|
|
|
289
277
|
|
|
290
278
|
const announcedVisitors: AnnouncedVisitor[] = [];
|
|
291
279
|
this.deltaVisitors.forEach((getVisitor) => announcedVisitors.push(getVisitor()));
|
|
292
|
-
const combinedVisitor = combineVisitors(
|
|
293
|
-
[forestVisitor, ...announcedVisitors],
|
|
294
|
-
announcedVisitors,
|
|
295
|
-
);
|
|
280
|
+
const combinedVisitor = combineVisitors([forestVisitor, ...announcedVisitors]);
|
|
296
281
|
this.activeVisitor = combinedVisitor;
|
|
297
282
|
return combinedVisitor;
|
|
298
283
|
}
|