@fluidframework/tree 2.10.0 → 2.11.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 +25 -0
- package/api-report/tree.alpha.api.md +47 -16
- package/api-report/tree.beta.api.md +5 -14
- package/api-report/tree.legacy.alpha.api.md +5 -14
- package/api-report/tree.legacy.public.api.md +5 -14
- package/api-report/tree.public.api.md +5 -14
- package/dist/alpha.d.ts +9 -0
- package/dist/core/forest/forest.d.ts +10 -2
- package/dist/core/forest/forest.d.ts.map +1 -1
- package/dist/core/forest/forest.js.map +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/rebase/utils.d.ts +1 -1
- package/dist/core/rebase/utils.d.ts.map +1 -1
- package/dist/core/rebase/utils.js +11 -8
- package/dist/core/rebase/utils.js.map +1 -1
- package/dist/core/revertible.d.ts +30 -1
- package/dist/core/revertible.d.ts.map +1 -1
- package/dist/core/revertible.js.map +1 -1
- package/dist/core/schema-stored/storedSchemaRepository.d.ts +2 -2
- package/dist/core/schema-stored/storedSchemaRepository.d.ts.map +1 -1
- package/dist/core/schema-stored/storedSchemaRepository.js +5 -5
- package/dist/core/schema-stored/storedSchemaRepository.js.map +1 -1
- package/dist/core/tree/anchorSet.d.ts +2 -2
- package/dist/core/tree/anchorSet.d.ts.map +1 -1
- package/dist/core/tree/anchorSet.js +21 -21
- package/dist/core/tree/anchorSet.js.map +1 -1
- package/dist/core/tree/detachedFieldIndexCodec.d.ts.map +1 -1
- package/dist/core/tree/detachedFieldIndexCodec.js +3 -2
- package/dist/core/tree/detachedFieldIndexCodec.js.map +1 -1
- package/dist/core/tree/index.d.ts +1 -1
- package/dist/core/tree/index.d.ts.map +1 -1
- package/dist/core/tree/index.js +2 -1
- package/dist/core/tree/index.js.map +1 -1
- package/dist/core/tree/visitorUtils.d.ts +25 -1
- package/dist/core/tree/visitorUtils.d.ts.map +1 -1
- package/dist/core/tree/visitorUtils.js +29 -1
- package/dist/core/tree/visitorUtils.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/chunkedForest.d.ts +5 -2
- package/dist/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/chunkedForest.js +24 -14
- package/dist/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/uniformChunk.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/uniformChunk.js +2 -2
- package/dist/feature-libraries/chunked-forest/uniformChunk.js.map +1 -1
- package/dist/feature-libraries/flex-tree/context.d.ts +1 -1
- package/dist/feature-libraries/flex-tree/context.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/context.js.map +1 -1
- package/dist/feature-libraries/index.d.ts +1 -0
- package/dist/feature-libraries/index.d.ts.map +1 -1
- package/dist/feature-libraries/index.js +4 -1
- package/dist/feature-libraries/index.js.map +1 -1
- package/dist/feature-libraries/indexing/anchorTreeIndex.d.ts +132 -0
- package/dist/feature-libraries/indexing/anchorTreeIndex.d.ts.map +1 -0
- package/dist/feature-libraries/indexing/anchorTreeIndex.js +361 -0
- package/dist/feature-libraries/indexing/anchorTreeIndex.js.map +1 -0
- package/dist/feature-libraries/indexing/index.d.ts +7 -0
- package/dist/feature-libraries/indexing/index.d.ts.map +1 -0
- package/dist/feature-libraries/indexing/index.js +11 -0
- package/dist/feature-libraries/indexing/index.js.map +1 -0
- package/dist/feature-libraries/indexing/types.d.ts +32 -0
- package/dist/feature-libraries/indexing/types.d.ts.map +1 -0
- package/dist/{events/interop.js → feature-libraries/indexing/types.js} +1 -1
- package/dist/feature-libraries/indexing/types.js.map +1 -0
- package/dist/feature-libraries/object-forest/objectForest.d.ts +5 -2
- package/dist/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
- package/dist/feature-libraries/object-forest/objectForest.js +21 -11
- package/dist/feature-libraries/object-forest/objectForest.js.map +1 -1
- package/dist/feature-libraries/sequence-field/invert.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/invert.js +2 -2
- package/dist/feature-libraries/sequence-field/invert.js.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.js +3 -2
- package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/shared-tree/index.d.ts +1 -1
- package/dist/shared-tree/index.d.ts.map +1 -1
- package/dist/shared-tree/index.js +1 -2
- package/dist/shared-tree/index.js.map +1 -1
- package/dist/shared-tree/schematizingTreeView.d.ts +7 -1
- package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/dist/shared-tree/schematizingTreeView.js +31 -30
- package/dist/shared-tree/schematizingTreeView.js.map +1 -1
- package/dist/shared-tree/sharedTree.d.ts +3 -0
- package/dist/shared-tree/sharedTree.d.ts.map +1 -1
- package/dist/shared-tree/sharedTree.js +56 -20
- package/dist/shared-tree/sharedTree.js.map +1 -1
- package/dist/shared-tree/sharedTreeChangeFamily.d.ts.map +1 -1
- package/dist/shared-tree/sharedTreeChangeFamily.js +3 -3
- package/dist/shared-tree/sharedTreeChangeFamily.js.map +1 -1
- package/dist/shared-tree/treeCheckout.d.ts +28 -64
- package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
- package/dist/shared-tree/treeCheckout.js +152 -129
- package/dist/shared-tree/treeCheckout.js.map +1 -1
- package/dist/shared-tree-core/branch.d.ts +25 -81
- package/dist/shared-tree-core/branch.d.ts.map +1 -1
- package/dist/shared-tree-core/branch.js +72 -151
- package/dist/shared-tree-core/branch.js.map +1 -1
- package/dist/shared-tree-core/branchCommitEnricher.d.ts +19 -33
- package/dist/shared-tree-core/branchCommitEnricher.d.ts.map +1 -1
- package/dist/shared-tree-core/branchCommitEnricher.js +73 -54
- package/dist/shared-tree-core/branchCommitEnricher.js.map +1 -1
- package/dist/shared-tree-core/defaultResubmitMachine.d.ts.map +1 -1
- package/dist/shared-tree-core/defaultResubmitMachine.js +2 -1
- package/dist/shared-tree-core/defaultResubmitMachine.js.map +1 -1
- package/dist/shared-tree-core/editManager.d.ts.map +1 -1
- package/dist/shared-tree-core/editManager.js +2 -2
- package/dist/shared-tree-core/editManager.js.map +1 -1
- package/dist/shared-tree-core/index.d.ts +1 -1
- package/dist/shared-tree-core/index.d.ts.map +1 -1
- package/dist/shared-tree-core/index.js +4 -3
- package/dist/shared-tree-core/index.js.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.d.ts +2 -2
- package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.js +11 -52
- package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/dist/shared-tree-core/transaction.d.ts +108 -0
- package/dist/shared-tree-core/transaction.d.ts.map +1 -0
- package/dist/shared-tree-core/transaction.js +99 -0
- package/dist/shared-tree-core/transaction.js.map +1 -0
- package/dist/shared-tree-core/transactionEnricher.d.ts +8 -13
- package/dist/shared-tree-core/transactionEnricher.d.ts.map +1 -1
- package/dist/shared-tree-core/transactionEnricher.js +41 -21
- package/dist/shared-tree-core/transactionEnricher.js.map +1 -1
- package/dist/simple-tree/api/identifierIndex.d.ts +21 -0
- package/dist/simple-tree/api/identifierIndex.d.ts.map +1 -0
- package/dist/simple-tree/api/identifierIndex.js +45 -0
- package/dist/simple-tree/api/identifierIndex.js.map +1 -0
- package/dist/simple-tree/api/index.d.ts +2 -0
- package/dist/simple-tree/api/index.d.ts.map +1 -1
- package/dist/simple-tree/api/index.js +5 -1
- package/dist/simple-tree/api/index.js.map +1 -1
- package/dist/simple-tree/api/simpleSchemaToJsonSchema.js +9 -7
- package/dist/simple-tree/api/simpleSchemaToJsonSchema.js.map +1 -1
- package/dist/simple-tree/api/simpleTreeIndex.d.ts +65 -0
- package/dist/simple-tree/api/simpleTreeIndex.d.ts.map +1 -0
- package/dist/simple-tree/api/simpleTreeIndex.js +91 -0
- package/dist/simple-tree/api/simpleTreeIndex.js.map +1 -0
- package/dist/simple-tree/api/tree.d.ts +4 -5
- 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/treeNodeApi.js.map +1 -1
- package/dist/simple-tree/core/index.d.ts +1 -1
- package/dist/simple-tree/core/index.d.ts.map +1 -1
- package/dist/simple-tree/core/index.js +2 -1
- package/dist/simple-tree/core/index.js.map +1 -1
- package/dist/simple-tree/core/treeNodeKernel.d.ts +6 -2
- package/dist/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
- package/dist/simple-tree/core/treeNodeKernel.js +53 -22
- package/dist/simple-tree/core/treeNodeKernel.js.map +1 -1
- package/dist/simple-tree/core/unhydratedFlexTree.d.ts +1 -1
- package/dist/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
- package/dist/simple-tree/core/unhydratedFlexTree.js +2 -2
- 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 +4 -2
- package/dist/simple-tree/index.js.map +1 -1
- package/dist/simple-tree/objectNode.d.ts +7 -2
- package/dist/simple-tree/objectNode.d.ts.map +1 -1
- package/dist/simple-tree/objectNode.js.map +1 -1
- package/dist/simple-tree/toMapTree.js +3 -3
- package/dist/simple-tree/toMapTree.js.map +1 -1
- package/dist/util/index.d.ts +1 -2
- package/dist/util/index.d.ts.map +1 -1
- package/dist/util/index.js +5 -4
- package/dist/util/index.js.map +1 -1
- package/dist/util/typeCheck.d.ts +6 -1
- package/dist/util/typeCheck.d.ts.map +1 -1
- package/dist/util/typeCheck.js.map +1 -1
- package/dist/util/typeCheckTests.d.ts +14 -2
- package/dist/util/typeCheckTests.d.ts.map +1 -1
- package/dist/util/typeCheckTests.js.map +1 -1
- package/dist/util/utils.d.ts +29 -0
- package/dist/util/utils.d.ts.map +1 -1
- package/dist/util/utils.js +13 -1
- package/dist/util/utils.js.map +1 -1
- package/lib/alpha.d.ts +9 -0
- package/lib/core/forest/forest.d.ts +10 -2
- package/lib/core/forest/forest.d.ts.map +1 -1
- package/lib/core/forest/forest.js.map +1 -1
- package/lib/core/index.d.ts +2 -2
- package/lib/core/index.d.ts.map +1 -1
- package/lib/core/index.js +2 -2
- package/lib/core/index.js.map +1 -1
- package/lib/core/rebase/utils.d.ts +1 -1
- package/lib/core/rebase/utils.d.ts.map +1 -1
- package/lib/core/rebase/utils.js +11 -8
- package/lib/core/rebase/utils.js.map +1 -1
- package/lib/core/revertible.d.ts +30 -1
- package/lib/core/revertible.d.ts.map +1 -1
- package/lib/core/revertible.js.map +1 -1
- package/lib/core/schema-stored/storedSchemaRepository.d.ts +2 -2
- package/lib/core/schema-stored/storedSchemaRepository.d.ts.map +1 -1
- package/lib/core/schema-stored/storedSchemaRepository.js +1 -1
- package/lib/core/schema-stored/storedSchemaRepository.js.map +1 -1
- package/lib/core/tree/anchorSet.d.ts +2 -2
- package/lib/core/tree/anchorSet.d.ts.map +1 -1
- package/lib/core/tree/anchorSet.js +1 -1
- package/lib/core/tree/anchorSet.js.map +1 -1
- package/lib/core/tree/detachedFieldIndexCodec.d.ts.map +1 -1
- package/lib/core/tree/detachedFieldIndexCodec.js +4 -3
- package/lib/core/tree/detachedFieldIndexCodec.js.map +1 -1
- package/lib/core/tree/index.d.ts +1 -1
- package/lib/core/tree/index.d.ts.map +1 -1
- package/lib/core/tree/index.js +1 -1
- package/lib/core/tree/index.js.map +1 -1
- package/lib/core/tree/visitorUtils.d.ts +25 -1
- package/lib/core/tree/visitorUtils.d.ts.map +1 -1
- package/lib/core/tree/visitorUtils.js +27 -0
- package/lib/core/tree/visitorUtils.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts +5 -2
- package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/chunkedForest.js +18 -8
- package/lib/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/uniformChunk.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/uniformChunk.js +3 -3
- package/lib/feature-libraries/chunked-forest/uniformChunk.js.map +1 -1
- package/lib/feature-libraries/flex-tree/context.d.ts +1 -1
- package/lib/feature-libraries/flex-tree/context.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/context.js.map +1 -1
- package/lib/feature-libraries/index.d.ts +1 -0
- package/lib/feature-libraries/index.d.ts.map +1 -1
- package/lib/feature-libraries/index.js +1 -0
- package/lib/feature-libraries/index.js.map +1 -1
- package/lib/feature-libraries/indexing/anchorTreeIndex.d.ts +132 -0
- package/lib/feature-libraries/indexing/anchorTreeIndex.d.ts.map +1 -0
- package/lib/feature-libraries/indexing/anchorTreeIndex.js +356 -0
- package/lib/feature-libraries/indexing/anchorTreeIndex.js.map +1 -0
- package/lib/feature-libraries/indexing/index.d.ts +7 -0
- package/lib/feature-libraries/indexing/index.d.ts.map +1 -0
- package/lib/{events → feature-libraries/indexing}/index.js +1 -1
- package/lib/feature-libraries/indexing/index.js.map +1 -0
- package/lib/feature-libraries/indexing/types.d.ts +32 -0
- package/lib/feature-libraries/indexing/types.d.ts.map +1 -0
- package/lib/{events/interop.js → feature-libraries/indexing/types.js} +1 -1
- package/lib/feature-libraries/indexing/types.js.map +1 -0
- package/lib/feature-libraries/object-forest/objectForest.d.ts +5 -2
- package/lib/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
- package/lib/feature-libraries/object-forest/objectForest.js +15 -5
- package/lib/feature-libraries/object-forest/objectForest.js.map +1 -1
- package/lib/feature-libraries/sequence-field/invert.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/invert.js +4 -4
- package/lib/feature-libraries/sequence-field/invert.js.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.js +4 -3
- package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.js.map +1 -1
- package/lib/index.d.ts +4 -4
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/shared-tree/index.d.ts +1 -1
- 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/schematizingTreeView.d.ts +7 -1
- package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/lib/shared-tree/schematizingTreeView.js +2 -2
- package/lib/shared-tree/schematizingTreeView.js.map +1 -1
- package/lib/shared-tree/sharedTree.d.ts +3 -0
- package/lib/shared-tree/sharedTree.d.ts.map +1 -1
- package/lib/shared-tree/sharedTree.js +37 -1
- package/lib/shared-tree/sharedTree.js.map +1 -1
- package/lib/shared-tree/sharedTreeChangeFamily.d.ts.map +1 -1
- package/lib/shared-tree/sharedTreeChangeFamily.js +5 -5
- package/lib/shared-tree/sharedTreeChangeFamily.js.map +1 -1
- package/lib/shared-tree/treeCheckout.d.ts +28 -64
- package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
- package/lib/shared-tree/treeCheckout.js +140 -116
- package/lib/shared-tree/treeCheckout.js.map +1 -1
- package/lib/shared-tree-core/branch.d.ts +25 -81
- package/lib/shared-tree-core/branch.d.ts.map +1 -1
- package/lib/shared-tree-core/branch.js +72 -151
- package/lib/shared-tree-core/branch.js.map +1 -1
- package/lib/shared-tree-core/branchCommitEnricher.d.ts +19 -33
- package/lib/shared-tree-core/branchCommitEnricher.d.ts.map +1 -1
- package/lib/shared-tree-core/branchCommitEnricher.js +74 -55
- package/lib/shared-tree-core/branchCommitEnricher.js.map +1 -1
- package/lib/shared-tree-core/defaultResubmitMachine.d.ts.map +1 -1
- package/lib/shared-tree-core/defaultResubmitMachine.js +3 -2
- package/lib/shared-tree-core/defaultResubmitMachine.js.map +1 -1
- package/lib/shared-tree-core/editManager.d.ts.map +1 -1
- package/lib/shared-tree-core/editManager.js +1 -1
- package/lib/shared-tree-core/editManager.js.map +1 -1
- package/lib/shared-tree-core/index.d.ts +1 -1
- package/lib/shared-tree-core/index.d.ts.map +1 -1
- package/lib/shared-tree-core/index.js +1 -1
- package/lib/shared-tree-core/index.js.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.d.ts +2 -2
- package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.js +12 -53
- package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/lib/shared-tree-core/transaction.d.ts +108 -0
- package/lib/shared-tree-core/transaction.d.ts.map +1 -0
- package/lib/shared-tree-core/transaction.js +95 -0
- package/lib/shared-tree-core/transaction.js.map +1 -0
- package/lib/shared-tree-core/transactionEnricher.d.ts +8 -13
- package/lib/shared-tree-core/transactionEnricher.d.ts.map +1 -1
- package/lib/shared-tree-core/transactionEnricher.js +41 -21
- package/lib/shared-tree-core/transactionEnricher.js.map +1 -1
- package/lib/simple-tree/api/identifierIndex.d.ts +21 -0
- package/lib/simple-tree/api/identifierIndex.d.ts.map +1 -0
- package/lib/simple-tree/api/identifierIndex.js +41 -0
- package/lib/simple-tree/api/identifierIndex.js.map +1 -0
- package/lib/simple-tree/api/index.d.ts +2 -0
- package/lib/simple-tree/api/index.d.ts.map +1 -1
- package/lib/simple-tree/api/index.js +2 -0
- package/lib/simple-tree/api/index.js.map +1 -1
- package/lib/simple-tree/api/simpleSchemaToJsonSchema.js +11 -9
- package/lib/simple-tree/api/simpleSchemaToJsonSchema.js.map +1 -1
- package/lib/simple-tree/api/simpleTreeIndex.d.ts +65 -0
- package/lib/simple-tree/api/simpleTreeIndex.d.ts.map +1 -0
- package/lib/simple-tree/api/simpleTreeIndex.js +87 -0
- package/lib/simple-tree/api/simpleTreeIndex.js.map +1 -0
- package/lib/simple-tree/api/tree.d.ts +4 -5
- 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/treeNodeApi.js.map +1 -1
- package/lib/simple-tree/core/index.d.ts +1 -1
- package/lib/simple-tree/core/index.d.ts.map +1 -1
- package/lib/simple-tree/core/index.js +1 -1
- package/lib/simple-tree/core/index.js.map +1 -1
- package/lib/simple-tree/core/treeNodeKernel.d.ts +6 -2
- package/lib/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
- package/lib/simple-tree/core/treeNodeKernel.js +31 -1
- package/lib/simple-tree/core/treeNodeKernel.js.map +1 -1
- package/lib/simple-tree/core/unhydratedFlexTree.d.ts +1 -1
- package/lib/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
- package/lib/simple-tree/core/unhydratedFlexTree.js +1 -1
- 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 +7 -2
- package/lib/simple-tree/objectNode.d.ts.map +1 -1
- package/lib/simple-tree/objectNode.js.map +1 -1
- package/lib/simple-tree/toMapTree.js +5 -5
- package/lib/simple-tree/toMapTree.js.map +1 -1
- package/lib/util/index.d.ts +1 -2
- package/lib/util/index.d.ts.map +1 -1
- package/lib/util/index.js +1 -2
- package/lib/util/index.js.map +1 -1
- package/lib/util/typeCheck.d.ts +6 -1
- package/lib/util/typeCheck.d.ts.map +1 -1
- package/lib/util/typeCheck.js.map +1 -1
- package/lib/util/typeCheckTests.d.ts +14 -2
- package/lib/util/typeCheckTests.d.ts.map +1 -1
- package/lib/util/typeCheckTests.js.map +1 -1
- package/lib/util/utils.d.ts +29 -0
- package/lib/util/utils.d.ts.map +1 -1
- package/lib/util/utils.js +9 -0
- package/lib/util/utils.js.map +1 -1
- package/package.json +22 -22
- package/src/core/forest/forest.ts +12 -1
- package/src/core/index.ts +8 -1
- package/src/core/rebase/utils.ts +12 -10
- package/src/core/revertible.ts +35 -1
- package/src/core/schema-stored/storedSchemaRepository.ts +2 -1
- package/src/core/tree/anchorSet.ts +2 -1
- package/src/core/tree/detachedFieldIndexCodec.ts +4 -3
- package/src/core/tree/index.ts +1 -0
- package/src/core/tree/visitorUtils.ts +56 -1
- package/src/feature-libraries/chunked-forest/chunkedForest.ts +33 -7
- package/src/feature-libraries/chunked-forest/uniformChunk.ts +3 -3
- package/src/feature-libraries/flex-tree/context.ts +1 -1
- package/src/feature-libraries/index.ts +9 -0
- package/src/feature-libraries/indexing/anchorTreeIndex.ts +453 -0
- package/src/feature-libraries/indexing/index.ts +11 -0
- package/src/feature-libraries/indexing/types.ts +37 -0
- package/src/feature-libraries/object-forest/objectForest.ts +22 -4
- package/src/feature-libraries/sequence-field/invert.ts +4 -4
- package/src/feature-libraries/sequence-field/sequenceFieldToDelta.ts +4 -4
- package/src/index.ts +16 -6
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/index.ts +0 -2
- package/src/shared-tree/schematizingTreeView.ts +7 -7
- package/src/shared-tree/sharedTree.ts +60 -6
- package/src/shared-tree/sharedTreeChangeFamily.ts +5 -4
- package/src/shared-tree/treeCheckout.ts +186 -193
- package/src/shared-tree-core/branch.ts +93 -220
- package/src/shared-tree-core/branchCommitEnricher.ts +69 -64
- package/src/shared-tree-core/defaultResubmitMachine.ts +3 -2
- package/src/shared-tree-core/editManager.ts +1 -1
- package/src/shared-tree-core/index.ts +9 -2
- package/src/shared-tree-core/sharedTreeCore.ts +17 -62
- package/src/shared-tree-core/transaction.ts +165 -0
- package/src/shared-tree-core/transactionEnricher.ts +30 -24
- package/src/simple-tree/api/identifierIndex.ts +64 -0
- package/src/simple-tree/api/index.ts +5 -0
- package/src/simple-tree/api/simpleSchemaToJsonSchema.ts +17 -18
- package/src/simple-tree/api/simpleTreeIndex.ts +231 -0
- package/src/simple-tree/api/tree.ts +8 -5
- package/src/simple-tree/api/treeNodeApi.ts +1 -1
- package/src/simple-tree/core/index.ts +1 -0
- package/src/simple-tree/core/treeNodeKernel.ts +37 -2
- package/src/simple-tree/core/unhydratedFlexTree.ts +2 -1
- package/src/simple-tree/index.ts +4 -0
- package/src/simple-tree/objectNode.ts +19 -12
- package/src/simple-tree/toMapTree.ts +5 -5
- package/src/util/index.ts +3 -1
- package/src/util/typeCheck.ts +6 -1
- package/src/util/typeCheckTests.ts +11 -1
- package/src/util/utils.ts +38 -0
- package/dist/events/emitter.d.ts +0 -139
- package/dist/events/emitter.d.ts.map +0 -1
- package/dist/events/emitter.js +0 -165
- package/dist/events/emitter.js.map +0 -1
- package/dist/events/index.d.ts +0 -7
- package/dist/events/index.d.ts.map +0 -1
- package/dist/events/index.js +0 -11
- package/dist/events/index.js.map +0 -1
- package/dist/events/interop.d.ts +0 -30
- package/dist/events/interop.d.ts.map +0 -1
- package/dist/events/interop.js.map +0 -1
- package/dist/events/listeners.d.ts +0 -76
- package/dist/events/listeners.d.ts.map +0 -1
- package/dist/events/listeners.js +0 -7
- package/dist/events/listeners.js.map +0 -1
- package/dist/shared-tree-core/transactionStack.d.ts +0 -29
- package/dist/shared-tree-core/transactionStack.d.ts.map +0 -1
- package/dist/shared-tree-core/transactionStack.js +0 -41
- package/dist/shared-tree-core/transactionStack.js.map +0 -1
- package/dist/util/transactionResult.d.ts +0 -19
- package/dist/util/transactionResult.d.ts.map +0 -1
- package/dist/util/transactionResult.js +0 -23
- package/dist/util/transactionResult.js.map +0 -1
- package/lib/events/emitter.d.ts +0 -139
- package/lib/events/emitter.d.ts.map +0 -1
- package/lib/events/emitter.js +0 -160
- package/lib/events/emitter.js.map +0 -1
- package/lib/events/index.d.ts +0 -7
- package/lib/events/index.d.ts.map +0 -1
- package/lib/events/index.js.map +0 -1
- package/lib/events/interop.d.ts +0 -30
- package/lib/events/interop.d.ts.map +0 -1
- package/lib/events/interop.js.map +0 -1
- package/lib/events/listeners.d.ts +0 -76
- package/lib/events/listeners.d.ts.map +0 -1
- package/lib/events/listeners.js +0 -6
- package/lib/events/listeners.js.map +0 -1
- package/lib/shared-tree-core/transactionStack.d.ts +0 -29
- package/lib/shared-tree-core/transactionStack.d.ts.map +0 -1
- package/lib/shared-tree-core/transactionStack.js +0 -37
- package/lib/shared-tree-core/transactionStack.js.map +0 -1
- package/lib/util/transactionResult.d.ts +0 -19
- package/lib/util/transactionResult.d.ts.map +0 -1
- package/lib/util/transactionResult.js +0 -20
- package/lib/util/transactionResult.js.map +0 -1
- package/src/events/README.md +0 -3
- package/src/events/emitter.ts +0 -256
- package/src/events/index.ts +0 -19
- package/src/events/interop.ts +0 -38
- package/src/events/listeners.ts +0 -80
- package/src/shared-tree-core/transactionStack.ts +0 -45
- package/src/util/transactionResult.ts +0 -19
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { assert } from "@fluidframework/core-utils/internal";
|
|
7
|
+
import { disposeSymbol, fail, getOrCreate } from "../../util/index.js";
|
|
8
|
+
import {
|
|
9
|
+
type Anchor,
|
|
10
|
+
type AnchorNode,
|
|
11
|
+
type FieldKey,
|
|
12
|
+
type TreeNodeSchemaIdentifier,
|
|
13
|
+
forEachField,
|
|
14
|
+
forEachNode,
|
|
15
|
+
type ITreeSubscriptionCursor,
|
|
16
|
+
createAnnouncedVisitor,
|
|
17
|
+
type IForestSubscription,
|
|
18
|
+
type AnnouncedVisitor,
|
|
19
|
+
CursorLocationType,
|
|
20
|
+
rootField,
|
|
21
|
+
type UpPath,
|
|
22
|
+
type ProtoNodes,
|
|
23
|
+
keyAsDetachedField,
|
|
24
|
+
compareUpPaths,
|
|
25
|
+
TreeNavigationResult,
|
|
26
|
+
} from "../../core/index.js";
|
|
27
|
+
import type { TreeIndex, TreeIndexKey, TreeIndexNodes } from "./types.js";
|
|
28
|
+
import { TreeStatus } from "../flex-tree/index.js";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A function that gets the value to index a node on, must be pure and functional.
|
|
32
|
+
* The given cursor should point to the node that will be indexed.
|
|
33
|
+
*
|
|
34
|
+
* @returns a value the index will use as the key for the given node
|
|
35
|
+
*
|
|
36
|
+
* @remarks
|
|
37
|
+
* This function does not own the cursor in any way, it walks the cursor to find the key the node is indexed on
|
|
38
|
+
* but returns the cursor to the state it was in before being passed to the function. It should also not be disposed by this function
|
|
39
|
+
* and must be disposed elsewhere.
|
|
40
|
+
*/
|
|
41
|
+
export type KeyFinder<TKey extends TreeIndexKey> = (tree: ITreeSubscriptionCursor) => TKey;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* An index from some arbitrary keys to anchor nodes. Keys can be anything that is a {@link TreeValue}.
|
|
45
|
+
* A key can map to multiple nodes but each collection of nodes only results in a single value.
|
|
46
|
+
*
|
|
47
|
+
* @remarks
|
|
48
|
+
* Detached nodes are stored in the index but filtered out when any public facing apis are called. This means that
|
|
49
|
+
* calling {@link keys} will not include any keys that are stored in the index but only map to detached nodes.
|
|
50
|
+
*/
|
|
51
|
+
export class AnchorTreeIndex<TKey extends TreeIndexKey, TValue>
|
|
52
|
+
implements TreeIndex<TKey, TValue>
|
|
53
|
+
{
|
|
54
|
+
public disposed = false;
|
|
55
|
+
/**
|
|
56
|
+
* Caches {@link KeyFinder}s for each schema definition. If a schema maps to null, it does not
|
|
57
|
+
* need to be considered at all for this index. This allows us to skip subtrees that aren't relevant
|
|
58
|
+
* as a performance optimization.
|
|
59
|
+
*/
|
|
60
|
+
private readonly keyFinders = new Map<TreeNodeSchemaIdentifier, KeyFinder<TKey> | null>();
|
|
61
|
+
/**
|
|
62
|
+
* The actual index from keys to anchor nodes.
|
|
63
|
+
*/
|
|
64
|
+
private readonly keyToNodes = new Map<TKey, AnchorNode[]>();
|
|
65
|
+
/**
|
|
66
|
+
* Maintained for efficient removal of anchor nodes from the index when updating their keys
|
|
67
|
+
*/
|
|
68
|
+
private readonly nodeToKey = new Map<AnchorNode, TKey>();
|
|
69
|
+
/**
|
|
70
|
+
* Keeps track of anchors for disposal.
|
|
71
|
+
*/
|
|
72
|
+
private readonly anchors = new Map<AnchorNode, Anchor[]>();
|
|
73
|
+
/**
|
|
74
|
+
* The key finder that is registered on the forest to keep this index updated, maintained
|
|
75
|
+
* here for deregistration on disposal
|
|
76
|
+
*/
|
|
77
|
+
private readonly keyFinder = this.acquireVisitor.bind(this);
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @param forest - the forest that is being indexed
|
|
81
|
+
* @param indexer - a function that retrieves the key finder based on a given schema or undefined if the schema does not have an associated key finder
|
|
82
|
+
* @param getValue - a pure and functional function that returns the associated value of one or more anchor nodes, can be used to map and filter the indexed anchor nodes
|
|
83
|
+
* so that the values returned from the index are more usable
|
|
84
|
+
* @param checkTreeStatus - a function that gets the tree status from an anchor node, used for filtering out detached nodes
|
|
85
|
+
*/
|
|
86
|
+
public constructor(
|
|
87
|
+
private readonly forest: IForestSubscription,
|
|
88
|
+
private readonly indexer: (
|
|
89
|
+
schemaId: TreeNodeSchemaIdentifier,
|
|
90
|
+
) => KeyFinder<TKey> | undefined,
|
|
91
|
+
private readonly getValue: (anchorNodes: TreeIndexNodes<AnchorNode>) => TValue | undefined,
|
|
92
|
+
private readonly checkTreeStatus: (node: AnchorNode) => TreeStatus | undefined,
|
|
93
|
+
) {
|
|
94
|
+
this.forest.registerAnnouncedVisitor(this.keyFinder);
|
|
95
|
+
|
|
96
|
+
const detachedFieldKeys: FieldKey[] = [];
|
|
97
|
+
const detachedFieldsCursor = forest.getCursorAboveDetachedFields();
|
|
98
|
+
forEachField(detachedFieldsCursor, (field) => {
|
|
99
|
+
detachedFieldKeys.push(field.getFieldKey());
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// index all existing trees (this includes the primary document tree and all other detached/removed trees)
|
|
103
|
+
for (const fieldKey of detachedFieldKeys) {
|
|
104
|
+
const cursor = forest.allocateCursor();
|
|
105
|
+
forest.tryMoveCursorToField({ fieldKey, parent: undefined }, cursor);
|
|
106
|
+
this.indexField(cursor);
|
|
107
|
+
cursor.free();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Creates an announced visitor that responds to edits to the forest and updates the index accordingly.
|
|
113
|
+
*/
|
|
114
|
+
private acquireVisitor(): AnnouncedVisitor {
|
|
115
|
+
this.checkNotDisposed(
|
|
116
|
+
"visitor getter should be deregistered from the forest when index is disposed",
|
|
117
|
+
);
|
|
118
|
+
let parentField: FieldKey | undefined;
|
|
119
|
+
let parent: UpPath | undefined;
|
|
120
|
+
|
|
121
|
+
return createAnnouncedVisitor({
|
|
122
|
+
// nodes (and their entire subtrees) are added to the index as soon as they are created
|
|
123
|
+
afterCreate: (content: ProtoNodes, destination: FieldKey) => {
|
|
124
|
+
const detachedCursor = this.forest.allocateCursor();
|
|
125
|
+
assert(
|
|
126
|
+
this.forest.tryMoveCursorToField(
|
|
127
|
+
{ fieldKey: destination, parent: undefined },
|
|
128
|
+
detachedCursor,
|
|
129
|
+
) === TreeNavigationResult.Ok,
|
|
130
|
+
0xa8a /* destination of created nodes must be a valid detached field */,
|
|
131
|
+
);
|
|
132
|
+
this.indexField(detachedCursor);
|
|
133
|
+
detachedCursor.free();
|
|
134
|
+
},
|
|
135
|
+
// when a replace happens, the keys of previously indexed nodes could be changed so we must re-index them
|
|
136
|
+
afterReplace: () => {
|
|
137
|
+
assert(parent !== undefined, 0xa8b /* must have a parent */);
|
|
138
|
+
const cursor = this.forest.allocateCursor();
|
|
139
|
+
this.forest.moveCursorToPath(parent, cursor);
|
|
140
|
+
assert(
|
|
141
|
+
cursor.mode === CursorLocationType.Nodes,
|
|
142
|
+
0xa8c /* replace should happen in a node */,
|
|
143
|
+
);
|
|
144
|
+
cursor.exitNode();
|
|
145
|
+
// we must re-index the spine because the key finders allow for any value under a subtree to be the key
|
|
146
|
+
// this means that a replace can cause the key for any node up its spine to be changed
|
|
147
|
+
this.indexSpine(cursor);
|
|
148
|
+
cursor.clear();
|
|
149
|
+
},
|
|
150
|
+
// the methods below are used to keep track of the path that has been traversed by the visitor
|
|
151
|
+
// this is required so that cursors can be moved to the correct location when index updates are required
|
|
152
|
+
enterNode(index: number): void {
|
|
153
|
+
assert(parentField !== undefined, 0xa8d /* must be in a field to enter node */);
|
|
154
|
+
|
|
155
|
+
parent = {
|
|
156
|
+
parent,
|
|
157
|
+
parentField,
|
|
158
|
+
parentIndex: index,
|
|
159
|
+
};
|
|
160
|
+
parentField = undefined;
|
|
161
|
+
},
|
|
162
|
+
exitNode(index: number): void {
|
|
163
|
+
assert(parent !== undefined, 0xa8e /* must have parent node */);
|
|
164
|
+
const temp = parent;
|
|
165
|
+
parentField = temp.parentField;
|
|
166
|
+
parent = temp.parent;
|
|
167
|
+
},
|
|
168
|
+
enterField: (key: FieldKey) => {
|
|
169
|
+
parentField = key;
|
|
170
|
+
},
|
|
171
|
+
exitField(key: FieldKey): void {
|
|
172
|
+
parentField = undefined;
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Returns the value associated with the given key if it has been indexed
|
|
179
|
+
*/
|
|
180
|
+
public get(key: TKey): TValue | undefined {
|
|
181
|
+
this.checkNotDisposed();
|
|
182
|
+
return this.getFilteredValue(this.keyToNodes.get(key));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Returns true iff the key exists in the index
|
|
187
|
+
*/
|
|
188
|
+
public has(key: TKey): boolean {
|
|
189
|
+
this.checkNotDisposed();
|
|
190
|
+
return this.get(key) !== undefined;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Returns the number of values that are indexed
|
|
195
|
+
*/
|
|
196
|
+
public get size(): number {
|
|
197
|
+
this.checkNotDisposed();
|
|
198
|
+
let s = 0;
|
|
199
|
+
for (const nodes of this.keyToNodes.values()) {
|
|
200
|
+
if (this.getFilteredValue(nodes) !== undefined) {
|
|
201
|
+
s += 1;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return s;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Returns all keys in the index
|
|
209
|
+
*/
|
|
210
|
+
public *keys(): IterableIterator<TKey> {
|
|
211
|
+
this.checkNotDisposed();
|
|
212
|
+
for (const [key, nodes] of this.keyToNodes.entries()) {
|
|
213
|
+
if (this.getFilteredValue(nodes) !== undefined) {
|
|
214
|
+
yield key;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Returns an iterable of values in the index
|
|
221
|
+
*/
|
|
222
|
+
public *values(): IterableIterator<TValue> {
|
|
223
|
+
this.checkNotDisposed();
|
|
224
|
+
for (const nodes of this.keyToNodes.values()) {
|
|
225
|
+
const filtered = this.getFilteredValue(nodes);
|
|
226
|
+
if (filtered !== undefined) {
|
|
227
|
+
yield filtered;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Returns an iterable of key, value pairs for every entry in the index
|
|
234
|
+
*/
|
|
235
|
+
public *entries(): IterableIterator<[TKey, TValue]> {
|
|
236
|
+
this.checkNotDisposed();
|
|
237
|
+
for (const [key, nodes] of this.keyToNodes.entries()) {
|
|
238
|
+
const filtered = this.getFilteredValue(nodes);
|
|
239
|
+
if (filtered !== undefined) {
|
|
240
|
+
yield [key, filtered];
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
public [Symbol.iterator](): IterableIterator<[TKey, TValue]> {
|
|
246
|
+
this.checkNotDisposed();
|
|
247
|
+
return this.entries();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Applies the provided callback to each entry in the index.
|
|
252
|
+
*/
|
|
253
|
+
public forEach(
|
|
254
|
+
callbackfn: (value: TValue, key: TKey, map: AnchorTreeIndex<TKey, TValue>) => void,
|
|
255
|
+
thisArg?: unknown,
|
|
256
|
+
): void {
|
|
257
|
+
this.checkNotDisposed();
|
|
258
|
+
for (const [key, nodes] of this.keyToNodes.entries()) {
|
|
259
|
+
const filtered = this.getFilteredValue(nodes);
|
|
260
|
+
if (filtered !== undefined) {
|
|
261
|
+
callbackfn.call(thisArg, filtered, key, this);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Returns an iterable of key, value pairs for every entry in the index, including ones that are detached.
|
|
268
|
+
* This function should only be used for testing purposes, it is not exposed as part of the public {@link TreeIndex} API.
|
|
269
|
+
*/
|
|
270
|
+
public *allEntries(): IterableIterator<[TKey, TValue]> {
|
|
271
|
+
this.checkNotDisposed();
|
|
272
|
+
for (const [key, nodes] of this.keyToNodes.entries()) {
|
|
273
|
+
const value = this.getValue(nodes as unknown as TreeIndexNodes<AnchorNode>);
|
|
274
|
+
if (value !== undefined) {
|
|
275
|
+
yield [key, value];
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
public dispose(): void {
|
|
281
|
+
this[disposeSymbol]();
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Disposes this index and all the anchors it holds onto.
|
|
286
|
+
*/
|
|
287
|
+
public [disposeSymbol](): void {
|
|
288
|
+
this.checkNotDisposed("index is already disposed");
|
|
289
|
+
for (const anchors of this.anchors.values()) {
|
|
290
|
+
for (const anchor of anchors) {
|
|
291
|
+
this.forest.forgetAnchor(anchor);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
this.keyToNodes.clear();
|
|
295
|
+
this.anchors.clear();
|
|
296
|
+
this.forest.deregisterAnnouncedVisitor(this.keyFinder);
|
|
297
|
+
this.disposed = true;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
private checkNotDisposed(errorMessage?: string): void {
|
|
301
|
+
if (this.disposed) {
|
|
302
|
+
if (errorMessage !== undefined) {
|
|
303
|
+
throw new Error(errorMessage);
|
|
304
|
+
}
|
|
305
|
+
assert(false, 0xa8f /* invalid operation on a disposed index */);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Given a cursor in node mode, indexes it.
|
|
311
|
+
*/
|
|
312
|
+
private indexNode(nodeCursor: ITreeSubscriptionCursor): void {
|
|
313
|
+
const keyFinder = getOrCreate(
|
|
314
|
+
this.keyFinders,
|
|
315
|
+
// the node schema type to look up
|
|
316
|
+
nodeCursor.type,
|
|
317
|
+
// if the indexer does not return a key finder for this schema, we cache a null value to indicate the indexer
|
|
318
|
+
// does not need to be called if this schema is encountered in the future
|
|
319
|
+
(schema) => this.indexer(schema) ?? null,
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
if (keyFinder !== null) {
|
|
323
|
+
const expectedPath = nodeCursor.getPath();
|
|
324
|
+
const key = keyFinder(nodeCursor);
|
|
325
|
+
// TODO: determine perf impact of this check, alternative is not doing it in which case (if the key finder is not pure and functional),
|
|
326
|
+
// an error may be thrown further down the line if the structure of the nodes aren't expected or the contents of the index could be inaccurate
|
|
327
|
+
if (!compareUpPaths(nodeCursor.getPath(), expectedPath)) {
|
|
328
|
+
throw new Error("key finder should be pure and functional");
|
|
329
|
+
}
|
|
330
|
+
const anchor = nodeCursor.buildAnchor();
|
|
331
|
+
const anchorNode = this.forest.anchors.locate(anchor) ?? fail("expected anchor node");
|
|
332
|
+
|
|
333
|
+
// check if this anchor node already exists in the index
|
|
334
|
+
const existingKey = this.nodeToKey.get(anchorNode);
|
|
335
|
+
if (existingKey !== undefined) {
|
|
336
|
+
// if the node already exists but has the same key, we return early
|
|
337
|
+
if (existingKey === key) {
|
|
338
|
+
this.forest.forgetAnchor(anchor);
|
|
339
|
+
return;
|
|
340
|
+
} else {
|
|
341
|
+
// if the node has a different key, we remove the existing one first because it means the key had been detached
|
|
342
|
+
this.removeAnchor(anchorNode, existingKey);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
getOrCreate(this.keyToNodes, key, () => []).push(anchorNode);
|
|
347
|
+
this.nodeToKey.set(anchorNode, key);
|
|
348
|
+
|
|
349
|
+
getOrCreate(this.anchors, anchorNode, () => []).push(anchor);
|
|
350
|
+
// when the anchor node is destroyed, delete it from the index
|
|
351
|
+
anchorNode.events.on("afterDestroy", () => {
|
|
352
|
+
this.removeAnchor(anchorNode, key);
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Given a cursor in field mode, recursively indexes all nodes under the field.
|
|
359
|
+
*/
|
|
360
|
+
private indexField(fieldCursor: ITreeSubscriptionCursor): void {
|
|
361
|
+
forEachNode(fieldCursor, (nodeCursor) => {
|
|
362
|
+
this.indexNode(nodeCursor);
|
|
363
|
+
|
|
364
|
+
forEachField(nodeCursor, (f) => {
|
|
365
|
+
this.indexField(f);
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Given a cursor in field mode, indexes all nodes under the field and then indexes all nodes up the spine.
|
|
372
|
+
*/
|
|
373
|
+
private indexSpine(cursor: ITreeSubscriptionCursor): void {
|
|
374
|
+
this.indexField(cursor);
|
|
375
|
+
|
|
376
|
+
if (keyAsDetachedField(cursor.getFieldKey()) !== rootField) {
|
|
377
|
+
cursor.exitField();
|
|
378
|
+
cursor.exitNode();
|
|
379
|
+
} else {
|
|
380
|
+
// return early if we're already at the root field
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// walk up the spine and index nodes until we reach the root
|
|
385
|
+
while (
|
|
386
|
+
cursor.mode === CursorLocationType.Fields &&
|
|
387
|
+
keyAsDetachedField(cursor.getFieldKey()) !== rootField
|
|
388
|
+
) {
|
|
389
|
+
forEachNode(cursor, (nodeCursor) => {
|
|
390
|
+
this.indexNode(nodeCursor);
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
cursor.exitField();
|
|
394
|
+
cursor.exitNode();
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
private removeAnchor(anchorNode: AnchorNode, key: TKey): void {
|
|
399
|
+
const indexedNodes = this.keyToNodes.get(key);
|
|
400
|
+
assert(
|
|
401
|
+
indexedNodes !== undefined,
|
|
402
|
+
0xa90 /* destroyed anchor node should be tracked by index */,
|
|
403
|
+
);
|
|
404
|
+
const index = indexedNodes.indexOf(anchorNode);
|
|
405
|
+
assert(index !== -1, 0xa91 /* destroyed anchor node should be tracked by index */);
|
|
406
|
+
const newNodes = filterNodes(indexedNodes, (n) => n !== anchorNode);
|
|
407
|
+
if (newNodes !== undefined && newNodes.length > 0) {
|
|
408
|
+
this.keyToNodes.set(key, newNodes);
|
|
409
|
+
} else {
|
|
410
|
+
this.keyToNodes.delete(key);
|
|
411
|
+
}
|
|
412
|
+
this.nodeToKey.delete(anchorNode);
|
|
413
|
+
assert(
|
|
414
|
+
this.anchors.delete(anchorNode),
|
|
415
|
+
0xa92 /* destroyed anchor should be tracked by index */,
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Filters out any anchor nodes that are detached and returns the value for the remaining nodes.
|
|
421
|
+
*/
|
|
422
|
+
private getFilteredValue(anchorNodes: AnchorNode[] | undefined): TValue | undefined {
|
|
423
|
+
const attachedNodes = filterNodes(anchorNodes, (anchorNode) => {
|
|
424
|
+
const nodeStatus = this.checkTreeStatus(anchorNode);
|
|
425
|
+
return nodeStatus === TreeStatus.InDocument;
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
if (attachedNodes !== undefined && hasElement(attachedNodes)) {
|
|
429
|
+
return this.getValue(attachedNodes);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Filters the given anchor nodes based on the given filter function.
|
|
436
|
+
*/
|
|
437
|
+
function filterNodes(
|
|
438
|
+
anchorNodes: readonly AnchorNode[] | undefined,
|
|
439
|
+
filter: (node: AnchorNode) => boolean,
|
|
440
|
+
): AnchorNode[] | undefined {
|
|
441
|
+
if (anchorNodes !== undefined) {
|
|
442
|
+
return anchorNodes.filter(filter);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return undefined;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Checks that an array is of the type {@link TreeIndexNodes} and has at least one element.
|
|
450
|
+
*/
|
|
451
|
+
export function hasElement<T>(array: readonly T[]): array is TreeIndexNodes<T> {
|
|
452
|
+
return array.length >= 1;
|
|
453
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
AnchorTreeIndex,
|
|
8
|
+
type KeyFinder,
|
|
9
|
+
hasElement,
|
|
10
|
+
} from "./anchorTreeIndex.js";
|
|
11
|
+
export type { TreeIndex, TreeIndexKey, TreeIndexNodes } from "./types.js";
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { IFluidHandle } from "@fluidframework/core-interfaces";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* an array of nodes that is guaranteed to have at least one element
|
|
10
|
+
*
|
|
11
|
+
* @alpha
|
|
12
|
+
*/
|
|
13
|
+
export type TreeIndexNodes<TNode> = readonly [first: TNode, ...rest: TNode[]];
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Value that may be used as keys in a {@link TreeIndex}.
|
|
17
|
+
*
|
|
18
|
+
* @privateRemarks
|
|
19
|
+
* no-new-null is disabled for this type so that it supports the TreeValue type.
|
|
20
|
+
*
|
|
21
|
+
* @alpha
|
|
22
|
+
*/
|
|
23
|
+
// eslint-disable-next-line @rushstack/no-new-null
|
|
24
|
+
export type TreeIndexKey = number | string | boolean | IFluidHandle | null;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A index where values are keyed on {@link TreeIndexKey}s.
|
|
28
|
+
*
|
|
29
|
+
* @alpha
|
|
30
|
+
*/
|
|
31
|
+
export interface TreeIndex<TKey extends TreeIndexKey, TValue>
|
|
32
|
+
extends ReadonlyMap<TKey, TValue> {
|
|
33
|
+
/**
|
|
34
|
+
* Disposes the index such that it can no longer be used and receives no updates from the forest
|
|
35
|
+
*/
|
|
36
|
+
dispose(): void;
|
|
37
|
+
}
|
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
7
|
+
import { createEmitter } from "@fluid-internal/client-utils";
|
|
8
|
+
import type { Listenable } from "@fluidframework/core-interfaces";
|
|
7
9
|
|
|
8
10
|
import {
|
|
9
11
|
type Anchor,
|
|
10
12
|
AnchorSet,
|
|
13
|
+
type AnnouncedVisitor,
|
|
11
14
|
type CursorLocationType,
|
|
12
15
|
type DeltaVisitor,
|
|
13
16
|
type DetachedField,
|
|
@@ -31,9 +34,9 @@ import {
|
|
|
31
34
|
type UpPath,
|
|
32
35
|
type Value,
|
|
33
36
|
aboveRootPlaceholder,
|
|
37
|
+
combineVisitors,
|
|
34
38
|
deepCopyMapTree,
|
|
35
39
|
} from "../../core/index.js";
|
|
36
|
-
import { createEmitter, type Listenable } from "../../events/index.js";
|
|
37
40
|
import {
|
|
38
41
|
assertNonNegativeSafeInteger,
|
|
39
42
|
assertValidIndex,
|
|
@@ -72,6 +75,7 @@ export class ObjectForest implements IEditableForest {
|
|
|
72
75
|
|
|
73
76
|
// All cursors that are in the "Current" state. Must be empty when editing.
|
|
74
77
|
public readonly currentCursors: Set<Cursor> = new Set();
|
|
78
|
+
private readonly deltaVisitors: Set<() => AnnouncedVisitor> = new Set();
|
|
75
79
|
|
|
76
80
|
readonly #events = createEmitter<ForestEvents>();
|
|
77
81
|
public readonly events: Listenable<ForestEvents> = this.#events;
|
|
@@ -254,9 +258,23 @@ export class ObjectForest implements IEditableForest {
|
|
|
254
258
|
}
|
|
255
259
|
}
|
|
256
260
|
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
|
|
261
|
+
const forestVisitor = new Visitor(this);
|
|
262
|
+
const announcedVisitors: AnnouncedVisitor[] = [];
|
|
263
|
+
this.deltaVisitors.forEach((getVisitor) => announcedVisitors.push(getVisitor()));
|
|
264
|
+
const combinedVisitor = combineVisitors(
|
|
265
|
+
[forestVisitor, ...announcedVisitors],
|
|
266
|
+
announcedVisitors,
|
|
267
|
+
);
|
|
268
|
+
this.activeVisitor = combinedVisitor;
|
|
269
|
+
return combinedVisitor;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
public registerAnnouncedVisitor(visitor: () => AnnouncedVisitor): void {
|
|
273
|
+
this.deltaVisitors.add(visitor);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
public deregisterAnnouncedVisitor(visitor: () => AnnouncedVisitor): void {
|
|
277
|
+
this.deltaVisitors.delete(visitor);
|
|
260
278
|
}
|
|
261
279
|
|
|
262
280
|
private nextRange = 0;
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { assert, unreachableCase
|
|
6
|
+
import { assert, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
7
7
|
|
|
8
8
|
import type { RevisionTag } from "../../core/index.js";
|
|
9
|
-
import { type IdAllocator, type Mutable, fail } from "../../util/index.js";
|
|
9
|
+
import { type IdAllocator, type Mutable, fail, hasSingle } from "../../util/index.js";
|
|
10
10
|
import {
|
|
11
11
|
type CrossFieldManager,
|
|
12
12
|
CrossFieldTarget,
|
|
@@ -257,11 +257,11 @@ function invertMark(
|
|
|
257
257
|
}
|
|
258
258
|
|
|
259
259
|
assert(
|
|
260
|
-
detachInverses
|
|
260
|
+
hasSingle(detachInverses),
|
|
261
261
|
0x80d /* Only expected MoveIn marks to be split when inverting */,
|
|
262
262
|
);
|
|
263
263
|
|
|
264
|
-
let detachInverse = detachInverses[0]
|
|
264
|
+
let detachInverse = detachInverses[0];
|
|
265
265
|
assert(isAttach(detachInverse), 0x80e /* Inverse of a detach should be an attach */);
|
|
266
266
|
|
|
267
267
|
const inverses: Mark[] = [];
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { assert, unreachableCase
|
|
6
|
+
import { assert, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
type DeltaDetachedNodeChanges,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
type DeltaMark,
|
|
13
13
|
areEqualChangeAtomIds,
|
|
14
14
|
} from "../../core/index.js";
|
|
15
|
-
import type
|
|
15
|
+
import { getLast, hasSome, type Mutable } from "../../util/index.js";
|
|
16
16
|
import { nodeIdFromChangeAtom } from "../deltaUtils.js";
|
|
17
17
|
|
|
18
18
|
import { isMoveIn, isMoveOut } from "./moveEffectTable.js";
|
|
@@ -176,8 +176,8 @@ export function sequenceFieldToDelta(
|
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
// Remove trailing no-op marks
|
|
179
|
-
while (local
|
|
180
|
-
const lastMark = local
|
|
179
|
+
while (hasSome(local)) {
|
|
180
|
+
const lastMark = getLast(local);
|
|
181
181
|
if (
|
|
182
182
|
lastMark.attach !== undefined ||
|
|
183
183
|
lastMark.detach !== undefined ||
|
package/src/index.ts
CHANGED
|
@@ -29,19 +29,24 @@ export {
|
|
|
29
29
|
MapNodeStoredSchema,
|
|
30
30
|
LeafNodeStoredSchema,
|
|
31
31
|
type RevertibleFactory,
|
|
32
|
+
type RevertibleAlphaFactory,
|
|
33
|
+
type RevertibleAlpha,
|
|
32
34
|
} from "./core/index.js";
|
|
33
35
|
export { type Brand } from "./util/index.js";
|
|
34
36
|
|
|
35
|
-
export {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
} from "
|
|
37
|
+
export type {
|
|
38
|
+
Listeners,
|
|
39
|
+
IsListener,
|
|
40
|
+
Listenable,
|
|
41
|
+
Off,
|
|
42
|
+
} from "@fluidframework/core-interfaces";
|
|
41
43
|
|
|
42
44
|
export {
|
|
43
45
|
TreeStatus,
|
|
44
46
|
TreeCompressionStrategy,
|
|
47
|
+
type TreeIndex,
|
|
48
|
+
type TreeIndexKey,
|
|
49
|
+
type TreeIndexNodes,
|
|
45
50
|
} from "./feature-libraries/index.js";
|
|
46
51
|
|
|
47
52
|
export {
|
|
@@ -126,6 +131,11 @@ export {
|
|
|
126
131
|
// Recursive Schema APIs
|
|
127
132
|
type ValidateRecursiveSchema,
|
|
128
133
|
type FixRecursiveArraySchema,
|
|
134
|
+
// Index APIs
|
|
135
|
+
type SimpleTreeIndex,
|
|
136
|
+
type IdentifierIndex,
|
|
137
|
+
createSimpleTreeIndex,
|
|
138
|
+
createIdentifierIndex,
|
|
129
139
|
// experimental @alpha APIs:
|
|
130
140
|
adaptEnum,
|
|
131
141
|
enumFromStrings,
|
package/src/packageVersion.ts
CHANGED