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