@fluidframework/tree 2.1.0-276985 → 2.1.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/.eslintrc.cjs +7 -0
- package/.vscode/Tree.code-workspace +9 -2
- package/CHANGELOG.md +38 -0
- package/README.md +55 -12
- package/api-report/tree.alpha.api.md +2 -1
- package/api-report/tree.beta.api.md +2 -1
- package/api-report/tree.public.api.md +2 -1
- package/beta.d.ts +1 -1
- package/dist/beta.d.ts +1 -1
- package/dist/core/forest/editableForest.d.ts +6 -3
- package/dist/core/forest/editableForest.d.ts.map +1 -1
- package/dist/core/forest/editableForest.js +16 -4
- package/dist/core/forest/editableForest.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/rebase/index.d.ts +1 -1
- package/dist/core/rebase/index.d.ts.map +1 -1
- package/dist/core/rebase/index.js +3 -1
- package/dist/core/rebase/index.js.map +1 -1
- package/dist/core/rebase/types.d.ts +2 -0
- package/dist/core/rebase/types.d.ts.map +1 -1
- package/dist/core/rebase/types.js +9 -1
- package/dist/core/rebase/types.js.map +1 -1
- package/dist/core/tree/anchorSet.d.ts +1 -0
- package/dist/core/tree/anchorSet.d.ts.map +1 -1
- package/dist/core/tree/anchorSet.js +13 -0
- package/dist/core/tree/anchorSet.js.map +1 -1
- package/dist/core/tree/detachedFieldIndex.d.ts +48 -11
- package/dist/core/tree/detachedFieldIndex.d.ts.map +1 -1
- package/dist/core/tree/detachedFieldIndex.js +144 -20
- package/dist/core/tree/detachedFieldIndex.js.map +1 -1
- package/dist/core/tree/detachedFieldIndexCodec.d.ts.map +1 -1
- package/dist/core/tree/detachedFieldIndexCodec.js +13 -4
- package/dist/core/tree/detachedFieldIndexCodec.js.map +1 -1
- package/dist/core/tree/detachedFieldIndexFormat.d.ts +1 -1
- package/dist/core/tree/detachedFieldIndexFormat.d.ts.map +1 -1
- package/dist/core/tree/detachedFieldIndexFormat.js.map +1 -1
- package/dist/core/tree/detachedFieldIndexTypes.d.ts +39 -4
- package/dist/core/tree/detachedFieldIndexTypes.d.ts.map +1 -1
- package/dist/core/tree/detachedFieldIndexTypes.js.map +1 -1
- package/dist/core/tree/index.d.ts +2 -1
- package/dist/core/tree/index.d.ts.map +1 -1
- package/dist/core/tree/index.js.map +1 -1
- package/dist/core/tree/visitDelta.d.ts +3 -1
- package/dist/core/tree/visitDelta.d.ts.map +1 -1
- package/dist/core/tree/visitDelta.js +31 -15
- package/dist/core/tree/visitDelta.js.map +1 -1
- package/dist/core/tree/visitorUtils.d.ts +3 -3
- package/dist/core/tree/visitorUtils.d.ts.map +1 -1
- package/dist/core/tree/visitorUtils.js +4 -4
- package/dist/core/tree/visitorUtils.js.map +1 -1
- package/dist/events/events.d.ts +4 -1
- package/dist/events/events.d.ts.map +1 -1
- package/dist/events/events.js.map +1 -1
- package/dist/feature-libraries/default-schema/defaultEditBuilder.js +1 -1
- package/dist/feature-libraries/default-schema/defaultEditBuilder.js.map +1 -1
- package/dist/feature-libraries/default-schema/defaultFieldKinds.d.ts.map +1 -1
- package/dist/feature-libraries/default-schema/defaultFieldKinds.js +1 -0
- package/dist/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
- package/dist/feature-libraries/editableTreeBinder.js +1 -1
- package/dist/feature-libraries/editableTreeBinder.js.map +1 -1
- package/dist/feature-libraries/flex-map-tree/mapTreeNode.d.ts +1 -10
- package/dist/feature-libraries/flex-map-tree/mapTreeNode.d.ts.map +1 -1
- package/dist/feature-libraries/flex-map-tree/mapTreeNode.js +0 -72
- package/dist/feature-libraries/flex-map-tree/mapTreeNode.js.map +1 -1
- package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts +1 -51
- package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/flexTreeTypes.js +0 -2
- package/dist/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
- package/dist/feature-libraries/flex-tree/index.d.ts +3 -2
- package/dist/feature-libraries/flex-tree/index.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/index.js +5 -1
- package/dist/feature-libraries/flex-tree/index.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyEntity.d.ts +1 -2
- package/dist/feature-libraries/flex-tree/lazyEntity.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyEntity.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.d.ts +1 -6
- package/dist/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.js +11 -32
- package/dist/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyNode.d.ts +1 -5
- package/dist/feature-libraries/flex-tree/lazyNode.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyNode.js +0 -30
- package/dist/feature-libraries/flex-tree/lazyNode.js.map +1 -1
- package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
- package/dist/feature-libraries/forest-summary/forestSummarizer.js +1 -1
- package/dist/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
- package/dist/feature-libraries/index.d.ts +3 -3
- package/dist/feature-libraries/index.d.ts.map +1 -1
- package/dist/feature-libraries/index.js +6 -3
- package/dist/feature-libraries/index.js.map +1 -1
- package/dist/feature-libraries/modular-schema/crossFieldQueries.d.ts +11 -0
- package/dist/feature-libraries/modular-schema/crossFieldQueries.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/crossFieldQueries.js.map +1 -1
- package/dist/feature-libraries/modular-schema/discrepancies.d.ts +96 -0
- package/dist/feature-libraries/modular-schema/discrepancies.d.ts.map +1 -0
- package/dist/feature-libraries/modular-schema/discrepancies.js +264 -0
- package/dist/feature-libraries/modular-schema/discrepancies.js.map +1 -0
- package/dist/feature-libraries/modular-schema/fieldChangeHandler.d.ts +9 -2
- package/dist/feature-libraries/modular-schema/fieldChangeHandler.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/fieldChangeHandler.js.map +1 -1
- package/dist/feature-libraries/modular-schema/genericFieldKind.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/genericFieldKind.js +3 -0
- package/dist/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
- package/dist/feature-libraries/modular-schema/index.d.ts +2 -1
- package/dist/feature-libraries/modular-schema/index.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/index.js +3 -1
- package/dist/feature-libraries/modular-schema/index.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.js +42 -26
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts +51 -2
- package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.js +827 -245
- package/dist/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFormat.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFormat.js +2 -0
- package/dist/feature-libraries/modular-schema/modularChangeFormat.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts +44 -1
- package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
- package/dist/feature-libraries/node-key/index.d.ts +0 -1
- package/dist/feature-libraries/node-key/index.d.ts.map +1 -1
- package/dist/feature-libraries/node-key/index.js +1 -3
- package/dist/feature-libraries/node-key/index.js.map +1 -1
- package/dist/feature-libraries/object-forest/objectForest.d.ts +3 -2
- package/dist/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
- package/dist/feature-libraries/object-forest/objectForest.js +5 -4
- package/dist/feature-libraries/object-forest/objectForest.js.map +1 -1
- package/dist/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
- package/dist/feature-libraries/optional-field/optionalField.js +1 -0
- package/dist/feature-libraries/optional-field/optionalField.js.map +1 -1
- package/dist/feature-libraries/sequence-field/index.d.ts +1 -1
- package/dist/feature-libraries/sequence-field/index.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/index.js +1 -2
- package/dist/feature-libraries/sequence-field/index.js.map +1 -1
- package/dist/feature-libraries/sequence-field/invert.js +1 -1
- package/dist/feature-libraries/sequence-field/invert.js.map +1 -1
- package/dist/feature-libraries/sequence-field/rebase.js +6 -1
- package/dist/feature-libraries/sequence-field/rebase.js.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldChangeHandler.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldChangeHandler.js +1 -0
- package/dist/feature-libraries/sequence-field/sequenceFieldChangeHandler.js.map +1 -1
- package/dist/feature-libraries/sequence-field/utils.d.ts +2 -17
- package/dist/feature-libraries/sequence-field/utils.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/utils.js +31 -39
- package/dist/feature-libraries/sequence-field/utils.js.map +1 -1
- package/dist/feature-libraries/typed-schema/typedTreeSchema.d.ts +1 -0
- package/dist/feature-libraries/typed-schema/typedTreeSchema.d.ts.map +1 -1
- package/dist/feature-libraries/typed-schema/typedTreeSchema.js +2 -0
- package/dist/feature-libraries/typed-schema/typedTreeSchema.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/public.d.ts +1 -1
- package/dist/shared-tree/schematizingTreeView.d.ts +4 -2
- package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/dist/shared-tree/schematizingTreeView.js +240 -184
- package/dist/shared-tree/schematizingTreeView.js.map +1 -1
- package/dist/shared-tree/sharedTree.d.ts +5 -1
- package/dist/shared-tree/sharedTree.d.ts.map +1 -1
- package/dist/shared-tree/sharedTree.js +157 -90
- package/dist/shared-tree/sharedTree.js.map +1 -1
- package/dist/shared-tree/sharedTreeChangeEnricher.js +1 -1
- package/dist/shared-tree/sharedTreeChangeEnricher.js.map +1 -1
- package/dist/shared-tree/treeApi.js +1 -1
- package/dist/shared-tree/treeApi.js.map +1 -1
- package/dist/shared-tree/treeCheckout.d.ts +10 -1
- package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
- package/dist/shared-tree/treeCheckout.js +47 -3
- package/dist/shared-tree/treeCheckout.js.map +1 -1
- package/dist/shared-tree/treeView.d.ts.map +1 -1
- package/dist/shared-tree/treeView.js +7 -3
- package/dist/shared-tree/treeView.js.map +1 -1
- package/dist/shared-tree-core/branch.d.ts +6 -0
- package/dist/shared-tree-core/branch.d.ts.map +1 -1
- package/dist/shared-tree-core/branch.js +3 -0
- package/dist/shared-tree-core/branch.js.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.d.ts +8 -6
- package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.js +271 -209
- package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/dist/simple-tree/arrayNode.d.ts +4 -0
- package/dist/simple-tree/arrayNode.d.ts.map +1 -1
- package/dist/simple-tree/arrayNode.js +36 -19
- package/dist/simple-tree/arrayNode.js.map +1 -1
- package/dist/simple-tree/index.d.ts +3 -3
- package/dist/simple-tree/index.d.ts.map +1 -1
- package/dist/simple-tree/index.js +2 -1
- package/dist/simple-tree/index.js.map +1 -1
- package/dist/simple-tree/leafNodeSchema.d.ts +22 -1
- package/dist/simple-tree/leafNodeSchema.d.ts.map +1 -1
- package/dist/simple-tree/leafNodeSchema.js +2 -1
- package/dist/simple-tree/leafNodeSchema.js.map +1 -1
- package/dist/simple-tree/mapNode.d.ts.map +1 -1
- package/dist/simple-tree/mapNode.js.map +1 -1
- package/dist/simple-tree/objectNode.d.ts.map +1 -1
- package/dist/simple-tree/objectNode.js +2 -1
- package/dist/simple-tree/objectNode.js.map +1 -1
- package/dist/simple-tree/proxies.d.ts.map +1 -1
- package/dist/simple-tree/proxies.js +9 -25
- package/dist/simple-tree/proxies.js.map +1 -1
- package/dist/simple-tree/proxyBinding.d.ts +4 -0
- package/dist/simple-tree/proxyBinding.d.ts.map +1 -1
- package/dist/simple-tree/proxyBinding.js +23 -1
- package/dist/simple-tree/proxyBinding.js.map +1 -1
- package/dist/simple-tree/schemaFactory.d.ts +16 -1
- package/dist/simple-tree/schemaFactory.d.ts.map +1 -1
- package/dist/simple-tree/schemaFactory.js +32 -4
- package/dist/simple-tree/schemaFactory.js.map +1 -1
- package/dist/simple-tree/schemaTypes.d.ts +36 -1
- package/dist/simple-tree/schemaTypes.d.ts.map +1 -1
- package/dist/simple-tree/schemaTypes.js.map +1 -1
- package/dist/simple-tree/toFlexSchema.d.ts +2 -2
- package/dist/simple-tree/toFlexSchema.d.ts.map +1 -1
- package/dist/simple-tree/toFlexSchema.js +3 -2
- package/dist/simple-tree/toFlexSchema.js.map +1 -1
- package/dist/simple-tree/tree.d.ts +4 -1
- package/dist/simple-tree/tree.d.ts.map +1 -1
- package/dist/simple-tree/tree.js +48 -1
- package/dist/simple-tree/tree.js.map +1 -1
- package/dist/simple-tree/treeNodeApi.d.ts +2 -75
- package/dist/simple-tree/treeNodeApi.d.ts.map +1 -1
- package/dist/simple-tree/treeNodeApi.js +17 -25
- package/dist/simple-tree/treeNodeApi.js.map +1 -1
- package/dist/simple-tree/treeNodeKernel.d.ts +26 -0
- package/dist/simple-tree/treeNodeKernel.d.ts.map +1 -0
- package/dist/simple-tree/treeNodeKernel.js +83 -0
- package/dist/simple-tree/treeNodeKernel.js.map +1 -0
- package/dist/simple-tree/types.d.ts +95 -3
- package/dist/simple-tree/types.d.ts.map +1 -1
- package/dist/simple-tree/types.js +120 -21
- package/dist/simple-tree/types.js.map +1 -1
- package/dist/util/breakable.d.ts +83 -0
- package/dist/util/breakable.d.ts.map +1 -0
- package/dist/util/breakable.js +178 -0
- package/dist/util/breakable.js.map +1 -0
- package/dist/util/index.d.ts +3 -2
- package/dist/util/index.d.ts.map +1 -1
- package/dist/util/index.js +9 -2
- package/dist/util/index.js.map +1 -1
- package/dist/util/nestedMap.d.ts +17 -3
- package/dist/util/nestedMap.d.ts.map +1 -1
- package/dist/util/nestedMap.js +21 -1
- package/dist/util/nestedMap.js.map +1 -1
- package/dist/util/utils.d.ts +7 -0
- package/dist/util/utils.d.ts.map +1 -1
- package/dist/util/utils.js +15 -1
- package/dist/util/utils.js.map +1 -1
- package/internal.d.ts +1 -1
- package/lib/beta.d.ts +1 -1
- package/lib/core/forest/editableForest.d.ts +6 -3
- package/lib/core/forest/editableForest.d.ts.map +1 -1
- package/lib/core/forest/editableForest.js +17 -5
- package/lib/core/forest/editableForest.js.map +1 -1
- 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/rebase/index.d.ts +1 -1
- package/lib/core/rebase/index.d.ts.map +1 -1
- package/lib/core/rebase/index.js +1 -1
- package/lib/core/rebase/index.js.map +1 -1
- package/lib/core/rebase/types.d.ts +2 -0
- package/lib/core/rebase/types.d.ts.map +1 -1
- package/lib/core/rebase/types.js +7 -1
- package/lib/core/rebase/types.js.map +1 -1
- package/lib/core/tree/anchorSet.d.ts +1 -0
- package/lib/core/tree/anchorSet.d.ts.map +1 -1
- package/lib/core/tree/anchorSet.js +13 -0
- package/lib/core/tree/anchorSet.js.map +1 -1
- package/lib/core/tree/detachedFieldIndex.d.ts +48 -11
- package/lib/core/tree/detachedFieldIndex.d.ts.map +1 -1
- package/lib/core/tree/detachedFieldIndex.js +145 -21
- package/lib/core/tree/detachedFieldIndex.js.map +1 -1
- package/lib/core/tree/detachedFieldIndexCodec.d.ts.map +1 -1
- package/lib/core/tree/detachedFieldIndexCodec.js +13 -4
- package/lib/core/tree/detachedFieldIndexCodec.js.map +1 -1
- package/lib/core/tree/detachedFieldIndexFormat.d.ts +1 -1
- package/lib/core/tree/detachedFieldIndexFormat.d.ts.map +1 -1
- package/lib/core/tree/detachedFieldIndexFormat.js.map +1 -1
- package/lib/core/tree/detachedFieldIndexTypes.d.ts +39 -4
- package/lib/core/tree/detachedFieldIndexTypes.d.ts.map +1 -1
- package/lib/core/tree/detachedFieldIndexTypes.js.map +1 -1
- package/lib/core/tree/index.d.ts +2 -1
- package/lib/core/tree/index.d.ts.map +1 -1
- package/lib/core/tree/index.js.map +1 -1
- package/lib/core/tree/visitDelta.d.ts +3 -1
- package/lib/core/tree/visitDelta.d.ts.map +1 -1
- package/lib/core/tree/visitDelta.js +31 -15
- package/lib/core/tree/visitDelta.js.map +1 -1
- package/lib/core/tree/visitorUtils.d.ts +3 -3
- package/lib/core/tree/visitorUtils.d.ts.map +1 -1
- package/lib/core/tree/visitorUtils.js +4 -4
- package/lib/core/tree/visitorUtils.js.map +1 -1
- package/lib/events/events.d.ts +4 -1
- package/lib/events/events.d.ts.map +1 -1
- package/lib/events/events.js.map +1 -1
- package/lib/feature-libraries/default-schema/defaultEditBuilder.js +1 -1
- package/lib/feature-libraries/default-schema/defaultEditBuilder.js.map +1 -1
- package/lib/feature-libraries/default-schema/defaultFieldKinds.d.ts.map +1 -1
- package/lib/feature-libraries/default-schema/defaultFieldKinds.js +1 -0
- package/lib/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
- package/lib/feature-libraries/editableTreeBinder.js +1 -1
- package/lib/feature-libraries/editableTreeBinder.js.map +1 -1
- package/lib/feature-libraries/flex-map-tree/mapTreeNode.d.ts +1 -10
- package/lib/feature-libraries/flex-map-tree/mapTreeNode.d.ts.map +1 -1
- package/lib/feature-libraries/flex-map-tree/mapTreeNode.js +2 -74
- package/lib/feature-libraries/flex-map-tree/mapTreeNode.js.map +1 -1
- package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts +1 -51
- package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/flexTreeTypes.js +0 -2
- package/lib/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
- package/lib/feature-libraries/flex-tree/index.d.ts +3 -2
- package/lib/feature-libraries/flex-tree/index.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/index.js +2 -1
- package/lib/feature-libraries/flex-tree/index.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyEntity.d.ts +1 -2
- package/lib/feature-libraries/flex-tree/lazyEntity.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyEntity.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.d.ts +1 -6
- package/lib/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.js +13 -34
- package/lib/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyNode.d.ts +1 -5
- package/lib/feature-libraries/flex-tree/lazyNode.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyNode.js +3 -33
- package/lib/feature-libraries/flex-tree/lazyNode.js.map +1 -1
- package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
- package/lib/feature-libraries/forest-summary/forestSummarizer.js +1 -1
- package/lib/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
- package/lib/feature-libraries/index.d.ts +3 -3
- package/lib/feature-libraries/index.d.ts.map +1 -1
- package/lib/feature-libraries/index.js +3 -3
- package/lib/feature-libraries/index.js.map +1 -1
- package/lib/feature-libraries/modular-schema/crossFieldQueries.d.ts +11 -0
- package/lib/feature-libraries/modular-schema/crossFieldQueries.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/crossFieldQueries.js.map +1 -1
- package/lib/feature-libraries/modular-schema/discrepancies.d.ts +96 -0
- package/lib/feature-libraries/modular-schema/discrepancies.d.ts.map +1 -0
- package/lib/feature-libraries/modular-schema/discrepancies.js +260 -0
- package/lib/feature-libraries/modular-schema/discrepancies.js.map +1 -0
- package/lib/feature-libraries/modular-schema/fieldChangeHandler.d.ts +9 -2
- package/lib/feature-libraries/modular-schema/fieldChangeHandler.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/fieldChangeHandler.js.map +1 -1
- package/lib/feature-libraries/modular-schema/genericFieldKind.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/genericFieldKind.js +3 -0
- package/lib/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
- package/lib/feature-libraries/modular-schema/index.d.ts +2 -1
- package/lib/feature-libraries/modular-schema/index.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/index.js +1 -0
- package/lib/feature-libraries/modular-schema/index.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.js +42 -26
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts +51 -2
- package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFamily.js +826 -247
- package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFormat.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFormat.js +2 -0
- package/lib/feature-libraries/modular-schema/modularChangeFormat.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts +44 -1
- package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
- package/lib/feature-libraries/node-key/index.d.ts +0 -1
- package/lib/feature-libraries/node-key/index.d.ts.map +1 -1
- package/lib/feature-libraries/node-key/index.js +0 -1
- package/lib/feature-libraries/node-key/index.js.map +1 -1
- package/lib/feature-libraries/object-forest/objectForest.d.ts +3 -2
- package/lib/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
- package/lib/feature-libraries/object-forest/objectForest.js +5 -4
- package/lib/feature-libraries/object-forest/objectForest.js.map +1 -1
- package/lib/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
- package/lib/feature-libraries/optional-field/optionalField.js +1 -0
- package/lib/feature-libraries/optional-field/optionalField.js.map +1 -1
- package/lib/feature-libraries/sequence-field/index.d.ts +1 -1
- package/lib/feature-libraries/sequence-field/index.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/index.js +1 -1
- package/lib/feature-libraries/sequence-field/index.js.map +1 -1
- package/lib/feature-libraries/sequence-field/invert.js +1 -1
- package/lib/feature-libraries/sequence-field/invert.js.map +1 -1
- package/lib/feature-libraries/sequence-field/rebase.js +6 -1
- package/lib/feature-libraries/sequence-field/rebase.js.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldChangeHandler.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldChangeHandler.js +2 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldChangeHandler.js.map +1 -1
- package/lib/feature-libraries/sequence-field/utils.d.ts +2 -17
- package/lib/feature-libraries/sequence-field/utils.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/utils.js +31 -39
- package/lib/feature-libraries/sequence-field/utils.js.map +1 -1
- package/lib/feature-libraries/typed-schema/typedTreeSchema.d.ts +1 -0
- package/lib/feature-libraries/typed-schema/typedTreeSchema.d.ts.map +1 -1
- package/lib/feature-libraries/typed-schema/typedTreeSchema.js +4 -2
- package/lib/feature-libraries/typed-schema/typedTreeSchema.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/public.d.ts +1 -1
- package/lib/shared-tree/schematizingTreeView.d.ts +4 -2
- package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/lib/shared-tree/schematizingTreeView.js +242 -185
- package/lib/shared-tree/schematizingTreeView.js.map +1 -1
- package/lib/shared-tree/sharedTree.d.ts +5 -1
- package/lib/shared-tree/sharedTree.d.ts.map +1 -1
- package/lib/shared-tree/sharedTree.js +158 -90
- package/lib/shared-tree/sharedTree.js.map +1 -1
- package/lib/shared-tree/sharedTreeChangeEnricher.js +1 -1
- package/lib/shared-tree/sharedTreeChangeEnricher.js.map +1 -1
- package/lib/shared-tree/treeApi.js +1 -1
- package/lib/shared-tree/treeApi.js.map +1 -1
- package/lib/shared-tree/treeCheckout.d.ts +10 -1
- package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
- package/lib/shared-tree/treeCheckout.js +47 -3
- package/lib/shared-tree/treeCheckout.js.map +1 -1
- package/lib/shared-tree/treeView.d.ts.map +1 -1
- package/lib/shared-tree/treeView.js +4 -0
- package/lib/shared-tree/treeView.js.map +1 -1
- package/lib/shared-tree-core/branch.d.ts +6 -0
- package/lib/shared-tree-core/branch.d.ts.map +1 -1
- package/lib/shared-tree-core/branch.js +3 -0
- package/lib/shared-tree-core/branch.js.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.d.ts +8 -6
- package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.js +273 -210
- package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/lib/simple-tree/arrayNode.d.ts +4 -0
- package/lib/simple-tree/arrayNode.d.ts.map +1 -1
- package/lib/simple-tree/arrayNode.js +39 -22
- package/lib/simple-tree/arrayNode.js.map +1 -1
- package/lib/simple-tree/index.d.ts +3 -3
- 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/leafNodeSchema.d.ts +22 -1
- package/lib/simple-tree/leafNodeSchema.d.ts.map +1 -1
- package/lib/simple-tree/leafNodeSchema.js +1 -1
- package/lib/simple-tree/leafNodeSchema.js.map +1 -1
- package/lib/simple-tree/mapNode.d.ts.map +1 -1
- package/lib/simple-tree/mapNode.js.map +1 -1
- package/lib/simple-tree/objectNode.d.ts.map +1 -1
- package/lib/simple-tree/objectNode.js +3 -2
- package/lib/simple-tree/objectNode.js.map +1 -1
- package/lib/simple-tree/proxies.d.ts.map +1 -1
- package/lib/simple-tree/proxies.js +9 -25
- package/lib/simple-tree/proxies.js.map +1 -1
- package/lib/simple-tree/proxyBinding.d.ts +4 -0
- package/lib/simple-tree/proxyBinding.d.ts.map +1 -1
- package/lib/simple-tree/proxyBinding.js +19 -0
- package/lib/simple-tree/proxyBinding.js.map +1 -1
- package/lib/simple-tree/schemaFactory.d.ts +16 -1
- package/lib/simple-tree/schemaFactory.d.ts.map +1 -1
- package/lib/simple-tree/schemaFactory.js +30 -3
- package/lib/simple-tree/schemaFactory.js.map +1 -1
- package/lib/simple-tree/schemaTypes.d.ts +36 -1
- package/lib/simple-tree/schemaTypes.d.ts.map +1 -1
- package/lib/simple-tree/schemaTypes.js.map +1 -1
- package/lib/simple-tree/toFlexSchema.d.ts +2 -2
- package/lib/simple-tree/toFlexSchema.d.ts.map +1 -1
- package/lib/simple-tree/toFlexSchema.js +3 -2
- package/lib/simple-tree/toFlexSchema.js.map +1 -1
- package/lib/simple-tree/tree.d.ts +4 -1
- package/lib/simple-tree/tree.d.ts.map +1 -1
- package/lib/simple-tree/tree.js +44 -0
- package/lib/simple-tree/tree.js.map +1 -1
- package/lib/simple-tree/treeNodeApi.d.ts +2 -75
- package/lib/simple-tree/treeNodeApi.d.ts.map +1 -1
- package/lib/simple-tree/treeNodeApi.js +20 -28
- package/lib/simple-tree/treeNodeApi.js.map +1 -1
- package/lib/simple-tree/treeNodeKernel.d.ts +26 -0
- package/lib/simple-tree/treeNodeKernel.d.ts.map +1 -0
- package/lib/simple-tree/treeNodeKernel.js +79 -0
- package/lib/simple-tree/treeNodeKernel.js.map +1 -0
- package/lib/simple-tree/types.d.ts +95 -3
- package/lib/simple-tree/types.d.ts.map +1 -1
- package/lib/simple-tree/types.js +121 -22
- package/lib/simple-tree/types.js.map +1 -1
- package/lib/util/breakable.d.ts +83 -0
- package/lib/util/breakable.d.ts.map +1 -0
- package/lib/util/breakable.js +171 -0
- package/lib/util/breakable.js.map +1 -0
- package/lib/util/index.d.ts +3 -2
- package/lib/util/index.d.ts.map +1 -1
- package/lib/util/index.js +3 -2
- package/lib/util/index.js.map +1 -1
- package/lib/util/nestedMap.d.ts +17 -3
- package/lib/util/nestedMap.d.ts.map +1 -1
- package/lib/util/nestedMap.js +19 -0
- package/lib/util/nestedMap.js.map +1 -1
- package/lib/util/utils.d.ts +7 -0
- package/lib/util/utils.d.ts.map +1 -1
- package/lib/util/utils.js +13 -0
- package/lib/util/utils.js.map +1 -1
- package/package.json +29 -27
- package/src/core/forest/editableForest.ts +25 -4
- package/src/core/index.ts +2 -0
- package/src/core/rebase/index.ts +2 -0
- package/src/core/rebase/types.ts +17 -0
- package/src/core/tree/anchorSet.ts +14 -0
- package/src/core/tree/detachedFieldIndex.ts +217 -35
- package/src/core/tree/detachedFieldIndexCodec.ts +17 -8
- package/src/core/tree/detachedFieldIndexFormat.ts +1 -1
- package/src/core/tree/detachedFieldIndexTypes.ts +41 -5
- package/src/core/tree/index.ts +2 -1
- package/src/core/tree/visitDelta.ts +58 -16
- package/src/core/tree/visitorUtils.ts +7 -4
- package/src/events/events.ts +4 -2
- package/src/feature-libraries/default-schema/defaultEditBuilder.ts +1 -1
- package/src/feature-libraries/default-schema/defaultFieldKinds.ts +1 -0
- package/src/feature-libraries/editableTreeBinder.ts +1 -1
- package/src/feature-libraries/flex-map-tree/mapTreeNode.ts +1 -95
- package/src/feature-libraries/flex-tree/flexTreeTypes.ts +0 -62
- package/src/feature-libraries/flex-tree/index.ts +7 -2
- package/src/feature-libraries/flex-tree/lazyEntity.ts +0 -3
- package/src/feature-libraries/flex-tree/lazyField.ts +15 -47
- package/src/feature-libraries/flex-tree/lazyNode.ts +1 -48
- package/src/feature-libraries/forest-summary/forestSummarizer.ts +1 -0
- package/src/feature-libraries/index.ts +4 -2
- package/src/feature-libraries/modular-schema/crossFieldQueries.ts +18 -0
- package/src/feature-libraries/modular-schema/discrepancies.ts +395 -0
- package/src/feature-libraries/modular-schema/fieldChangeHandler.ts +10 -2
- package/src/feature-libraries/modular-schema/genericFieldKind.ts +3 -0
- package/src/feature-libraries/modular-schema/index.ts +2 -0
- package/src/feature-libraries/modular-schema/modularChangeCodecs.ts +81 -35
- package/src/feature-libraries/modular-schema/modularChangeFamily.ts +1521 -444
- package/src/feature-libraries/modular-schema/modularChangeFormat.ts +2 -0
- package/src/feature-libraries/modular-schema/modularChangeTypes.ts +51 -0
- package/src/feature-libraries/node-key/index.ts +0 -1
- package/src/feature-libraries/object-forest/objectForest.ts +7 -3
- package/src/feature-libraries/optional-field/optionalField.ts +1 -0
- package/src/feature-libraries/sequence-field/index.ts +0 -2
- package/src/feature-libraries/sequence-field/invert.ts +1 -1
- package/src/feature-libraries/sequence-field/rebase.ts +7 -1
- package/src/feature-libraries/sequence-field/sequenceFieldChangeHandler.ts +2 -1
- package/src/feature-libraries/sequence-field/utils.ts +37 -85
- package/src/feature-libraries/typed-schema/typedTreeSchema.ts +10 -0
- package/src/index.ts +0 -1
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/schematizingTreeView.ts +6 -2
- package/src/shared-tree/sharedTree.ts +12 -1
- package/src/shared-tree/sharedTreeChangeEnricher.ts +1 -1
- package/src/shared-tree/treeApi.ts +1 -1
- package/src/shared-tree/treeCheckout.ts +60 -5
- package/src/shared-tree/treeView.ts +5 -0
- package/src/shared-tree-core/branch.ts +10 -0
- package/src/shared-tree-core/sharedTreeCore.ts +25 -6
- package/src/simple-tree/arrayNode.ts +50 -23
- package/src/simple-tree/index.ts +3 -3
- package/src/simple-tree/leafNodeSchema.ts +1 -1
- package/src/simple-tree/mapNode.ts +2 -2
- package/src/simple-tree/objectNode.ts +9 -3
- package/src/simple-tree/proxies.ts +10 -33
- package/src/simple-tree/proxyBinding.ts +23 -0
- package/src/simple-tree/schemaFactory.ts +37 -2
- package/src/simple-tree/schemaTypes.ts +36 -1
- package/src/simple-tree/toFlexSchema.ts +5 -4
- package/src/simple-tree/tree.ts +68 -4
- package/src/simple-tree/treeNodeApi.ts +29 -111
- package/src/simple-tree/treeNodeKernel.ts +91 -0
- package/src/simple-tree/types.ts +292 -31
- package/src/util/breakable.ts +214 -0
- package/src/util/index.ts +11 -0
- package/src/util/nestedMap.ts +33 -3
- package/src/util/utils.ts +17 -0
- package/dist/feature-libraries/node-key/nodeKeyIndex.d.ts +0 -41
- package/dist/feature-libraries/node-key/nodeKeyIndex.d.ts.map +0 -1
- package/dist/feature-libraries/node-key/nodeKeyIndex.js +0 -101
- package/dist/feature-libraries/node-key/nodeKeyIndex.js.map +0 -1
- package/lib/feature-libraries/node-key/nodeKeyIndex.d.ts +0 -41
- package/lib/feature-libraries/node-key/nodeKeyIndex.d.ts.map +0 -1
- package/lib/feature-libraries/node-key/nodeKeyIndex.js +0 -97
- package/lib/feature-libraries/node-key/nodeKeyIndex.js.map +0 -1
- package/src/feature-libraries/node-key/nodeKeyIndex.ts +0 -132
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.ModularEditBuilder = exports.getChangeHandler = exports.getFieldKind = exports.rebaseRevisionMetadataFromInfo = exports.intoDelta = exports.updateRefreshers = exports.relevantRemovedRoots = exports.ModularChangeFamily = void 0;
|
|
7
|
+
exports.newCrossFieldKeyTable = exports.getFieldsForCrossFieldKey = exports.getParentFieldId = exports.ModularEditBuilder = exports.getChangeHandler = exports.getFieldKind = exports.rebaseRevisionMetadataFromInfo = exports.intoDelta = exports.updateRefreshers = exports.relevantRemovedRoots = exports.ModularChangeFamily = void 0;
|
|
8
8
|
const internal_1 = require("@fluidframework/core-utils/internal");
|
|
9
9
|
const sorted_btree_es6_1 = require("@tylerbu/sorted-btree-es6");
|
|
10
10
|
const index_js_1 = require("../../core/index.js");
|
|
@@ -37,27 +37,30 @@ class ModularChangeFamily {
|
|
|
37
37
|
*/
|
|
38
38
|
normalizeFieldChanges(change1, change2, genId, revisionMetadata) {
|
|
39
39
|
// TODO: Handle the case where changes have conflicting field kinds
|
|
40
|
-
const kind = change1
|
|
40
|
+
const kind = change1.fieldKind !== genericFieldKind_js_1.genericFieldKind.identifier
|
|
41
41
|
? change1.fieldKind
|
|
42
|
-
: change2
|
|
42
|
+
: change2.fieldKind;
|
|
43
43
|
if (kind === genericFieldKind_js_1.genericFieldKind.identifier) {
|
|
44
|
-
//
|
|
44
|
+
// Both changes are generic
|
|
45
45
|
return {
|
|
46
|
-
fieldKind: genericFieldKind_js_1.genericFieldKind,
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
fieldKind: genericFieldKind_js_1.genericFieldKind.identifier,
|
|
47
|
+
changeHandler: genericFieldKind_js_1.genericFieldKind.changeHandler,
|
|
48
|
+
change1: change1.change,
|
|
49
|
+
change2: change2.change,
|
|
49
50
|
};
|
|
50
51
|
}
|
|
51
52
|
const fieldKind = getFieldKind(this.fieldKinds, kind);
|
|
52
|
-
const
|
|
53
|
-
const normalizedChange1 = this.normalizeFieldChange(change1,
|
|
54
|
-
const normalizedChange2 = this.normalizeFieldChange(change2,
|
|
55
|
-
return {
|
|
53
|
+
const changeHandler = fieldKind.changeHandler;
|
|
54
|
+
const normalizedChange1 = this.normalizeFieldChange(change1, changeHandler, genId, revisionMetadata);
|
|
55
|
+
const normalizedChange2 = this.normalizeFieldChange(change2, changeHandler, genId, revisionMetadata);
|
|
56
|
+
return {
|
|
57
|
+
fieldKind: kind,
|
|
58
|
+
changeHandler,
|
|
59
|
+
change1: normalizedChange1,
|
|
60
|
+
change2: normalizedChange2,
|
|
61
|
+
};
|
|
56
62
|
}
|
|
57
63
|
normalizeFieldChange(fieldChange, handler, genId, revisionMetadata) {
|
|
58
|
-
if (fieldChange === undefined) {
|
|
59
|
-
return undefined;
|
|
60
|
-
}
|
|
61
64
|
if (fieldChange.fieldKind !== genericFieldKind_js_1.genericFieldKind.identifier) {
|
|
62
65
|
return fieldChange.change;
|
|
63
66
|
}
|
|
@@ -72,105 +75,224 @@ class ModularChangeFamily {
|
|
|
72
75
|
compose(changes) {
|
|
73
76
|
const { revInfos, maxId } = getRevInfoFromTaggedChanges(changes);
|
|
74
77
|
const idState = { maxId };
|
|
75
|
-
|
|
78
|
+
if (changes.length === 0) {
|
|
79
|
+
return makeModularChangeset();
|
|
80
|
+
}
|
|
81
|
+
return changes.reduce((change1, change2) => (0, index_js_1.makeAnonChange)(this.composePair(change1, change2, revInfos, idState))).change;
|
|
76
82
|
}
|
|
77
83
|
composePair(change1, change2, revInfos, idState) {
|
|
78
|
-
const
|
|
79
|
-
const revisionMetadata = (0, index_js_1.revisionMetadataSourceFromInfo)(revInfos);
|
|
80
|
-
const crossFieldTable = newComposeTable();
|
|
81
|
-
const composedFields = this.composeFieldMaps(getActiveFieldChanges(change1.change), getActiveFieldChanges(change2.change), genId, crossFieldTable, revisionMetadata);
|
|
82
|
-
const composedNodeChanges = new Map();
|
|
83
|
-
for (const [id1, id2] of crossFieldTable.nodeIdPairs) {
|
|
84
|
-
this.composeNodesById(change1.change.nodeChanges, change2.change.nodeChanges, composedNodeChanges, id1, id2, genId, crossFieldTable, revisionMetadata);
|
|
85
|
-
}
|
|
86
|
-
crossFieldTable.nodeIdPairs.length = 0;
|
|
87
|
-
while (crossFieldTable.invalidatedFields.size > 0) {
|
|
88
|
-
const fieldsToUpdate = crossFieldTable.invalidatedFields;
|
|
89
|
-
crossFieldTable.invalidatedFields = new Set();
|
|
90
|
-
for (const fieldChange of fieldsToUpdate) {
|
|
91
|
-
const context = crossFieldTable.fieldToContext.get(fieldChange);
|
|
92
|
-
(0, internal_1.assert)(context !== undefined, 0x8cc /* Should have context for every invalidated field */);
|
|
93
|
-
const { change1: fieldChange1, change2: fieldChange2, composedChange } = context;
|
|
94
|
-
const rebaser = getChangeHandler(this.fieldKinds, composedChange.fieldKind).rebaser;
|
|
95
|
-
const composeNodes = (child1, child2) => {
|
|
96
|
-
if (child2 !== undefined &&
|
|
97
|
-
!(0, index_js_2.nestedSetContains)(crossFieldTable.nodeIds, child2.revision, child2.localId)) {
|
|
98
|
-
crossFieldTable.nodeIdPairs.push([child1, child2]);
|
|
99
|
-
if (child1 !== undefined && child2 !== undefined) {
|
|
100
|
-
(0, index_js_2.addToNestedSet)(crossFieldTable.nodeIds, child2.revision, child2.localId);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
return child1 ?? child2 ?? (0, index_js_2.fail)("Should not compose two undefined nodes");
|
|
104
|
-
};
|
|
105
|
-
const amendedChange = rebaser.compose(fieldChange1, fieldChange2, composeNodes, genId, newCrossFieldManager(crossFieldTable, fieldChange, false), revisionMetadata);
|
|
106
|
-
composedChange.change = (0, index_js_2.brand)(amendedChange);
|
|
107
|
-
// Process any newly discovered nodes.
|
|
108
|
-
for (const [taggedId1, taggedId2] of crossFieldTable.nodeIdPairs) {
|
|
109
|
-
this.composeNodesById(change1.change.nodeChanges, change2.change.nodeChanges, composedNodeChanges, taggedId1, taggedId2, genId, crossFieldTable, revisionMetadata);
|
|
110
|
-
}
|
|
111
|
-
crossFieldTable.nodeIdPairs.length = 0;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
84
|
+
const { fieldChanges, nodeChanges, nodeToParent, nodeAliases, crossFieldKeys } = this.composeAllFields(change1.change, change2.change, revInfos, idState);
|
|
114
85
|
const { allBuilds, allDestroys, allRefreshers } = composeBuildsDestroysAndRefreshers([
|
|
115
86
|
change1,
|
|
116
87
|
change2,
|
|
117
88
|
]);
|
|
118
|
-
return makeModularChangeset(this.pruneFieldMap(
|
|
89
|
+
return makeModularChangeset(this.pruneFieldMap(fieldChanges, nodeChanges), nodeChanges, nodeToParent, nodeAliases, crossFieldKeys, idState.maxId, revInfos, undefined, allBuilds, allDestroys, allRefreshers);
|
|
90
|
+
}
|
|
91
|
+
composeAllFields(change1, change2, revInfos, idState) {
|
|
92
|
+
if (hasConflicts(change1) && hasConflicts(change2)) {
|
|
93
|
+
return {
|
|
94
|
+
fieldChanges: new Map(),
|
|
95
|
+
nodeChanges: new Map(),
|
|
96
|
+
nodeToParent: new Map(),
|
|
97
|
+
nodeAliases: new Map(),
|
|
98
|
+
crossFieldKeys: newBTree(),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
else if (hasConflicts(change1)) {
|
|
102
|
+
return change2;
|
|
103
|
+
}
|
|
104
|
+
else if (hasConflicts(change2)) {
|
|
105
|
+
return change1;
|
|
106
|
+
}
|
|
107
|
+
const genId = (0, index_js_2.idAllocatorFromState)(idState);
|
|
108
|
+
const revisionMetadata = (0, index_js_1.revisionMetadataSourceFromInfo)(revInfos);
|
|
109
|
+
const crossFieldTable = newComposeTable(change1, change2);
|
|
110
|
+
// We merge nodeChanges, nodeToParent, and nodeAliases from the two changesets.
|
|
111
|
+
// The merged tables will have correct entries for all nodes which are only referenced in one of the input changesets.
|
|
112
|
+
// During composeFieldMaps and processInvalidatedElements we will find all nodes referenced in both input changesets
|
|
113
|
+
// and adjust these tables as necessary.
|
|
114
|
+
// Note that when merging these tables we may encounter key collisions and will arbitrarily drop values in that case.
|
|
115
|
+
// A collision for a node ID means that that node is referenced in both changesets
|
|
116
|
+
// (since we assume that if two changesets use the same node ID they are referring to the same node),
|
|
117
|
+
// therefore all collisions will be addressed when processing the intersection of the changesets.
|
|
118
|
+
const composedNodeChanges = mergeNestedMaps(change1.nodeChanges, change2.nodeChanges);
|
|
119
|
+
const composedNodeToParent = mergeNestedMaps(change1.nodeToParent, change2.nodeToParent);
|
|
120
|
+
const composedNodeAliases = mergeNestedMaps(change1.nodeAliases, change2.nodeAliases);
|
|
121
|
+
const composedFields = this.composeFieldMaps(change1.fieldChanges, change2.fieldChanges, genId, crossFieldTable, revisionMetadata);
|
|
122
|
+
this.processInvalidatedElements(crossFieldTable, composedFields, composedNodeChanges, composedNodeToParent, composedNodeAliases, genId, revisionMetadata);
|
|
123
|
+
// Currently no field kinds require making changes to cross-field keys during composition, so we can just merge the two tables.
|
|
124
|
+
const composedCrossFieldKeys = mergeBTrees(change1.crossFieldKeys, change2.crossFieldKeys);
|
|
125
|
+
return {
|
|
126
|
+
fieldChanges: composedFields,
|
|
127
|
+
nodeChanges: composedNodeChanges,
|
|
128
|
+
nodeToParent: composedNodeToParent,
|
|
129
|
+
nodeAliases: composedNodeAliases,
|
|
130
|
+
crossFieldKeys: (0, index_js_2.brand)(composedCrossFieldKeys),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
composeInvalidatedField(fieldChange, crossFieldTable, genId, revisionMetadata) {
|
|
134
|
+
const context = crossFieldTable.fieldToContext.get(fieldChange);
|
|
135
|
+
(0, internal_1.assert)(context !== undefined, 0x8cc /* Should have context for every invalidated field */);
|
|
136
|
+
const { change1: fieldChange1, change2: fieldChange2, composedChange } = context;
|
|
137
|
+
const rebaser = getChangeHandler(this.fieldKinds, composedChange.fieldKind).rebaser;
|
|
138
|
+
const composeNodes = (child1, child2) => {
|
|
139
|
+
if (child1 !== undefined &&
|
|
140
|
+
child2 !== undefined &&
|
|
141
|
+
(0, index_js_1.getFromChangeAtomIdMap)(crossFieldTable.newToBaseNodeId, child2) === undefined) {
|
|
142
|
+
(0, index_js_1.setInChangeAtomIdMap)(crossFieldTable.newToBaseNodeId, child2, child1);
|
|
143
|
+
crossFieldTable.pendingCompositions.nodeIdsToCompose.push([child1, child2]);
|
|
144
|
+
}
|
|
145
|
+
return child1 ?? child2 ?? (0, index_js_2.fail)("Should not compose two undefined nodes");
|
|
146
|
+
};
|
|
147
|
+
const amendedChange = rebaser.compose(fieldChange1, fieldChange2, composeNodes, genId, new ComposeManager(crossFieldTable, fieldChange, false), revisionMetadata);
|
|
148
|
+
composedChange.change = (0, index_js_2.brand)(amendedChange);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Updates everything in the composed output which may no longer be valid.
|
|
152
|
+
* This could be due to
|
|
153
|
+
* - discovering that two node changesets refer to the same node (`nodeIdsToCompose`)
|
|
154
|
+
* - a previously composed field being invalidated by a cross field effect (`invalidatedFields`)
|
|
155
|
+
* - a field which was copied directly from an input changeset being invalidated by a cross field effect
|
|
156
|
+
* (`affectedBaseFields` and `affectedNewFields`)
|
|
157
|
+
*
|
|
158
|
+
* Updating an element may invalidate further elements. This function runs until there is no more invalidation.
|
|
159
|
+
*/
|
|
160
|
+
processInvalidatedElements(table, composedFields, composedNodes, composedNodeToParent, nodeAliases, genId, metadata) {
|
|
161
|
+
const pending = table.pendingCompositions;
|
|
162
|
+
while (table.invalidatedFields.size > 0 ||
|
|
163
|
+
pending.nodeIdsToCompose.length > 0 ||
|
|
164
|
+
pending.affectedBaseFields.length > 0 ||
|
|
165
|
+
pending.affectedNewFields.length > 0) {
|
|
166
|
+
// Note that the call to `composeNodesById` can add entries to `crossFieldTable.nodeIdPairs`.
|
|
167
|
+
for (const [id1, id2] of pending.nodeIdsToCompose) {
|
|
168
|
+
this.composeNodesById(table.baseChange.nodeChanges, table.newChange.nodeChanges, composedNodes, composedNodeToParent, nodeAliases, id1, id2, genId, table, metadata);
|
|
169
|
+
}
|
|
170
|
+
pending.nodeIdsToCompose.length = 0;
|
|
171
|
+
this.composeAffectedFields(table, table.baseChange, true, pending.affectedBaseFields, composedFields, composedNodes, genId, metadata);
|
|
172
|
+
this.composeAffectedFields(table, table.newChange, false, pending.affectedNewFields, composedFields, composedNodes, genId, metadata);
|
|
173
|
+
this.processInvalidatedCompositions(table, genId, metadata);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
processInvalidatedCompositions(table, genId, metadata) {
|
|
177
|
+
const fieldsToUpdate = table.invalidatedFields;
|
|
178
|
+
table.invalidatedFields = new Set();
|
|
179
|
+
for (const fieldChange of fieldsToUpdate) {
|
|
180
|
+
this.composeInvalidatedField(fieldChange, table, genId, metadata);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Ensures that each field in `affectedFields` has been updated in the composition output.
|
|
185
|
+
* Any field which has already been composed is ignored.
|
|
186
|
+
* All other fields are optimistically assumed to not have any changes in the other input changeset.
|
|
187
|
+
*
|
|
188
|
+
* @param change - The changeset which contains the affected fields.
|
|
189
|
+
* This should be one of the two changesets being composed.
|
|
190
|
+
* @param areBaseFields - Whether the affected fields are part of the base changeset.
|
|
191
|
+
* If not, they are assumed to be part of the new changeset.
|
|
192
|
+
* @param affectedFields - The set of fields to process.
|
|
193
|
+
*/
|
|
194
|
+
composeAffectedFields(table, change, areBaseFields, affectedFields, composedFields, composedNodes, genId, metadata) {
|
|
195
|
+
for (const fieldIdKey of affectedFields.keys()) {
|
|
196
|
+
const fieldId = normalizeFieldId(fieldIdFromFieldIdKey(fieldIdKey), change.nodeAliases);
|
|
197
|
+
const fieldChange = fieldChangeFromId(change.fieldChanges, change.nodeChanges, fieldId);
|
|
198
|
+
if (table.fieldToContext.has(fieldChange) ||
|
|
199
|
+
table.newFieldToBaseField.has(fieldChange)) {
|
|
200
|
+
// This function handles fields which were not part of the intersection of the two changesets but which need to be updated anyway.
|
|
201
|
+
// If we've already processed this field then either it is up to date
|
|
202
|
+
// or there is pending inval which will be handled in processInvalidatedCompositions.
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
const emptyChange = this.createEmptyFieldChange(fieldChange.fieldKind);
|
|
206
|
+
const [change1, change2] = areBaseFields
|
|
207
|
+
? [fieldChange, emptyChange]
|
|
208
|
+
: [emptyChange, fieldChange];
|
|
209
|
+
const composedField = this.composeFieldChanges(change1, change2, genId, table, metadata);
|
|
210
|
+
if (fieldId.nodeId === undefined) {
|
|
211
|
+
composedFields.set(fieldId.field, composedField);
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
const nodeId = (0, index_js_1.getFromChangeAtomIdMap)(table.newToBaseNodeId, fieldId.nodeId) ?? fieldId.nodeId;
|
|
215
|
+
let nodeChangeset = nodeChangeFromId(composedNodes, nodeId);
|
|
216
|
+
if (!table.composedNodes.has(nodeChangeset)) {
|
|
217
|
+
nodeChangeset = cloneNodeChangeset(nodeChangeset);
|
|
218
|
+
(0, index_js_1.setInChangeAtomIdMap)(composedNodes, nodeId, nodeChangeset);
|
|
219
|
+
}
|
|
220
|
+
if (nodeChangeset.fieldChanges === undefined) {
|
|
221
|
+
nodeChangeset.fieldChanges = new Map();
|
|
222
|
+
}
|
|
223
|
+
nodeChangeset.fieldChanges.set(fieldId.field, composedField);
|
|
224
|
+
}
|
|
225
|
+
affectedFields.clear();
|
|
119
226
|
}
|
|
120
227
|
composeFieldMaps(change1, change2, genId, crossFieldTable, revisionMetadata) {
|
|
121
228
|
const composedFields = new Map();
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const fieldChange1 = change1?.get(field);
|
|
131
|
-
const fieldChange2 = change2?.get(field);
|
|
132
|
-
const { fieldKind, change1: normalizedFieldChange1, change2: normalizedFieldChange2, } = this.normalizeFieldChanges(fieldChange1, fieldChange2, genId, revisionMetadata);
|
|
133
|
-
const manager = newCrossFieldManager(crossFieldTable, fieldChange1 ?? fieldChange2);
|
|
134
|
-
const change1Normalized = normalizedFieldChange1 ?? fieldKind.changeHandler.createEmpty();
|
|
135
|
-
const change2Normalized = normalizedFieldChange2 ?? fieldKind.changeHandler.createEmpty();
|
|
136
|
-
const composedChange = fieldKind.changeHandler.rebaser.compose(change1Normalized, change2Normalized, (child1, child2) => {
|
|
137
|
-
crossFieldTable.nodeIdPairs.push([child1, child2]);
|
|
138
|
-
if (child2 !== undefined) {
|
|
139
|
-
(0, index_js_2.addToNestedSet)(crossFieldTable.nodeIds, child2.revision, child2.localId);
|
|
140
|
-
}
|
|
141
|
-
return child1 ?? child2 ?? (0, index_js_2.fail)("Should not compose two undefined nodes");
|
|
142
|
-
}, genId, manager, revisionMetadata);
|
|
143
|
-
const composedField = {
|
|
144
|
-
fieldKind: fieldKind.identifier,
|
|
145
|
-
change: (0, index_js_2.brand)(composedChange),
|
|
146
|
-
};
|
|
147
|
-
const fieldKey = fieldChange1 ?? fieldChange2 ?? (0, index_js_2.fail)("At least one field should have changes");
|
|
148
|
-
crossFieldTable.fieldToContext.set(fieldKey, {
|
|
149
|
-
change1: change1Normalized,
|
|
150
|
-
change2: change2Normalized,
|
|
151
|
-
composedChange: composedField,
|
|
152
|
-
});
|
|
153
|
-
// TODO: Could optimize by checking that composedField is non-empty
|
|
229
|
+
if (change1 === undefined || change2 === undefined) {
|
|
230
|
+
return change1 ?? change2 ?? composedFields;
|
|
231
|
+
}
|
|
232
|
+
for (const [field, fieldChange1] of change1) {
|
|
233
|
+
const fieldChange2 = change2.get(field);
|
|
234
|
+
const composedField = fieldChange2 !== undefined
|
|
235
|
+
? this.composeFieldChanges(fieldChange1, fieldChange2, genId, crossFieldTable, revisionMetadata)
|
|
236
|
+
: fieldChange1;
|
|
154
237
|
composedFields.set(field, composedField);
|
|
155
238
|
}
|
|
239
|
+
for (const [field, fieldChange2] of change2) {
|
|
240
|
+
if (change1 === undefined || !change1.has(field)) {
|
|
241
|
+
composedFields.set(field, fieldChange2);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
156
244
|
return composedFields;
|
|
157
245
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
246
|
+
/**
|
|
247
|
+
* Returns the composition of the two input fields.
|
|
248
|
+
*
|
|
249
|
+
* Any nodes in this field which were modified by both changesets
|
|
250
|
+
* will be added to `crossFieldTable.pendingCompositions.nodeIdsToCompose`.
|
|
251
|
+
*
|
|
252
|
+
* Any fields which had cross-field information sent to them as part of this field composition
|
|
253
|
+
* will be added to either `affectedBaseFields` or `affectedNewFields` in `crossFieldTable.pendingCompositions`.
|
|
254
|
+
*
|
|
255
|
+
* Any composed `FieldChange` which is invalidated by new cross-field information will be added to `crossFieldTable.invalidatedFields`.
|
|
256
|
+
*/
|
|
257
|
+
composeFieldChanges(change1, change2, idAllocator, crossFieldTable, revisionMetadata) {
|
|
258
|
+
const { fieldKind, changeHandler, change1: change1Normalized, change2: change2Normalized, } = this.normalizeFieldChanges(change1, change2, idAllocator, revisionMetadata);
|
|
259
|
+
const manager = new ComposeManager(crossFieldTable, change1);
|
|
260
|
+
const composedChange = changeHandler.rebaser.compose(change1Normalized, change2Normalized, (child1, child2) => {
|
|
261
|
+
if (child1 !== undefined && child2 !== undefined) {
|
|
262
|
+
(0, index_js_1.setInChangeAtomIdMap)(crossFieldTable.newToBaseNodeId, child2, child1);
|
|
263
|
+
crossFieldTable.pendingCompositions.nodeIdsToCompose.push([child1, child2]);
|
|
264
|
+
}
|
|
265
|
+
return child1 ?? child2 ?? (0, index_js_2.fail)("Should not compose two undefined nodes");
|
|
266
|
+
}, idAllocator, manager, revisionMetadata);
|
|
267
|
+
const composedField = {
|
|
268
|
+
fieldKind,
|
|
269
|
+
change: (0, index_js_2.brand)(composedChange),
|
|
270
|
+
};
|
|
271
|
+
crossFieldTable.fieldToContext.set(change1, {
|
|
272
|
+
change1: change1Normalized,
|
|
273
|
+
change2: change2Normalized,
|
|
274
|
+
composedChange: composedField,
|
|
275
|
+
});
|
|
276
|
+
crossFieldTable.newFieldToBaseField.set(change2, change1);
|
|
277
|
+
return composedField;
|
|
278
|
+
}
|
|
279
|
+
composeNodesById(nodeChanges1, nodeChanges2, composedNodes, composedNodeToParent, nodeAliases, id1, id2, idAllocator, crossFieldTable, revisionMetadata) {
|
|
280
|
+
const nodeChangeset1 = nodeChangeFromId(nodeChanges1, id1);
|
|
281
|
+
const nodeChangeset2 = nodeChangeFromId(nodeChanges2, id2);
|
|
167
282
|
const composedNodeChangeset = this.composeNodeChanges(nodeChangeset1, nodeChangeset2, idAllocator, crossFieldTable, revisionMetadata);
|
|
168
|
-
|
|
169
|
-
(0,
|
|
283
|
+
(0, index_js_1.setInChangeAtomIdMap)(composedNodes, id1, composedNodeChangeset);
|
|
284
|
+
if (!(0, index_js_1.areEqualChangeAtomIds)(id1, id2)) {
|
|
285
|
+
(0, index_js_2.deleteFromNestedMap)(composedNodes, id2.revision, id2.localId);
|
|
286
|
+
(0, index_js_2.deleteFromNestedMap)(composedNodeToParent, id2.revision, id2.localId);
|
|
287
|
+
(0, index_js_1.setInChangeAtomIdMap)(nodeAliases, id2, id1);
|
|
288
|
+
// We need to delete id1 to avoid forming a cycle in case id1 already had an alias.
|
|
289
|
+
(0, index_js_2.deleteFromNestedMap)(nodeAliases, id1.revision, id1.localId);
|
|
290
|
+
}
|
|
291
|
+
crossFieldTable.composedNodes.add(composedNodeChangeset);
|
|
170
292
|
}
|
|
171
293
|
composeNodeChanges(change1, change2, genId, crossFieldTable, revisionMetadata) {
|
|
172
|
-
const nodeExistsConstraint = change1
|
|
173
|
-
const composedFieldChanges = this.composeFieldMaps(change1
|
|
294
|
+
const nodeExistsConstraint = change1.nodeExistsConstraint ?? change2.nodeExistsConstraint;
|
|
295
|
+
const composedFieldChanges = this.composeFieldMaps(change1.fieldChanges, change2.fieldChanges, genId, crossFieldTable, revisionMetadata);
|
|
174
296
|
const composedNodeChange = {};
|
|
175
297
|
if (composedFieldChanges.size > 0) {
|
|
176
298
|
composedNodeChange.fieldChanges = composedFieldChanges;
|
|
@@ -193,23 +315,21 @@ class ModularChangeFamily {
|
|
|
193
315
|
// Destroys only occur in rollback changesets, which are never inverted.
|
|
194
316
|
(0, internal_1.assert)(change.change.destroys === undefined, 0x89a /* Unexpected destroys in change to invert */);
|
|
195
317
|
if ((change.change.constraintViolationCount ?? 0) > 0) {
|
|
196
|
-
return makeModularChangeset(undefined, undefined, change.change.maxId, [], undefined, undefined, destroys);
|
|
318
|
+
return makeModularChangeset(undefined, undefined, undefined, undefined, undefined, change.change.maxId, [], undefined, undefined, destroys);
|
|
197
319
|
}
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
// this function to read the updated idState.maxId after more IDs are allocated.
|
|
201
|
-
// TODO: add a getMax function to IdAllocator to make for a clearer contract.
|
|
202
|
-
const genId = (0, index_js_2.idAllocatorFromState)(idState);
|
|
320
|
+
const genId = (0, index_js_2.idAllocatorFromMaxId)(change.change.maxId ?? -1);
|
|
321
|
+
const invertedNodeToParent = cloneNestedMap(change.change.nodeToParent);
|
|
203
322
|
const crossFieldTable = {
|
|
204
323
|
...newCrossFieldTable(),
|
|
205
324
|
originalFieldToContext: new Map(),
|
|
325
|
+
invertedNodeToParent,
|
|
206
326
|
};
|
|
207
327
|
const { revInfos } = getRevInfoFromTaggedChanges([change]);
|
|
208
328
|
const revisionMetadata = (0, index_js_1.revisionMetadataSourceFromInfo)(revInfos);
|
|
209
|
-
const invertedFields = this.invertFieldMap(change.change.fieldChanges, isRollback, genId, crossFieldTable, revisionMetadata);
|
|
329
|
+
const invertedFields = this.invertFieldMap(change.change.fieldChanges, undefined, isRollback, genId, crossFieldTable, revisionMetadata);
|
|
210
330
|
const invertedNodes = new Map();
|
|
211
331
|
(0, index_js_2.forEachInNestedMap)(change.change.nodeChanges, (nodeChangeset, revision, localId) => {
|
|
212
|
-
(0, index_js_2.setInNestedMap)(invertedNodes, revision, localId, this.invertNodeChange(nodeChangeset, isRollback, genId, crossFieldTable, revisionMetadata));
|
|
332
|
+
(0, index_js_2.setInNestedMap)(invertedNodes, revision, localId, this.invertNodeChange(nodeChangeset, { revision, localId }, isRollback, genId, crossFieldTable, revisionMetadata));
|
|
213
333
|
});
|
|
214
334
|
if (crossFieldTable.invalidatedFields.size > 0) {
|
|
215
335
|
const fieldsToUpdate = crossFieldTable.invalidatedFields;
|
|
@@ -218,17 +338,19 @@ class ModularChangeFamily {
|
|
|
218
338
|
const originalFieldChange = fieldChange.change;
|
|
219
339
|
const context = crossFieldTable.originalFieldToContext.get(fieldChange);
|
|
220
340
|
(0, internal_1.assert)(context !== undefined, 0x851 /* Should have context for every invalidated field */);
|
|
221
|
-
const { invertedField } = context;
|
|
222
|
-
const amendedChange = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).rebaser.invert(originalFieldChange, isRollback, genId,
|
|
341
|
+
const { invertedField, fieldId } = context;
|
|
342
|
+
const amendedChange = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).rebaser.invert(originalFieldChange, isRollback, genId, new InvertManager(crossFieldTable, fieldChange, fieldId), revisionMetadata);
|
|
223
343
|
invertedField.change = (0, index_js_2.brand)(amendedChange);
|
|
224
344
|
}
|
|
225
345
|
}
|
|
226
|
-
|
|
346
|
+
const crossFieldKeys = this.makeCrossFieldKeyTable(invertedFields, invertedNodes);
|
|
347
|
+
return makeModularChangeset(invertedFields, invertedNodes, invertedNodeToParent, change.change.nodeAliases, crossFieldKeys, genId.getMaxId(), [], change.change.constraintViolationCount, undefined, destroys);
|
|
227
348
|
}
|
|
228
|
-
invertFieldMap(changes, isRollback, genId, crossFieldTable, revisionMetadata) {
|
|
349
|
+
invertFieldMap(changes, parentId, isRollback, genId, crossFieldTable, revisionMetadata) {
|
|
229
350
|
const invertedFields = new Map();
|
|
230
351
|
for (const [field, fieldChange] of changes) {
|
|
231
|
-
const
|
|
352
|
+
const fieldId = { nodeId: parentId, field };
|
|
353
|
+
const manager = new InvertManager(crossFieldTable, fieldChange, fieldId);
|
|
232
354
|
const invertedChange = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).rebaser.invert(fieldChange.change, isRollback, genId, manager, revisionMetadata);
|
|
233
355
|
const invertedFieldChange = {
|
|
234
356
|
...fieldChange,
|
|
@@ -236,15 +358,16 @@ class ModularChangeFamily {
|
|
|
236
358
|
};
|
|
237
359
|
invertedFields.set(field, invertedFieldChange);
|
|
238
360
|
crossFieldTable.originalFieldToContext.set(fieldChange, {
|
|
361
|
+
fieldId,
|
|
239
362
|
invertedField: invertedFieldChange,
|
|
240
363
|
});
|
|
241
364
|
}
|
|
242
365
|
return invertedFields;
|
|
243
366
|
}
|
|
244
|
-
invertNodeChange(change, isRollback, genId, crossFieldTable, revisionMetadata) {
|
|
367
|
+
invertNodeChange(change, id, isRollback, genId, crossFieldTable, revisionMetadata) {
|
|
245
368
|
const inverse = {};
|
|
246
369
|
if (change.fieldChanges !== undefined) {
|
|
247
|
-
inverse.fieldChanges = this.invertFieldMap(change.fieldChanges, isRollback, genId, crossFieldTable, revisionMetadata);
|
|
370
|
+
inverse.fieldChanges = this.invertFieldMap(change.fieldChanges, id, isRollback, genId, crossFieldTable, revisionMetadata);
|
|
248
371
|
}
|
|
249
372
|
return inverse;
|
|
250
373
|
}
|
|
@@ -255,9 +378,15 @@ class ModularChangeFamily {
|
|
|
255
378
|
const genId = (0, index_js_2.idAllocatorFromState)(idState);
|
|
256
379
|
const crossFieldTable = {
|
|
257
380
|
...newCrossFieldTable(),
|
|
258
|
-
|
|
259
|
-
|
|
381
|
+
newChange: change,
|
|
382
|
+
baseChange: over.change,
|
|
383
|
+
baseFieldToContext: new Map(),
|
|
384
|
+
baseToRebasedNodeId: new Map(),
|
|
385
|
+
rebasedFields: new Set(),
|
|
386
|
+
rebasedNodeToParent: cloneNestedMap(change.nodeToParent),
|
|
387
|
+
rebasedCrossFieldKeys: (0, index_js_2.brand)(change.crossFieldKeys.clone()),
|
|
260
388
|
nodeIdPairs: [],
|
|
389
|
+
affectedBaseFields: newBTree(),
|
|
261
390
|
};
|
|
262
391
|
let constraintState = newConstraintState(change.constraintViolationCount ?? 0);
|
|
263
392
|
const getBaseRevisions = () => revisionInfoFromTaggedChange(over).map((info) => info.revision);
|
|
@@ -266,108 +395,198 @@ class ModularChangeFamily {
|
|
|
266
395
|
getRevisionToRebase: () => taggedChange.revision,
|
|
267
396
|
getBaseRevisions,
|
|
268
397
|
};
|
|
269
|
-
const
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
const newNodeChange = newId !== undefined
|
|
273
|
-
? (0, index_js_2.tryGetFromNestedMap)(change.nodeChanges, newId.revision, newId.localId)
|
|
274
|
-
: undefined;
|
|
275
|
-
const baseNodeChange = baseId !== undefined
|
|
276
|
-
? (0, index_js_2.tryGetFromNestedMap)(over.change.nodeChanges, baseId.revision, baseId.localId) ??
|
|
277
|
-
(0, index_js_2.fail)("Unknown node ID")
|
|
278
|
-
: {};
|
|
279
|
-
const rebasedNode = this.rebaseNodeChange(newNodeChange, baseNodeChange, genId, crossFieldTable, rebaseMetadata);
|
|
280
|
-
if (rebasedNode !== undefined) {
|
|
281
|
-
const nodeId = newId ?? baseId ?? (0, index_js_2.fail)("Should not have two undefined IDs");
|
|
282
|
-
(0, index_js_2.setInNestedMap)(rebasedNodes, nodeId.revision, nodeId.localId, rebasedNode);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
398
|
+
const rebasedNodes = cloneNestedMap(change.nodeChanges);
|
|
399
|
+
const rebasedFields = this.rebaseIntersectingFields(crossFieldTable, rebasedNodes, genId, constraintState, rebaseMetadata);
|
|
400
|
+
this.rebaseFieldsWithoutNewChanges(rebasedFields, rebasedNodes, crossFieldTable, genId, rebaseMetadata);
|
|
285
401
|
if (crossFieldTable.invalidatedFields.size > 0) {
|
|
286
402
|
const fieldsToUpdate = crossFieldTable.invalidatedFields;
|
|
287
403
|
crossFieldTable.invalidatedFields = new Set();
|
|
288
404
|
constraintState = newConstraintState(change.constraintViolationCount ?? 0);
|
|
289
405
|
for (const field of fieldsToUpdate) {
|
|
290
|
-
|
|
291
|
-
const context = crossFieldTable.fieldToContext.get(field);
|
|
406
|
+
const context = crossFieldTable.baseFieldToContext.get(field);
|
|
292
407
|
(0, internal_1.assert)(context !== undefined, 0x852 /* Every field should have a context */);
|
|
293
|
-
const {
|
|
294
|
-
|
|
408
|
+
const { changeHandler, change1: fieldChangeset, change2: baseChangeset, } = this.normalizeFieldChanges(context.newChange, context.baseChange, genId, revisionMetadata);
|
|
409
|
+
const rebaseChild = (curr, base) => {
|
|
410
|
+
if (curr !== undefined) {
|
|
411
|
+
return curr;
|
|
412
|
+
}
|
|
413
|
+
if (base !== undefined) {
|
|
414
|
+
for (const id of context.baseNodeIds) {
|
|
415
|
+
if ((0, index_js_1.areEqualChangeAtomIds)(base, id)) {
|
|
416
|
+
return base;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return undefined;
|
|
421
|
+
};
|
|
422
|
+
context.rebasedChange.change = (0, index_js_2.brand)(changeHandler.rebaser.rebase(fieldChangeset, baseChangeset, rebaseChild, genId, new RebaseManager(crossFieldTable, field, context.fieldId), rebaseMetadata));
|
|
295
423
|
}
|
|
296
424
|
}
|
|
297
425
|
this.updateConstraintsForFields(rebasedFields, fieldChangeHandler_js_1.NodeAttachState.Attached, constraintState, rebasedNodes);
|
|
298
|
-
return makeModularChangeset(this.pruneFieldMap(rebasedFields, rebasedNodes), rebasedNodes, idState.maxId, change.revisions, constraintState.violationCount, change.builds, change.destroys, change.refreshers);
|
|
426
|
+
return makeModularChangeset(this.pruneFieldMap(rebasedFields, rebasedNodes), rebasedNodes, crossFieldTable.rebasedNodeToParent, change.nodeAliases, crossFieldTable.rebasedCrossFieldKeys, idState.maxId, change.revisions, constraintState.violationCount, change.builds, change.destroys, change.refreshers);
|
|
299
427
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
428
|
+
// This performs a first pass on all fields which have both new and base changes.
|
|
429
|
+
// TODO: Can we also handle additional passes in this method?
|
|
430
|
+
rebaseIntersectingFields(crossFieldTable, rebasedNodes, genId, constraintState, metadata) {
|
|
431
|
+
const change = crossFieldTable.newChange;
|
|
432
|
+
const baseChange = crossFieldTable.baseChange;
|
|
433
|
+
const rebasedFields = this.rebaseFieldMap(change.fieldChanges, baseChange.fieldChanges, undefined, genId, crossFieldTable, metadata);
|
|
434
|
+
// This loop processes all fields which have both base and new changes.
|
|
435
|
+
// Note that the call to `rebaseNodeChange` can add entries to `crossFieldTable.nodeIdPairs`.
|
|
436
|
+
for (const [newId, baseId, _attachState] of crossFieldTable.nodeIdPairs) {
|
|
437
|
+
const rebasedNode = this.rebaseNodeChange(newId, baseId, genId, crossFieldTable, metadata, constraintState);
|
|
438
|
+
(0, index_js_1.setInChangeAtomIdMap)(rebasedNodes, newId, rebasedNode);
|
|
439
|
+
}
|
|
440
|
+
return rebasedFields;
|
|
441
|
+
}
|
|
442
|
+
// This processes fields which have no new changes but have been invalidated by another field.
|
|
443
|
+
rebaseFieldsWithoutNewChanges(rebasedFields, rebasedNodes, crossFieldTable, genId, metadata) {
|
|
444
|
+
const baseChange = crossFieldTable.baseChange;
|
|
445
|
+
for (const [revision, localId, fieldKey] of crossFieldTable.affectedBaseFields.keys()) {
|
|
446
|
+
const baseNodeId = localId !== undefined
|
|
447
|
+
? normalizeNodeId({ revision, localId }, baseChange.nodeAliases)
|
|
448
|
+
: undefined;
|
|
449
|
+
const baseFieldChange = fieldMapFromNodeId(baseChange.fieldChanges, baseChange.nodeChanges, baseNodeId).get(fieldKey);
|
|
450
|
+
(0, internal_1.assert)(baseFieldChange !== undefined, 0x9c2 /* Cross field key registered for empty field */);
|
|
451
|
+
if (crossFieldTable.baseFieldToContext.has(baseFieldChange)) {
|
|
452
|
+
// This field has already been processed because there were changes to rebase.
|
|
453
|
+
continue;
|
|
454
|
+
}
|
|
455
|
+
// This field has no changes in the new changeset, otherwise it would have been added to
|
|
456
|
+
// `crossFieldTable.baseFieldToContext` when processing fields with both base and new changes.
|
|
457
|
+
const rebaseChild = (child, baseChild, stateChange) => {
|
|
458
|
+
(0, internal_1.assert)(child === undefined, 0x9c3 /* There should be no new changes in this field */);
|
|
459
|
+
return undefined;
|
|
307
460
|
};
|
|
308
|
-
const
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
return (child ??
|
|
313
|
-
// The fact `child` is undefined means that the changeset to rebase does not include changes for
|
|
314
|
-
// this node or its descendants. However, it's possible that it will after rebasing.
|
|
315
|
-
// In that case, we will need a NodeId to represent these changes under in the rebased changeset.
|
|
316
|
-
// We adopt `baseChild` for this purpose.
|
|
317
|
-
baseChild ??
|
|
318
|
-
(0, index_js_2.fail)("Should not have two undefined node IDs"));
|
|
461
|
+
const handler = getChangeHandler(this.fieldKinds, baseFieldChange.fieldKind);
|
|
462
|
+
const fieldChange = {
|
|
463
|
+
...baseFieldChange,
|
|
464
|
+
change: (0, index_js_2.brand)(handler.createEmpty()),
|
|
319
465
|
};
|
|
320
|
-
const
|
|
466
|
+
const rebasedNodeId = baseNodeId !== undefined
|
|
467
|
+
? rebasedNodeIdFromBaseNodeId(crossFieldTable, baseNodeId)
|
|
468
|
+
: undefined;
|
|
469
|
+
const fieldId = { nodeId: rebasedNodeId, field: fieldKey };
|
|
470
|
+
const rebasedField = handler.rebaser.rebase(fieldChange.change, baseFieldChange.change, rebaseChild, genId, new RebaseManager(crossFieldTable, baseFieldChange, fieldId), metadata);
|
|
321
471
|
const rebasedFieldChange = {
|
|
322
|
-
|
|
472
|
+
...baseFieldChange,
|
|
323
473
|
change: (0, index_js_2.brand)(rebasedField),
|
|
324
474
|
};
|
|
325
|
-
|
|
326
|
-
crossFieldTable.
|
|
327
|
-
baseChange: baseChanges,
|
|
475
|
+
// TODO: Deduplicate
|
|
476
|
+
crossFieldTable.baseFieldToContext.set(baseFieldChange, {
|
|
328
477
|
newChange: fieldChange,
|
|
478
|
+
baseChange: baseFieldChange,
|
|
329
479
|
rebasedChange: rebasedFieldChange,
|
|
480
|
+
fieldId,
|
|
481
|
+
baseNodeIds: [],
|
|
330
482
|
});
|
|
483
|
+
crossFieldTable.rebasedFields.add(rebasedFieldChange);
|
|
484
|
+
this.attachRebasedField(rebasedFields, rebasedNodes, crossFieldTable, rebasedFieldChange, fieldId, genId, metadata);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
attachRebasedField(rebasedFields, rebasedNodes, table, rebasedField, { nodeId, field: fieldKey }, idAllocator, metadata) {
|
|
488
|
+
if (nodeId === undefined) {
|
|
489
|
+
rebasedFields.set(fieldKey, rebasedField);
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
const rebasedNode = (0, index_js_1.getFromChangeAtomIdMap)(rebasedNodes, nodeId);
|
|
493
|
+
if (rebasedNode !== undefined) {
|
|
494
|
+
if (rebasedNode.fieldChanges === undefined) {
|
|
495
|
+
rebasedNode.fieldChanges = new Map([[fieldKey, rebasedField]]);
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
(0, internal_1.assert)(!rebasedNode.fieldChanges.has(fieldKey), 0x9c4 /* Expected an empty field */);
|
|
499
|
+
rebasedNode.fieldChanges.set(fieldKey, rebasedField);
|
|
500
|
+
return;
|
|
331
501
|
}
|
|
332
|
-
|
|
502
|
+
const newNode = {
|
|
503
|
+
fieldChanges: new Map([[fieldKey, rebasedField]]),
|
|
504
|
+
};
|
|
505
|
+
(0, index_js_1.setInChangeAtomIdMap)(rebasedNodes, nodeId, newNode);
|
|
506
|
+
(0, index_js_1.setInChangeAtomIdMap)(table.baseToRebasedNodeId, nodeId, nodeId);
|
|
507
|
+
const parentFieldId = getParentFieldId(table.baseChange, nodeId);
|
|
508
|
+
this.attachRebasedNode(rebasedFields, rebasedNodes, table, nodeId, parentFieldId, idAllocator, metadata);
|
|
509
|
+
}
|
|
510
|
+
attachRebasedNode(rebasedFields, rebasedNodes, table, baseNodeId, parentFieldIdBase, idAllocator, metadata) {
|
|
511
|
+
const baseFieldChange = fieldChangeFromId(table.baseChange.fieldChanges, table.baseChange.nodeChanges, parentFieldIdBase);
|
|
512
|
+
const rebasedFieldId = rebasedFieldIdFromBaseId(table, parentFieldIdBase);
|
|
513
|
+
(0, index_js_1.setInChangeAtomIdMap)(table.rebasedNodeToParent, baseNodeId, rebasedFieldId);
|
|
514
|
+
const context = table.baseFieldToContext.get(baseFieldChange);
|
|
515
|
+
if (context !== undefined) {
|
|
516
|
+
// We've already processed this field.
|
|
517
|
+
// The new child node can be attached when processing invalidated fields.
|
|
518
|
+
context.baseNodeIds.push(baseNodeId);
|
|
519
|
+
table.invalidatedFields.add(baseFieldChange);
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
const handler = getChangeHandler(this.fieldKinds, baseFieldChange.fieldKind);
|
|
523
|
+
const fieldChange = {
|
|
524
|
+
...baseFieldChange,
|
|
525
|
+
change: (0, index_js_2.brand)(handler.createEmpty()),
|
|
526
|
+
};
|
|
527
|
+
const rebasedChangeset = handler.rebaser.rebase(handler.createEmpty(), baseFieldChange.change, (_idNew, idBase) => idBase !== undefined && (0, index_js_1.areEqualChangeAtomIds)(idBase, baseNodeId)
|
|
528
|
+
? baseNodeId
|
|
529
|
+
: undefined, idAllocator, new RebaseManager(table, baseFieldChange, rebasedFieldId), metadata);
|
|
530
|
+
const rebasedField = { ...baseFieldChange, change: (0, index_js_2.brand)(rebasedChangeset) };
|
|
531
|
+
table.rebasedFields.add(rebasedField);
|
|
532
|
+
table.baseFieldToContext.set(baseFieldChange, {
|
|
533
|
+
newChange: fieldChange,
|
|
534
|
+
baseChange: baseFieldChange,
|
|
535
|
+
rebasedChange: rebasedField,
|
|
536
|
+
fieldId: rebasedFieldId,
|
|
537
|
+
baseNodeIds: [],
|
|
538
|
+
});
|
|
539
|
+
this.attachRebasedField(rebasedFields, rebasedNodes, table, rebasedField, rebasedFieldId, idAllocator, metadata);
|
|
540
|
+
}
|
|
541
|
+
rebaseFieldMap(change, over, parentId, genId, crossFieldTable, revisionMetadata) {
|
|
542
|
+
const rebasedFields = new Map();
|
|
543
|
+
const rebaseChild = (child, baseChild, stateChange) => {
|
|
544
|
+
if (child !== undefined && baseChild !== undefined) {
|
|
545
|
+
crossFieldTable.nodeIdPairs.push([child, baseChild, stateChange]);
|
|
546
|
+
}
|
|
547
|
+
return child;
|
|
548
|
+
};
|
|
333
549
|
for (const [field, fieldChange] of change) {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
const { fieldKind, change1: fieldChangeset, change2: baseChangeset, } = this.normalizeFieldChanges(fieldChange, baseChanges, genId, revisionMetadata);
|
|
340
|
-
// TODO: Don't we need to add an entry in the context table?
|
|
341
|
-
const manager = newCrossFieldManager(crossFieldTable, fieldChange);
|
|
342
|
-
const rebasedChangeset = fieldKind.changeHandler.rebaser.rebase(fieldChangeset, baseChangeset, (child, baseChild) => {
|
|
343
|
-
(0, internal_1.assert)(baseChild === undefined, 0x5b6 /* This field should not have any base changes */);
|
|
344
|
-
crossFieldTable.nodeIdPairs.push([child, undefined]);
|
|
345
|
-
return child;
|
|
346
|
-
}, genId, manager, revisionMetadata);
|
|
347
|
-
const rebasedFieldChange = {
|
|
348
|
-
fieldKind: fieldKind.identifier,
|
|
349
|
-
change: (0, index_js_2.brand)(rebasedChangeset),
|
|
350
|
-
};
|
|
351
|
-
rebasedFields.set(field, rebasedFieldChange);
|
|
550
|
+
const fieldId = { nodeId: parentId, field };
|
|
551
|
+
const baseChange = over.get(field);
|
|
552
|
+
if (baseChange === undefined) {
|
|
553
|
+
rebasedFields.set(field, fieldChange);
|
|
554
|
+
continue;
|
|
352
555
|
}
|
|
556
|
+
const { fieldKind, changeHandler, change1: fieldChangeset, change2: baseChangeset, } = this.normalizeFieldChanges(fieldChange, baseChange, genId, revisionMetadata);
|
|
557
|
+
const manager = new RebaseManager(crossFieldTable, baseChange, fieldId);
|
|
558
|
+
const rebasedField = changeHandler.rebaser.rebase(fieldChangeset, baseChangeset, rebaseChild, genId, manager, revisionMetadata);
|
|
559
|
+
const rebasedFieldChange = {
|
|
560
|
+
fieldKind,
|
|
561
|
+
change: (0, index_js_2.brand)(rebasedField),
|
|
562
|
+
};
|
|
563
|
+
rebasedFields.set(field, rebasedFieldChange);
|
|
564
|
+
crossFieldTable.baseFieldToContext.set(baseChange, {
|
|
565
|
+
baseChange,
|
|
566
|
+
newChange: fieldChange,
|
|
567
|
+
rebasedChange: rebasedFieldChange,
|
|
568
|
+
fieldId,
|
|
569
|
+
baseNodeIds: [],
|
|
570
|
+
});
|
|
571
|
+
crossFieldTable.rebasedFields.add(rebasedFieldChange);
|
|
353
572
|
}
|
|
354
573
|
return rebasedFields;
|
|
355
574
|
}
|
|
356
|
-
rebaseNodeChange(
|
|
357
|
-
const
|
|
358
|
-
|
|
359
|
-
return undefined;
|
|
360
|
-
}
|
|
575
|
+
rebaseNodeChange(newId, baseId, genId, crossFieldTable, revisionMetadata, constraintState) {
|
|
576
|
+
const change = nodeChangeFromId(crossFieldTable.newChange.nodeChanges, newId);
|
|
577
|
+
const over = nodeChangeFromId(crossFieldTable.baseChange.nodeChanges, baseId);
|
|
361
578
|
const baseMap = over?.fieldChanges ?? new Map();
|
|
362
|
-
const fieldChanges =
|
|
579
|
+
const fieldChanges = change.fieldChanges !== undefined && over.fieldChanges !== undefined
|
|
580
|
+
? this.rebaseFieldMap(change?.fieldChanges ?? new Map(), baseMap, newId, genId, crossFieldTable, revisionMetadata)
|
|
581
|
+
: change.fieldChanges;
|
|
363
582
|
const rebasedChange = {};
|
|
364
|
-
if (fieldChanges.size > 0) {
|
|
583
|
+
if (fieldChanges !== undefined && fieldChanges.size > 0) {
|
|
365
584
|
rebasedChange.fieldChanges = fieldChanges;
|
|
366
585
|
}
|
|
367
586
|
if (change?.nodeExistsConstraint !== undefined) {
|
|
368
587
|
rebasedChange.nodeExistsConstraint = change.nodeExistsConstraint;
|
|
369
588
|
}
|
|
370
|
-
crossFieldTable.
|
|
589
|
+
(0, index_js_1.setInChangeAtomIdMap)(crossFieldTable.baseToRebasedNodeId, baseId, newId);
|
|
371
590
|
return rebasedChange;
|
|
372
591
|
}
|
|
373
592
|
updateConstraintsForFields(fields, parentAttachState, constraintState, nodes) {
|
|
@@ -399,6 +618,9 @@ class ModularChangeFamily {
|
|
|
399
618
|
}
|
|
400
619
|
}
|
|
401
620
|
pruneFieldMap(changeset, nodeMap) {
|
|
621
|
+
if (changeset === undefined) {
|
|
622
|
+
return undefined;
|
|
623
|
+
}
|
|
402
624
|
const prunedChangeset = new Map();
|
|
403
625
|
for (const [field, fieldChange] of changeset) {
|
|
404
626
|
const handler = getChangeHandler(this.fieldKinds, fieldChange.fieldKind);
|
|
@@ -410,8 +632,7 @@ class ModularChangeFamily {
|
|
|
410
632
|
return prunedChangeset.size > 0 ? prunedChangeset : undefined;
|
|
411
633
|
}
|
|
412
634
|
pruneNodeChange(nodeId, nodeMap) {
|
|
413
|
-
const changeset = (
|
|
414
|
-
(0, internal_1.assert)(changeset !== undefined, 0x930 /* Unknown node ID */);
|
|
635
|
+
const changeset = nodeChangeFromId(nodeMap, nodeId);
|
|
415
636
|
const prunedFields = changeset.fieldChanges !== undefined
|
|
416
637
|
? this.pruneFieldMap(changeset.fieldChanges, nodeMap)
|
|
417
638
|
: undefined;
|
|
@@ -424,7 +645,7 @@ class ModularChangeFamily {
|
|
|
424
645
|
return undefined;
|
|
425
646
|
}
|
|
426
647
|
else {
|
|
427
|
-
(0,
|
|
648
|
+
(0, index_js_1.setInChangeAtomIdMap)(nodeMap, nodeId, prunedChange);
|
|
428
649
|
return nodeId;
|
|
429
650
|
}
|
|
430
651
|
}
|
|
@@ -438,10 +659,19 @@ class ModularChangeFamily {
|
|
|
438
659
|
id,
|
|
439
660
|
this.replaceNodeChangesetRevisions(nodeChangeset, oldRevisions, newRevision),
|
|
440
661
|
]));
|
|
662
|
+
const updatedNodeToParent = (0, index_js_2.nestedMapFromFlatList)((0, index_js_2.nestedMapToFlatList)(change.nodeToParent).map(([revision, id, fieldId]) => [
|
|
663
|
+
replaceRevision(revision, oldRevisions, newRevision),
|
|
664
|
+
id,
|
|
665
|
+
replaceFieldIdRevision(normalizeFieldId(fieldId, change.nodeAliases), oldRevisions, newRevision),
|
|
666
|
+
]));
|
|
441
667
|
const updated = {
|
|
442
668
|
...change,
|
|
443
669
|
fieldChanges: updatedFields,
|
|
444
670
|
nodeChanges: updatedNodes,
|
|
671
|
+
nodeToParent: updatedNodeToParent,
|
|
672
|
+
// We've updated all references to old node IDs, so we no longer need an alias table.
|
|
673
|
+
nodeAliases: new Map(),
|
|
674
|
+
crossFieldKeys: replaceCrossFieldKeyTableRevisions(change.crossFieldKeys, oldRevisions, newRevision, change.nodeAliases),
|
|
445
675
|
};
|
|
446
676
|
if (change.builds !== undefined) {
|
|
447
677
|
updated.builds = replaceIdMapRevisions(change.builds, oldRevisions, newRevision);
|
|
@@ -474,17 +704,63 @@ class ModularChangeFamily {
|
|
|
474
704
|
replaceFieldMapRevisions(fields, oldRevisions, newRevision) {
|
|
475
705
|
const updatedFields = new Map();
|
|
476
706
|
for (const [field, fieldChange] of fields) {
|
|
477
|
-
const updatedFieldChange =
|
|
478
|
-
updatedFields.set(field, { ...fieldChange, change: updatedFieldChange });
|
|
707
|
+
const updatedFieldChange = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).rebaser.replaceRevisions(fieldChange.change, oldRevisions, newRevision);
|
|
708
|
+
updatedFields.set(field, { ...fieldChange, change: (0, index_js_2.brand)(updatedFieldChange) });
|
|
479
709
|
}
|
|
480
710
|
return updatedFields;
|
|
481
711
|
}
|
|
712
|
+
makeCrossFieldKeyTable(fields, nodes) {
|
|
713
|
+
const keys = newCrossFieldKeyTable();
|
|
714
|
+
this.populateCrossFieldKeyTableForFieldMap(keys, fields, undefined);
|
|
715
|
+
(0, index_js_2.forEachInNestedMap)(nodes, (node, revision, localId) => {
|
|
716
|
+
if (node.fieldChanges !== undefined) {
|
|
717
|
+
this.populateCrossFieldKeyTableForFieldMap(keys, node.fieldChanges, {
|
|
718
|
+
revision,
|
|
719
|
+
localId,
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
});
|
|
723
|
+
return keys;
|
|
724
|
+
}
|
|
725
|
+
populateCrossFieldKeyTableForFieldMap(table, fields, parent) {
|
|
726
|
+
for (const [fieldKey, fieldChange] of fields) {
|
|
727
|
+
const keys = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).getCrossFieldKeys(fieldChange.change);
|
|
728
|
+
for (const key of keys) {
|
|
729
|
+
table.set(key, { nodeId: parent, field: fieldKey });
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
}
|
|
482
733
|
buildEditor(changeReceiver) {
|
|
483
|
-
return new ModularEditBuilder(this, changeReceiver);
|
|
734
|
+
return new ModularEditBuilder(this, this.fieldKinds, changeReceiver);
|
|
735
|
+
}
|
|
736
|
+
createEmptyFieldChange(fieldKind) {
|
|
737
|
+
const emptyChange = getChangeHandler(this.fieldKinds, fieldKind).createEmpty();
|
|
738
|
+
return { fieldKind, change: (0, index_js_2.brand)(emptyChange) };
|
|
484
739
|
}
|
|
485
740
|
}
|
|
486
741
|
exports.ModularChangeFamily = ModularChangeFamily;
|
|
487
742
|
ModularChangeFamily.emptyChange = makeModularChangeset();
|
|
743
|
+
function replaceCrossFieldKeyTableRevisions(table, oldRevisions, newRevision, nodeAliases) {
|
|
744
|
+
const updated = newBTree();
|
|
745
|
+
table.forEachPair(([target, revision, id, count], field) => {
|
|
746
|
+
const updatedKey = [
|
|
747
|
+
target,
|
|
748
|
+
replaceRevision(revision, oldRevisions, newRevision),
|
|
749
|
+
id,
|
|
750
|
+
count,
|
|
751
|
+
];
|
|
752
|
+
const normalizedFieldId = normalizeFieldId(field, nodeAliases);
|
|
753
|
+
const updatedNodeId = normalizedFieldId.nodeId !== undefined
|
|
754
|
+
? (0, index_js_1.replaceAtomRevisions)(normalizedFieldId.nodeId, oldRevisions, newRevision)
|
|
755
|
+
: undefined;
|
|
756
|
+
const updatedValue = {
|
|
757
|
+
...normalizedFieldId,
|
|
758
|
+
nodeId: updatedNodeId,
|
|
759
|
+
};
|
|
760
|
+
updated.set(updatedKey, updatedValue);
|
|
761
|
+
});
|
|
762
|
+
return updated;
|
|
763
|
+
}
|
|
488
764
|
function replaceRevision(revision, oldRevisions, newRevision) {
|
|
489
765
|
return oldRevisions.has(revision) ? newRevision : revision;
|
|
490
766
|
}
|
|
@@ -600,8 +876,7 @@ function* relevantRemovedRootsFromFields(change, nodeChanges, fieldKinds) {
|
|
|
600
876
|
for (const [_, fieldChange] of change) {
|
|
601
877
|
const handler = getChangeHandler(fieldKinds, fieldChange.fieldKind);
|
|
602
878
|
const delegate = function* (node) {
|
|
603
|
-
const nodeChangeset = (
|
|
604
|
-
(0, internal_1.assert)(nodeChangeset !== undefined, 0x931 /* Unknown node ID */);
|
|
879
|
+
const nodeChangeset = nodeChangeFromId(nodeChanges, node);
|
|
605
880
|
if (nodeChangeset.fieldChanges !== undefined) {
|
|
606
881
|
yield* relevantRemovedRootsFromFields(nodeChangeset.fieldChanges, nodeChanges, fieldKinds);
|
|
607
882
|
}
|
|
@@ -655,7 +930,7 @@ function updateRefreshers(change, getDetachedNode, removedRoots, requireRefreshe
|
|
|
655
930
|
}
|
|
656
931
|
}
|
|
657
932
|
const { fieldChanges, nodeChanges, maxId, revisions, constraintViolationCount, builds, destroys, } = change;
|
|
658
|
-
return makeModularChangeset(fieldChanges, nodeChanges, maxId, revisions, constraintViolationCount, builds, destroys, refreshers);
|
|
933
|
+
return makeModularChangeset(fieldChanges, nodeChanges, change.nodeToParent, change.nodeAliases, change.crossFieldKeys, maxId, revisions, constraintViolationCount, builds, destroys, refreshers);
|
|
659
934
|
}
|
|
660
935
|
exports.updateRefreshers = updateRefreshers;
|
|
661
936
|
/**
|
|
@@ -713,8 +988,7 @@ function intoDeltaImpl(change, nodeChanges, idAllocator, fieldKinds) {
|
|
|
713
988
|
const delta = new Map();
|
|
714
989
|
for (const [field, fieldChange] of change) {
|
|
715
990
|
const deltaField = getChangeHandler(fieldKinds, fieldChange.fieldKind).intoDelta(fieldChange.change, (childChange) => {
|
|
716
|
-
const nodeChange = (
|
|
717
|
-
(0, internal_1.assert)(nodeChange !== undefined, 0x932 /* Unknown node ID */);
|
|
991
|
+
const nodeChange = nodeChangeFromId(nodeChanges, childChange);
|
|
718
992
|
return deltaFromNodeChange(nodeChange, nodeChanges, idAllocator, fieldKinds);
|
|
719
993
|
}, idAllocator);
|
|
720
994
|
if (!(0, index_js_1.isEmptyFieldChanges)(deltaField)) {
|
|
@@ -774,12 +1048,20 @@ function getChangeHandler(fieldKinds, kind) {
|
|
|
774
1048
|
return getFieldKind(fieldKinds, kind).changeHandler;
|
|
775
1049
|
}
|
|
776
1050
|
exports.getChangeHandler = getChangeHandler;
|
|
777
|
-
function newComposeTable() {
|
|
1051
|
+
function newComposeTable(baseChange, newChange) {
|
|
778
1052
|
return {
|
|
779
1053
|
...newCrossFieldTable(),
|
|
1054
|
+
baseChange,
|
|
1055
|
+
newChange,
|
|
780
1056
|
fieldToContext: new Map(),
|
|
781
|
-
|
|
782
|
-
|
|
1057
|
+
newFieldToBaseField: new Map(),
|
|
1058
|
+
newToBaseNodeId: new Map(),
|
|
1059
|
+
composedNodes: new Set(),
|
|
1060
|
+
pendingCompositions: {
|
|
1061
|
+
nodeIdsToCompose: [],
|
|
1062
|
+
affectedBaseFields: newBTree(),
|
|
1063
|
+
affectedNewFields: newBTree(),
|
|
1064
|
+
},
|
|
783
1065
|
};
|
|
784
1066
|
}
|
|
785
1067
|
function newCrossFieldTable() {
|
|
@@ -796,43 +1078,148 @@ function newConstraintState(violationCount) {
|
|
|
796
1078
|
violationCount,
|
|
797
1079
|
};
|
|
798
1080
|
}
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
crossFieldTable.invalidatedFields.add(dependentEntry.value);
|
|
814
|
-
}
|
|
815
|
-
firstId = (0, index_js_2.brand)(firstId + dependentEntry.length);
|
|
1081
|
+
class CrossFieldManagerI {
|
|
1082
|
+
constructor(crossFieldTable, currentFieldKey, allowInval = true) {
|
|
1083
|
+
this.crossFieldTable = crossFieldTable;
|
|
1084
|
+
this.currentFieldKey = currentFieldKey;
|
|
1085
|
+
this.allowInval = allowInval;
|
|
1086
|
+
}
|
|
1087
|
+
set(target, revision, id, count, newValue, invalidateDependents) {
|
|
1088
|
+
if (invalidateDependents && this.allowInval) {
|
|
1089
|
+
const lastChangedId = id + count - 1;
|
|
1090
|
+
let firstId = id;
|
|
1091
|
+
while (firstId <= lastChangedId) {
|
|
1092
|
+
const dependentEntry = (0, crossFieldQueries_js_1.getFirstFromCrossFieldMap)(this.getDependents(target), revision, firstId, lastChangedId - firstId + 1);
|
|
1093
|
+
if (dependentEntry.value !== undefined) {
|
|
1094
|
+
this.crossFieldTable.invalidatedFields.add(dependentEntry.value);
|
|
816
1095
|
}
|
|
1096
|
+
firstId = (0, index_js_2.brand)(firstId + dependentEntry.length);
|
|
817
1097
|
}
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
1098
|
+
}
|
|
1099
|
+
(0, crossFieldQueries_js_1.setInCrossFieldMap)(this.getMap(target), revision, id, count, newValue);
|
|
1100
|
+
}
|
|
1101
|
+
get(target, revision, id, count, addDependency) {
|
|
1102
|
+
if (addDependency) {
|
|
1103
|
+
// We assume that if there is already an entry for this ID it is because
|
|
1104
|
+
// a field handler has called compose on the same node multiple times.
|
|
1105
|
+
// In this case we only want to update the latest version, so we overwrite the dependency.
|
|
1106
|
+
(0, crossFieldQueries_js_1.setInCrossFieldMap)(this.getDependents(target), revision, id, count, this.currentFieldKey);
|
|
1107
|
+
}
|
|
1108
|
+
return (0, crossFieldQueries_js_1.getFirstFromCrossFieldMap)(this.getMap(target), revision, id, count);
|
|
1109
|
+
}
|
|
1110
|
+
getMap(target) {
|
|
1111
|
+
return target === crossFieldQueries_js_1.CrossFieldTarget.Source
|
|
1112
|
+
? this.crossFieldTable.srcTable
|
|
1113
|
+
: this.crossFieldTable.dstTable;
|
|
1114
|
+
}
|
|
1115
|
+
getDependents(target) {
|
|
1116
|
+
return target === crossFieldQueries_js_1.CrossFieldTarget.Source
|
|
1117
|
+
? this.crossFieldTable.srcDependents
|
|
1118
|
+
: this.crossFieldTable.dstDependents;
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
class InvertManager extends CrossFieldManagerI {
|
|
1122
|
+
constructor(table, field, fieldId, allowInval = true) {
|
|
1123
|
+
super(table, field, allowInval);
|
|
1124
|
+
this.fieldId = fieldId;
|
|
1125
|
+
}
|
|
1126
|
+
onMoveIn(id) {
|
|
1127
|
+
(0, index_js_1.setInChangeAtomIdMap)(this.table.invertedNodeToParent, id, this.fieldId);
|
|
1128
|
+
}
|
|
1129
|
+
moveKey(target, revision, id, count) {
|
|
1130
|
+
(0, internal_1.assert)(false, 0x9c5 /* Keys should not be moved manually during invert */);
|
|
1131
|
+
}
|
|
1132
|
+
get table() {
|
|
1133
|
+
return this.crossFieldTable;
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
class RebaseManager extends CrossFieldManagerI {
|
|
1137
|
+
constructor(table, currentField, fieldId, allowInval = true) {
|
|
1138
|
+
super(table, currentField, allowInval);
|
|
1139
|
+
this.fieldId = fieldId;
|
|
1140
|
+
}
|
|
1141
|
+
set(target, revision, id, count, newValue, invalidateDependents) {
|
|
1142
|
+
if (invalidateDependents && this.allowInval) {
|
|
1143
|
+
const newFieldIds = getFieldsForCrossFieldKey(this.table.newChange, [
|
|
1144
|
+
target,
|
|
1145
|
+
revision,
|
|
1146
|
+
id,
|
|
1147
|
+
count,
|
|
1148
|
+
]);
|
|
1149
|
+
(0, internal_1.assert)(newFieldIds.length === 0, 0x9c6 /* TODO: Modifying a cross-field key from the new changeset is currently unsupported */);
|
|
1150
|
+
const baseFieldIds = getFieldsForCrossFieldKey(this.table.baseChange, [
|
|
1151
|
+
target,
|
|
1152
|
+
revision,
|
|
1153
|
+
id,
|
|
1154
|
+
count,
|
|
1155
|
+
]);
|
|
1156
|
+
(0, internal_1.assert)(baseFieldIds.length > 0, 0x9c7 /* Cross field key not registered in base or new change */);
|
|
1157
|
+
for (const baseFieldId of baseFieldIds) {
|
|
1158
|
+
this.table.affectedBaseFields.set([baseFieldId.nodeId?.revision, baseFieldId.nodeId?.localId, baseFieldId.field], true);
|
|
826
1159
|
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
}
|
|
830
|
-
|
|
1160
|
+
}
|
|
1161
|
+
super.set(target, revision, id, count, newValue, invalidateDependents);
|
|
1162
|
+
}
|
|
1163
|
+
onMoveIn(id) {
|
|
1164
|
+
(0, index_js_1.setInChangeAtomIdMap)(this.table.rebasedNodeToParent, id, this.fieldId);
|
|
1165
|
+
}
|
|
1166
|
+
moveKey(target, revision, id, count) {
|
|
1167
|
+
setInCrossFieldKeyTable(this.table.rebasedCrossFieldKeys, target, revision, id, count, this.fieldId);
|
|
1168
|
+
}
|
|
1169
|
+
get table() {
|
|
1170
|
+
return this.crossFieldTable;
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
// TODO: Deduplicate this with RebaseTable
|
|
1174
|
+
class ComposeManager extends CrossFieldManagerI {
|
|
1175
|
+
constructor(table, currentField, allowInval = true) {
|
|
1176
|
+
super(table, currentField, allowInval);
|
|
1177
|
+
}
|
|
1178
|
+
set(target, revision, id, count, newValue, invalidateDependents) {
|
|
1179
|
+
if (invalidateDependents && this.allowInval) {
|
|
1180
|
+
const newFieldIds = getFieldsForCrossFieldKey(this.table.newChange, [
|
|
1181
|
+
target,
|
|
1182
|
+
revision,
|
|
1183
|
+
id,
|
|
1184
|
+
count,
|
|
1185
|
+
]);
|
|
1186
|
+
if (newFieldIds.length > 0) {
|
|
1187
|
+
for (const newFieldId of newFieldIds) {
|
|
1188
|
+
this.table.pendingCompositions.affectedNewFields.set([newFieldId.nodeId?.revision, newFieldId.nodeId?.localId, newFieldId.field], true);
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
else {
|
|
1192
|
+
const baseFieldIds = getFieldsForCrossFieldKey(this.table.baseChange, [
|
|
1193
|
+
target,
|
|
1194
|
+
revision,
|
|
1195
|
+
id,
|
|
1196
|
+
count,
|
|
1197
|
+
]);
|
|
1198
|
+
(0, internal_1.assert)(baseFieldIds.length > 0, 0x9c8 /* Cross field key not registered in base or new change */);
|
|
1199
|
+
for (const baseFieldId of baseFieldIds) {
|
|
1200
|
+
this.table.pendingCompositions.affectedBaseFields.set([baseFieldId.nodeId?.revision, baseFieldId.nodeId?.localId, baseFieldId.field], true);
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
super.set(target, revision, id, count, newValue, invalidateDependents);
|
|
1205
|
+
}
|
|
1206
|
+
onMoveIn(id) {
|
|
1207
|
+
throw new Error("Method not implemented.");
|
|
1208
|
+
}
|
|
1209
|
+
moveKey(target, revision, id, count) {
|
|
1210
|
+
throw new Error("Method not implemented.");
|
|
1211
|
+
}
|
|
1212
|
+
get table() {
|
|
1213
|
+
return this.crossFieldTable;
|
|
1214
|
+
}
|
|
831
1215
|
}
|
|
832
|
-
function makeModularChangeset(fieldChanges = undefined, nodeChanges = undefined, maxId = -1, revisions = undefined, constraintViolationCount = undefined, builds, destroys, refreshers) {
|
|
1216
|
+
function makeModularChangeset(fieldChanges = undefined, nodeChanges = undefined, nodeToParent = undefined, nodeAliases = undefined, crossFieldKeys = undefined, maxId = -1, revisions = undefined, constraintViolationCount = undefined, builds, destroys, refreshers) {
|
|
833
1217
|
const changeset = {
|
|
834
1218
|
fieldChanges: fieldChanges ?? new Map(),
|
|
835
1219
|
nodeChanges: nodeChanges ?? new Map(),
|
|
1220
|
+
nodeToParent: nodeToParent ?? new Map(),
|
|
1221
|
+
nodeAliases: nodeAliases ?? new Map(),
|
|
1222
|
+
crossFieldKeys: crossFieldKeys ?? newCrossFieldKeyTable(),
|
|
836
1223
|
};
|
|
837
1224
|
if (revisions !== undefined && revisions.length > 0) {
|
|
838
1225
|
changeset.revisions = revisions;
|
|
@@ -855,8 +1242,9 @@ function makeModularChangeset(fieldChanges = undefined, nodeChanges = undefined,
|
|
|
855
1242
|
return changeset;
|
|
856
1243
|
}
|
|
857
1244
|
class ModularEditBuilder extends index_js_1.EditBuilder {
|
|
858
|
-
constructor(family, changeReceiver) {
|
|
1245
|
+
constructor(family, fieldKinds, changeReceiver) {
|
|
859
1246
|
super(family, changeReceiver);
|
|
1247
|
+
this.fieldKinds = fieldKinds;
|
|
860
1248
|
this.transactionDepth = 0;
|
|
861
1249
|
this.idAllocator = (0, index_js_2.idAllocatorFromMaxId)();
|
|
862
1250
|
}
|
|
@@ -902,7 +1290,8 @@ class ModularEditBuilder extends index_js_1.EditBuilder {
|
|
|
902
1290
|
* @param maxId - the highest `ChangesetLocalId` used in this change
|
|
903
1291
|
*/
|
|
904
1292
|
submitChange(field, fieldKind, change) {
|
|
905
|
-
const
|
|
1293
|
+
const crossFieldKeys = getChangeHandler(this.fieldKinds, fieldKind).getCrossFieldKeys(change);
|
|
1294
|
+
const modularChange = buildModularChangesetFromField(field, { fieldKind, change }, new Map(), new Map(), newCrossFieldKeyTable(), this.idAllocator, crossFieldKeys);
|
|
906
1295
|
this.applyChange(modularChange);
|
|
907
1296
|
}
|
|
908
1297
|
submitChanges(changes) {
|
|
@@ -911,11 +1300,11 @@ class ModularEditBuilder extends index_js_1.EditBuilder {
|
|
|
911
1300
|
}
|
|
912
1301
|
buildChanges(changes) {
|
|
913
1302
|
const changeMaps = changes.map((change) => (0, index_js_1.makeAnonChange)(change.type === "global"
|
|
914
|
-
? makeModularChangeset(undefined, undefined, this.idAllocator.getMaxId(), undefined, undefined, change.builds)
|
|
1303
|
+
? makeModularChangeset(undefined, undefined, undefined, undefined, undefined, this.idAllocator.getMaxId(), undefined, undefined, change.builds)
|
|
915
1304
|
: buildModularChangesetFromField(change.field, {
|
|
916
1305
|
fieldKind: change.fieldKind,
|
|
917
1306
|
change: change.change,
|
|
918
|
-
}, new Map(), this.idAllocator)));
|
|
1307
|
+
}, new Map(), new Map(), newCrossFieldKeyTable(), this.idAllocator, getChangeHandler(this.fieldKinds, change.fieldKind).getCrossFieldKeys(change.change))));
|
|
919
1308
|
const composedChange = this.changeFamily.rebaser.compose(changeMaps);
|
|
920
1309
|
const maxId = (0, index_js_2.brand)(this.idAllocator.getMaxId());
|
|
921
1310
|
if (maxId >= 0) {
|
|
@@ -930,29 +1319,47 @@ class ModularEditBuilder extends index_js_1.EditBuilder {
|
|
|
930
1319
|
const nodeChange = {
|
|
931
1320
|
nodeExistsConstraint: { violated: false },
|
|
932
1321
|
};
|
|
933
|
-
this.applyChange(buildModularChangesetFromNode(path, nodeChange, new Map(), this.idAllocator));
|
|
1322
|
+
this.applyChange(buildModularChangesetFromNode(path, nodeChange, new Map(), new Map(), newCrossFieldKeyTable(), this.idAllocator));
|
|
934
1323
|
}
|
|
935
1324
|
}
|
|
936
1325
|
exports.ModularEditBuilder = ModularEditBuilder;
|
|
937
|
-
function buildModularChangesetFromField(path, fieldChange, nodeChanges, idAllocator = (0, index_js_2.idAllocatorFromMaxId)()) {
|
|
1326
|
+
function buildModularChangesetFromField(path, fieldChange, nodeChanges, nodeToParent, crossFieldKeys, idAllocator = (0, index_js_2.idAllocatorFromMaxId)(), localCrossFieldKeys = [], childId = undefined) {
|
|
938
1327
|
const fieldChanges = new Map([[path.field, fieldChange]]);
|
|
939
1328
|
if (path.parent === undefined) {
|
|
940
|
-
|
|
1329
|
+
for (const key of localCrossFieldKeys) {
|
|
1330
|
+
crossFieldKeys.set(key, { nodeId: undefined, field: path.field });
|
|
1331
|
+
}
|
|
1332
|
+
if (childId !== undefined) {
|
|
1333
|
+
(0, index_js_1.setInChangeAtomIdMap)(nodeToParent, childId, {
|
|
1334
|
+
nodeId: undefined,
|
|
1335
|
+
field: path.field,
|
|
1336
|
+
});
|
|
1337
|
+
}
|
|
1338
|
+
return makeModularChangeset(fieldChanges, nodeChanges, nodeToParent, undefined, crossFieldKeys, idAllocator.getMaxId());
|
|
941
1339
|
}
|
|
942
1340
|
const nodeChangeset = {
|
|
943
1341
|
fieldChanges,
|
|
944
1342
|
};
|
|
945
|
-
|
|
1343
|
+
const parentId = { localId: (0, index_js_2.brand)(idAllocator.allocate()) };
|
|
1344
|
+
for (const key of localCrossFieldKeys) {
|
|
1345
|
+
crossFieldKeys.set(key, { nodeId: parentId, field: path.field });
|
|
1346
|
+
}
|
|
1347
|
+
if (childId !== undefined) {
|
|
1348
|
+
(0, index_js_1.setInChangeAtomIdMap)(nodeToParent, childId, {
|
|
1349
|
+
nodeId: parentId,
|
|
1350
|
+
field: path.field,
|
|
1351
|
+
});
|
|
1352
|
+
}
|
|
1353
|
+
return buildModularChangesetFromNode(path.parent, nodeChangeset, nodeChanges, nodeToParent, crossFieldKeys, idAllocator, parentId);
|
|
946
1354
|
}
|
|
947
|
-
function buildModularChangesetFromNode(path, nodeChange, nodeChanges, idAllocator) {
|
|
948
|
-
|
|
949
|
-
(0, index_js_2.setInNestedMap)(nodeChanges, nodeId.revision, nodeId.localId, nodeChange);
|
|
1355
|
+
function buildModularChangesetFromNode(path, nodeChange, nodeChanges, nodeToParent, crossFieldKeys, idAllocator, nodeId = { localId: (0, index_js_2.brand)(idAllocator.allocate()) }) {
|
|
1356
|
+
(0, index_js_1.setInChangeAtomIdMap)(nodeChanges, nodeId, nodeChange);
|
|
950
1357
|
const fieldChangeset = genericFieldKind_js_1.genericFieldKind.changeHandler.editor.buildChildChange(path.parentIndex, nodeId);
|
|
951
1358
|
const fieldChange = {
|
|
952
1359
|
fieldKind: genericFieldKind_js_1.genericFieldKind.identifier,
|
|
953
1360
|
change: fieldChangeset,
|
|
954
1361
|
};
|
|
955
|
-
return buildModularChangesetFromField({ parent: path.parent, field: path.parentField }, fieldChange, nodeChanges, idAllocator);
|
|
1362
|
+
return buildModularChangesetFromField({ parent: path.parent, field: path.parentField }, fieldChange, nodeChanges, nodeToParent, crossFieldKeys, idAllocator, [], nodeId);
|
|
956
1363
|
}
|
|
957
1364
|
function getRevInfoFromTaggedChanges(changes) {
|
|
958
1365
|
let maxId = -1;
|
|
@@ -1001,9 +1408,184 @@ function revisionFromRevInfos(revInfos) {
|
|
|
1001
1408
|
}
|
|
1002
1409
|
return revInfos[0].revision;
|
|
1003
1410
|
}
|
|
1004
|
-
function
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1411
|
+
function mergeBTrees(tree1, tree2) {
|
|
1412
|
+
const result = tree1.clone();
|
|
1413
|
+
tree2.forEachPair((k, v) => {
|
|
1414
|
+
result.set(k, v);
|
|
1415
|
+
});
|
|
1416
|
+
return result;
|
|
1417
|
+
}
|
|
1418
|
+
function mergeNestedMaps(map1, map2) {
|
|
1419
|
+
const merged = new Map();
|
|
1420
|
+
(0, index_js_2.populateNestedMap)(map1, merged, true);
|
|
1421
|
+
(0, index_js_2.populateNestedMap)(map2, merged, true);
|
|
1422
|
+
return merged;
|
|
1423
|
+
}
|
|
1424
|
+
function fieldChangeFromId(fields, nodes, id) {
|
|
1425
|
+
const fieldMap = fieldMapFromNodeId(fields, nodes, id.nodeId);
|
|
1426
|
+
return fieldMap.get(id.field) ?? (0, index_js_2.fail)("No field exists for the given ID");
|
|
1427
|
+
}
|
|
1428
|
+
function fieldMapFromNodeId(rootFieldMap, nodes, nodeId) {
|
|
1429
|
+
if (nodeId === undefined) {
|
|
1430
|
+
return rootFieldMap;
|
|
1431
|
+
}
|
|
1432
|
+
const node = nodeChangeFromId(nodes, nodeId);
|
|
1433
|
+
(0, internal_1.assert)(node.fieldChanges !== undefined, 0x9c9 /* Expected node to have field changes */);
|
|
1434
|
+
return node.fieldChanges;
|
|
1435
|
+
}
|
|
1436
|
+
function rebasedFieldIdFromBaseId(table, baseId) {
|
|
1437
|
+
if (baseId.nodeId === undefined) {
|
|
1438
|
+
return baseId;
|
|
1439
|
+
}
|
|
1440
|
+
return { ...baseId, nodeId: rebasedNodeIdFromBaseNodeId(table, baseId.nodeId) };
|
|
1441
|
+
}
|
|
1442
|
+
function rebasedNodeIdFromBaseNodeId(table, baseId) {
|
|
1443
|
+
return (0, index_js_1.getFromChangeAtomIdMap)(table.baseToRebasedNodeId, baseId) ?? baseId;
|
|
1444
|
+
}
|
|
1445
|
+
function nodeChangeFromId(nodes, id) {
|
|
1446
|
+
const node = (0, index_js_1.getFromChangeAtomIdMap)(nodes, id);
|
|
1447
|
+
(0, internal_1.assert)(node !== undefined, 0x9ca /* Unknown node ID */);
|
|
1448
|
+
return node;
|
|
1449
|
+
}
|
|
1450
|
+
function fieldIdFromFieldIdKey([revision, localId, field]) {
|
|
1451
|
+
const nodeId = localId !== undefined ? { revision, localId } : undefined;
|
|
1452
|
+
return { nodeId, field };
|
|
1453
|
+
}
|
|
1454
|
+
function cloneNodeChangeset(nodeChangeset) {
|
|
1455
|
+
if (nodeChangeset.fieldChanges !== undefined) {
|
|
1456
|
+
return { ...nodeChangeset, fieldChanges: new Map(nodeChangeset.fieldChanges) };
|
|
1457
|
+
}
|
|
1458
|
+
return { ...nodeChangeset };
|
|
1459
|
+
}
|
|
1460
|
+
function replaceFieldIdRevision(fieldId, oldRevisions, newRevision) {
|
|
1461
|
+
if (fieldId.nodeId === undefined) {
|
|
1462
|
+
return fieldId;
|
|
1463
|
+
}
|
|
1464
|
+
return {
|
|
1465
|
+
...fieldId,
|
|
1466
|
+
nodeId: (0, index_js_1.replaceAtomRevisions)(fieldId.nodeId, oldRevisions, newRevision),
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1469
|
+
function getParentFieldId(changeset, nodeId) {
|
|
1470
|
+
const parentId = (0, index_js_1.getFromChangeAtomIdMap)(changeset.nodeToParent, nodeId);
|
|
1471
|
+
(0, internal_1.assert)(parentId !== undefined, 0x9cb /* Parent field should be defined */);
|
|
1472
|
+
return normalizeFieldId(parentId, changeset.nodeAliases);
|
|
1473
|
+
}
|
|
1474
|
+
exports.getParentFieldId = getParentFieldId;
|
|
1475
|
+
function getFieldsForCrossFieldKey(changeset, [target, revision, id, count]) {
|
|
1476
|
+
let firstLocalId = id;
|
|
1477
|
+
const lastLocalId = id + count - 1;
|
|
1478
|
+
const fields = [];
|
|
1479
|
+
// eslint-disable-next-line no-constant-condition
|
|
1480
|
+
while (true) {
|
|
1481
|
+
const entry = getFirstIntersectingCrossFieldEntry(changeset.crossFieldKeys, [
|
|
1482
|
+
target,
|
|
1483
|
+
revision,
|
|
1484
|
+
(0, index_js_2.brand)(firstLocalId),
|
|
1485
|
+
count,
|
|
1486
|
+
]);
|
|
1487
|
+
if (entry === undefined) {
|
|
1488
|
+
return fields;
|
|
1489
|
+
}
|
|
1490
|
+
const [[_target, _revision, entryId, entryCount], fieldId] = entry;
|
|
1491
|
+
fields.push(normalizeFieldId(fieldId, changeset.nodeAliases));
|
|
1492
|
+
const entryLastId = entryId + entryCount - 1;
|
|
1493
|
+
if (entryLastId >= lastLocalId) {
|
|
1494
|
+
return fields;
|
|
1495
|
+
}
|
|
1496
|
+
firstLocalId = entryLastId + 1;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
exports.getFieldsForCrossFieldKey = getFieldsForCrossFieldKey;
|
|
1500
|
+
function getFirstIntersectingCrossFieldEntry(table, [target, revision, id, count]) {
|
|
1501
|
+
const entry = table.nextLowerPair([target, revision, id, Infinity]);
|
|
1502
|
+
if (entry === undefined) {
|
|
1503
|
+
return undefined;
|
|
1504
|
+
}
|
|
1505
|
+
const [entryTarget, entryRevision, entryId, entryCount] = entry[0];
|
|
1506
|
+
if (entryTarget !== target || entryRevision !== revision) {
|
|
1507
|
+
return undefined;
|
|
1508
|
+
}
|
|
1509
|
+
const lastQueryId = id + count - 1;
|
|
1510
|
+
const entryLastId = entryId + entryCount - 1;
|
|
1511
|
+
if (entryId > lastQueryId || entryLastId < id) {
|
|
1512
|
+
return undefined;
|
|
1513
|
+
}
|
|
1514
|
+
return entry;
|
|
1515
|
+
}
|
|
1516
|
+
function setInCrossFieldKeyTable(table, target, revision, id, count, value) {
|
|
1517
|
+
let entry = getFirstIntersectingCrossFieldEntry(table, [target, revision, id, count]);
|
|
1518
|
+
const lastQueryId = id + count - 1;
|
|
1519
|
+
while (entry !== undefined) {
|
|
1520
|
+
const [entryKey, entryValue] = entry;
|
|
1521
|
+
table.delete(entryKey);
|
|
1522
|
+
const [_target, _revision, entryId, entryCount] = entryKey;
|
|
1523
|
+
if (entryId < id) {
|
|
1524
|
+
table.set([target, revision, entryId, id - entryId], entryValue);
|
|
1525
|
+
}
|
|
1526
|
+
const lastEntryId = entryId + entryCount - 1;
|
|
1527
|
+
if (lastEntryId > lastQueryId) {
|
|
1528
|
+
table.set([target, revision, (0, index_js_2.brand)(lastQueryId + 1), lastEntryId - lastQueryId], entryValue);
|
|
1529
|
+
break;
|
|
1530
|
+
}
|
|
1531
|
+
const nextId = (0, index_js_2.brand)(lastEntryId + 1);
|
|
1532
|
+
entry = getFirstIntersectingCrossFieldEntry(table, [
|
|
1533
|
+
target,
|
|
1534
|
+
revision,
|
|
1535
|
+
nextId,
|
|
1536
|
+
lastQueryId - nextId + 1,
|
|
1537
|
+
]);
|
|
1538
|
+
}
|
|
1539
|
+
table.set([target, revision, id, count], value);
|
|
1540
|
+
}
|
|
1541
|
+
function normalizeFieldId(fieldId, nodeAliases) {
|
|
1542
|
+
return fieldId.nodeId !== undefined
|
|
1543
|
+
? { ...fieldId, nodeId: normalizeNodeId(fieldId.nodeId, nodeAliases) }
|
|
1544
|
+
: fieldId;
|
|
1545
|
+
}
|
|
1546
|
+
/**
|
|
1547
|
+
* @returns The canonical form of nodeId, according to nodeAliases
|
|
1548
|
+
*/
|
|
1549
|
+
function normalizeNodeId(nodeId, nodeAliases) {
|
|
1550
|
+
let currentId = nodeId;
|
|
1551
|
+
// eslint-disable-next-line no-constant-condition
|
|
1552
|
+
while (true) {
|
|
1553
|
+
const dealiased = (0, index_js_1.getFromChangeAtomIdMap)(nodeAliases, currentId);
|
|
1554
|
+
if (dealiased === undefined) {
|
|
1555
|
+
return currentId;
|
|
1556
|
+
}
|
|
1557
|
+
currentId = dealiased;
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
function hasConflicts(change) {
|
|
1561
|
+
return (change.constraintViolationCount ?? 0) > 0;
|
|
1562
|
+
}
|
|
1563
|
+
function newCrossFieldKeyTable() {
|
|
1564
|
+
return newBTree();
|
|
1565
|
+
}
|
|
1566
|
+
exports.newCrossFieldKeyTable = newCrossFieldKeyTable;
|
|
1567
|
+
function newBTree() {
|
|
1568
|
+
return (0, index_js_2.brand)(new sorted_btree_es6_1.BTree(undefined, compareTuples));
|
|
1569
|
+
}
|
|
1570
|
+
// This assumes that the arrays are the same length.
|
|
1571
|
+
function compareTuples(arrayA, arrayB) {
|
|
1572
|
+
for (let i = 0; i < arrayA.length; i++) {
|
|
1573
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1574
|
+
const a = arrayA[i];
|
|
1575
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1576
|
+
const b = arrayB[i];
|
|
1577
|
+
if (a < b) {
|
|
1578
|
+
return -1;
|
|
1579
|
+
}
|
|
1580
|
+
else if (a > b) {
|
|
1581
|
+
return 1;
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
return 0;
|
|
1585
|
+
}
|
|
1586
|
+
function cloneNestedMap(map) {
|
|
1587
|
+
const cloned = new Map();
|
|
1588
|
+
(0, index_js_2.populateNestedMap)(map, cloned, true);
|
|
1589
|
+
return cloned;
|
|
1008
1590
|
}
|
|
1009
1591
|
//# sourceMappingURL=modularChangeFamily.js.map
|