@fluidframework/tree 2.83.0 → 2.90.0-378676
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/api-report/tree.alpha.api.md +1 -0
- package/dist/core/change-family/changeFamily.d.ts +4 -1
- package/dist/core/change-family/changeFamily.d.ts.map +1 -1
- package/dist/core/change-family/changeFamily.js.map +1 -1
- package/dist/core/change-family/index.d.ts +1 -1
- package/dist/core/change-family/index.d.ts.map +1 -1
- package/dist/core/change-family/index.js.map +1 -1
- package/dist/core/index.d.ts +3 -3
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +6 -4
- package/dist/core/index.js.map +1 -1
- package/dist/core/rebase/changeRebaser.d.ts +6 -1
- package/dist/core/rebase/changeRebaser.d.ts.map +1 -1
- package/dist/core/rebase/changeRebaser.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 +2 -1
- package/dist/core/rebase/index.js.map +1 -1
- package/dist/core/rebase/types.d.ts +1 -0
- package/dist/core/rebase/types.d.ts.map +1 -1
- package/dist/core/rebase/types.js +5 -1
- package/dist/core/rebase/types.js.map +1 -1
- package/dist/core/rebase/utils.d.ts.map +1 -1
- package/dist/core/rebase/utils.js +25 -7
- package/dist/core/rebase/utils.js.map +1 -1
- package/dist/core/tree/delta.d.ts +5 -0
- package/dist/core/tree/delta.d.ts.map +1 -1
- package/dist/core/tree/delta.js.map +1 -1
- package/dist/core/tree/detachedFieldIndex.d.ts +13 -1
- package/dist/core/tree/detachedFieldIndex.d.ts.map +1 -1
- package/dist/core/tree/detachedFieldIndex.js +14 -1
- package/dist/core/tree/detachedFieldIndex.js.map +1 -1
- package/dist/core/tree/detachedFieldIndexTypes.d.ts +4 -0
- package/dist/core/tree/detachedFieldIndexTypes.d.ts.map +1 -1
- package/dist/core/tree/detachedFieldIndexTypes.js.map +1 -1
- package/dist/core/tree/index.d.ts +2 -2
- package/dist/core/tree/index.d.ts.map +1 -1
- package/dist/core/tree/index.js +4 -3
- package/dist/core/tree/index.js.map +1 -1
- package/dist/core/tree/pathTree.d.ts +11 -3
- package/dist/core/tree/pathTree.d.ts.map +1 -1
- package/dist/core/tree/pathTree.js +14 -2
- package/dist/core/tree/pathTree.js.map +1 -1
- package/dist/core/tree/visitDelta.d.ts.map +1 -1
- package/dist/core/tree/visitDelta.js +17 -13
- package/dist/core/tree/visitDelta.js.map +1 -1
- package/dist/feature-libraries/changeAtomIdBTree.d.ts +3 -2
- package/dist/feature-libraries/changeAtomIdBTree.d.ts.map +1 -1
- package/dist/feature-libraries/changeAtomIdBTree.js +15 -2
- package/dist/feature-libraries/changeAtomIdBTree.js.map +1 -1
- package/dist/feature-libraries/default-schema/defaultEditBuilder.d.ts +92 -44
- package/dist/feature-libraries/default-schema/defaultEditBuilder.d.ts.map +1 -1
- package/dist/feature-libraries/default-schema/defaultEditBuilder.js +220 -70
- 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 +12 -2
- package/dist/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
- package/dist/feature-libraries/default-schema/index.d.ts +2 -1
- package/dist/feature-libraries/default-schema/index.d.ts.map +1 -1
- package/dist/feature-libraries/default-schema/index.js +4 -2
- package/dist/feature-libraries/default-schema/index.js.map +1 -1
- package/dist/feature-libraries/default-schema/locationBasedEditBuilder.d.ts +40 -0
- package/dist/feature-libraries/default-schema/locationBasedEditBuilder.d.ts.map +1 -0
- package/dist/feature-libraries/default-schema/locationBasedEditBuilder.js +153 -0
- package/dist/feature-libraries/default-schema/locationBasedEditBuilder.js.map +1 -0
- package/dist/feature-libraries/default-schema/mappedEditBuilder.d.ts +7 -6
- package/dist/feature-libraries/default-schema/mappedEditBuilder.d.ts.map +1 -1
- package/dist/feature-libraries/default-schema/mappedEditBuilder.js +15 -0
- package/dist/feature-libraries/default-schema/mappedEditBuilder.js.map +1 -1
- package/dist/feature-libraries/deltaUtils.d.ts +1 -0
- package/dist/feature-libraries/deltaUtils.d.ts.map +1 -1
- package/dist/feature-libraries/deltaUtils.js +6 -1
- package/dist/feature-libraries/deltaUtils.js.map +1 -1
- package/dist/feature-libraries/flex-tree/context.d.ts +9 -0
- package/dist/feature-libraries/flex-tree/context.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/context.js +6 -0
- package/dist/feature-libraries/flex-tree/context.js.map +1 -1
- package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts +6 -6
- 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/lazyField.d.ts +8 -7
- package/dist/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.js +39 -8
- package/dist/feature-libraries/flex-tree/lazyField.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 +8 -4
- package/dist/feature-libraries/index.js.map +1 -1
- package/dist/feature-libraries/mitigatedChangeFamily.d.ts.map +1 -1
- package/dist/feature-libraries/mitigatedChangeFamily.js +2 -2
- package/dist/feature-libraries/mitigatedChangeFamily.js.map +1 -1
- package/dist/feature-libraries/modular-schema/crossFieldQueries.d.ts +100 -24
- package/dist/feature-libraries/modular-schema/crossFieldQueries.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/crossFieldQueries.js +8 -12
- package/dist/feature-libraries/modular-schema/crossFieldQueries.js.map +1 -1
- package/dist/feature-libraries/modular-schema/fieldChangeHandler.d.ts +85 -51
- 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 +4 -9
- package/dist/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
- package/dist/feature-libraries/modular-schema/index.d.ts +3 -3
- package/dist/feature-libraries/modular-schema/index.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/index.js +2 -3
- package/dist/feature-libraries/modular-schema/index.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecV1.d.ts +18 -22
- package/dist/feature-libraries/modular-schema/modularChangeCodecV1.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecV1.js +276 -158
- package/dist/feature-libraries/modular-schema/modularChangeCodecV1.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecV2.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecV2.js +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecV2.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecV3.d.ts +15 -0
- package/dist/feature-libraries/modular-schema/modularChangeCodecV3.d.ts.map +1 -0
- package/dist/feature-libraries/modular-schema/modularChangeCodecV3.js +296 -0
- package/dist/feature-libraries/modular-schema/modularChangeCodecV3.js.map +1 -0
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.d.ts +1 -0
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.js +8 -0
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts +56 -22
- package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.js +1390 -462
- package/dist/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFormatV1.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFormatV1.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFormatV2.d.ts +1 -2
- package/dist/feature-libraries/modular-schema/modularChangeFormatV2.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFormatV2.js +3 -3
- package/dist/feature-libraries/modular-schema/modularChangeFormatV2.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFormatV3.d.ts +74 -0
- package/dist/feature-libraries/modular-schema/modularChangeFormatV3.d.ts.map +1 -0
- package/dist/feature-libraries/modular-schema/modularChangeFormatV3.js +35 -0
- package/dist/feature-libraries/modular-schema/modularChangeFormatV3.js.map +1 -0
- package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts +49 -10
- package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeTypes.js +3 -3
- package/dist/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
- package/dist/feature-libraries/optional-field/optionalField.d.ts +13 -32
- package/dist/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
- package/dist/feature-libraries/optional-field/optionalField.js +257 -446
- package/dist/feature-libraries/optional-field/optionalField.js.map +1 -1
- package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV3.d.ts +23 -0
- package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV3.d.ts.map +1 -0
- package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV3.js +31 -0
- package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV3.js.map +1 -0
- package/dist/feature-libraries/optional-field/optionalFieldChangeTypes.d.ts +31 -31
- package/dist/feature-libraries/optional-field/optionalFieldChangeTypes.d.ts.map +1 -1
- package/dist/feature-libraries/optional-field/optionalFieldChangeTypes.js.map +1 -1
- package/dist/feature-libraries/optional-field/optionalFieldCodecV2.d.ts +1 -1
- package/dist/feature-libraries/optional-field/optionalFieldCodecV2.d.ts.map +1 -1
- package/dist/feature-libraries/optional-field/optionalFieldCodecV2.js +57 -28
- package/dist/feature-libraries/optional-field/optionalFieldCodecV2.js.map +1 -1
- package/dist/feature-libraries/optional-field/optionalFieldCodecV3.d.ts +12 -0
- package/dist/feature-libraries/optional-field/optionalFieldCodecV3.d.ts.map +1 -0
- package/dist/feature-libraries/optional-field/optionalFieldCodecV3.js +57 -0
- package/dist/feature-libraries/optional-field/optionalFieldCodecV3.js.map +1 -0
- package/dist/feature-libraries/optional-field/optionalFieldCodecs.d.ts.map +1 -1
- package/dist/feature-libraries/optional-field/optionalFieldCodecs.js +5 -1
- package/dist/feature-libraries/optional-field/optionalFieldCodecs.js.map +1 -1
- package/dist/feature-libraries/optional-field/requiredField.d.ts +3 -2
- package/dist/feature-libraries/optional-field/requiredField.d.ts.map +1 -1
- package/dist/feature-libraries/optional-field/requiredField.js +6 -1
- package/dist/feature-libraries/optional-field/requiredField.js.map +1 -1
- package/dist/feature-libraries/sequence-field/compose.d.ts +6 -7
- package/dist/feature-libraries/sequence-field/compose.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/compose.js +81 -259
- package/dist/feature-libraries/sequence-field/compose.js.map +1 -1
- package/dist/feature-libraries/sequence-field/helperTypes.d.ts +14 -10
- package/dist/feature-libraries/sequence-field/helperTypes.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/helperTypes.js.map +1 -1
- package/dist/feature-libraries/sequence-field/invert.d.ts +3 -3
- package/dist/feature-libraries/sequence-field/invert.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/invert.js +65 -167
- package/dist/feature-libraries/sequence-field/invert.js.map +1 -1
- package/dist/feature-libraries/sequence-field/markQueue.d.ts +2 -2
- package/dist/feature-libraries/sequence-field/markQueue.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/markQueue.js.map +1 -1
- package/dist/feature-libraries/sequence-field/moveEffectTable.d.ts +4 -56
- package/dist/feature-libraries/sequence-field/moveEffectTable.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/moveEffectTable.js +7 -90
- package/dist/feature-libraries/sequence-field/moveEffectTable.js.map +1 -1
- package/dist/feature-libraries/sequence-field/rebase.d.ts +3 -3
- package/dist/feature-libraries/sequence-field/rebase.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/rebase.js +109 -116
- package/dist/feature-libraries/sequence-field/rebase.js.map +1 -1
- package/dist/feature-libraries/sequence-field/replaceRevisions.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/replaceRevisions.js +19 -32
- package/dist/feature-libraries/sequence-field/replaceRevisions.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 -2
- package/dist/feature-libraries/sequence-field/sequenceFieldChangeHandler.js.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV2.d.ts +22 -4
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV2.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV2.js +388 -187
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV2.js.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV3.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV3.js +20 -62
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV3.js.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldEditor.d.ts +2 -2
- package/dist/feature-libraries/sequence-field/sequenceFieldEditor.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldEditor.js +13 -13
- package/dist/feature-libraries/sequence-field/sequenceFieldEditor.js.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts +3 -2
- package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.js +16 -111
- package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.js.map +1 -1
- package/dist/feature-libraries/sequence-field/types.d.ts +37 -74
- package/dist/feature-libraries/sequence-field/types.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/types.js.map +1 -1
- package/dist/feature-libraries/sequence-field/utils.d.ts +20 -25
- package/dist/feature-libraries/sequence-field/utils.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/utils.js +159 -320
- package/dist/feature-libraries/sequence-field/utils.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/shared-tree/independentView.d.ts.map +1 -1
- package/dist/shared-tree/independentView.js +1 -1
- package/dist/shared-tree/independentView.js.map +1 -1
- package/dist/shared-tree/index.d.ts +1 -1
- package/dist/shared-tree/index.d.ts.map +1 -1
- package/dist/shared-tree/index.js.map +1 -1
- package/dist/shared-tree/schematizeTree.d.ts +4 -4
- package/dist/shared-tree/schematizeTree.d.ts.map +1 -1
- package/dist/shared-tree/schematizeTree.js +2 -1
- package/dist/shared-tree/schematizeTree.js.map +1 -1
- package/dist/shared-tree/schematizingTreeView.d.ts +1 -5
- package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/dist/shared-tree/schematizingTreeView.js +21 -35
- package/dist/shared-tree/schematizingTreeView.js.map +1 -1
- package/dist/shared-tree/sharedTree.d.ts +9 -3
- package/dist/shared-tree/sharedTree.d.ts.map +1 -1
- package/dist/shared-tree/sharedTree.js +4 -1
- package/dist/shared-tree/sharedTree.js.map +1 -1
- package/dist/shared-tree/sharedTreeChangeCodecs.d.ts +1 -0
- package/dist/shared-tree/sharedTreeChangeCodecs.d.ts.map +1 -1
- package/dist/shared-tree/sharedTreeChangeCodecs.js +8 -0
- package/dist/shared-tree/sharedTreeChangeCodecs.js.map +1 -1
- package/dist/shared-tree/sharedTreeChangeFamily.d.ts +4 -4
- package/dist/shared-tree/sharedTreeChangeFamily.d.ts.map +1 -1
- package/dist/shared-tree/sharedTreeChangeFamily.js +2 -2
- package/dist/shared-tree/sharedTreeChangeFamily.js.map +1 -1
- package/dist/shared-tree/sharedTreeEditBuilder.d.ts +16 -6
- package/dist/shared-tree/sharedTreeEditBuilder.d.ts.map +1 -1
- package/dist/shared-tree/sharedTreeEditBuilder.js +14 -7
- package/dist/shared-tree/sharedTreeEditBuilder.js.map +1 -1
- package/dist/shared-tree/treeCheckout.d.ts +13 -11
- package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
- package/dist/shared-tree/treeCheckout.js +56 -6
- package/dist/shared-tree/treeCheckout.js.map +1 -1
- package/dist/shared-tree-core/branch.d.ts +3 -2
- package/dist/shared-tree-core/branch.d.ts.map +1 -1
- package/dist/shared-tree-core/branch.js +4 -3
- package/dist/shared-tree-core/branch.js.map +1 -1
- package/dist/shared-tree-core/editManager.d.ts +2 -2
- package/dist/shared-tree-core/editManager.d.ts.map +1 -1
- package/dist/shared-tree-core/editManager.js +9 -9
- package/dist/shared-tree-core/editManager.js.map +1 -1
- package/dist/shared-tree-core/editManagerCodecs.d.ts +4 -0
- package/dist/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerCodecs.js +10 -2
- package/dist/shared-tree-core/editManagerCodecs.js.map +1 -1
- package/dist/shared-tree-core/editManagerFormatCommons.d.ts +1 -0
- package/dist/shared-tree-core/editManagerFormatCommons.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerFormatCommons.js +6 -0
- package/dist/shared-tree-core/editManagerFormatCommons.js.map +1 -1
- package/dist/shared-tree-core/editManagerFormatV1toV4.d.ts +2 -2
- package/dist/shared-tree-core/editManagerFormatV1toV4.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerFormatV1toV4.js +1 -0
- package/dist/shared-tree-core/editManagerFormatV1toV4.js.map +1 -1
- package/dist/shared-tree-core/index.d.ts +2 -2
- package/dist/shared-tree-core/index.d.ts.map +1 -1
- package/dist/shared-tree-core/index.js +3 -1
- package/dist/shared-tree-core/index.js.map +1 -1
- package/dist/shared-tree-core/messageCodecV1ToV4.d.ts +1 -1
- package/dist/shared-tree-core/messageCodecV1ToV4.d.ts.map +1 -1
- package/dist/shared-tree-core/messageCodecV1ToV4.js.map +1 -1
- package/dist/shared-tree-core/messageCodecs.d.ts +4 -0
- package/dist/shared-tree-core/messageCodecs.d.ts.map +1 -1
- package/dist/shared-tree-core/messageCodecs.js +10 -2
- package/dist/shared-tree-core/messageCodecs.js.map +1 -1
- package/dist/shared-tree-core/messageFormat.d.ts +1 -0
- package/dist/shared-tree-core/messageFormat.d.ts.map +1 -1
- package/dist/shared-tree-core/messageFormat.js +6 -0
- package/dist/shared-tree-core/messageFormat.js.map +1 -1
- package/dist/shared-tree-core/messageFormatV1ToV4.d.ts +2 -2
- package/dist/shared-tree-core/messageFormatV1ToV4.d.ts.map +1 -1
- package/dist/shared-tree-core/messageFormatV1ToV4.js +1 -0
- package/dist/shared-tree-core/messageFormatV1ToV4.js.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.d.ts +1 -0
- package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.js +1 -1
- package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/dist/simple-tree/core/unhydratedFlexTree.d.ts +16 -12
- package/dist/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
- package/dist/simple-tree/core/unhydratedFlexTree.js +59 -8
- package/dist/simple-tree/core/unhydratedFlexTree.js.map +1 -1
- package/dist/simple-tree/fieldSchema.d.ts +4 -4
- package/dist/simple-tree/fieldSchema.d.ts.map +1 -1
- package/dist/simple-tree/fieldSchema.js.map +1 -1
- package/dist/simple-tree/index.d.ts +2 -2
- package/dist/simple-tree/index.d.ts.map +1 -1
- package/dist/simple-tree/index.js +1 -1
- package/dist/simple-tree/index.js.map +1 -1
- package/dist/simple-tree/node-kinds/array/arrayNode.d.ts.map +1 -1
- package/dist/simple-tree/node-kinds/array/arrayNode.js +5 -3
- package/dist/simple-tree/node-kinds/array/arrayNode.js.map +1 -1
- package/dist/simple-tree/node-kinds/common.d.ts.map +1 -1
- package/dist/simple-tree/node-kinds/common.js +1 -1
- package/dist/simple-tree/node-kinds/common.js.map +1 -1
- package/dist/simple-tree/node-kinds/map/mapNode.js +2 -2
- package/dist/simple-tree/node-kinds/map/mapNode.js.map +1 -1
- package/dist/simple-tree/node-kinds/object/objectNode.d.ts.map +1 -1
- package/dist/simple-tree/node-kinds/object/objectNode.js +19 -19
- package/dist/simple-tree/node-kinds/object/objectNode.js.map +1 -1
- package/dist/simple-tree/node-kinds/record/recordNode.d.ts.map +1 -1
- package/dist/simple-tree/node-kinds/record/recordNode.js +4 -2
- package/dist/simple-tree/node-kinds/record/recordNode.js.map +1 -1
- package/dist/simple-tree/prepareForInsertion.d.ts +54 -47
- package/dist/simple-tree/prepareForInsertion.d.ts.map +1 -1
- package/dist/simple-tree/prepareForInsertion.js +183 -125
- package/dist/simple-tree/prepareForInsertion.js.map +1 -1
- package/dist/simple-tree/unhydratedFlexTreeFromInsertable.d.ts +8 -3
- package/dist/simple-tree/unhydratedFlexTreeFromInsertable.d.ts.map +1 -1
- package/dist/simple-tree/unhydratedFlexTreeFromInsertable.js +27 -13
- package/dist/simple-tree/unhydratedFlexTreeFromInsertable.js.map +1 -1
- package/dist/treeFactory.d.ts.map +1 -1
- package/dist/treeFactory.js +12 -2
- package/dist/treeFactory.js.map +1 -1
- package/dist/util/index.d.ts +1 -1
- package/dist/util/index.d.ts.map +1 -1
- package/dist/util/index.js +2 -1
- package/dist/util/index.js.map +1 -1
- package/dist/util/rangeMap.d.ts +23 -11
- package/dist/util/rangeMap.d.ts.map +1 -1
- package/dist/util/rangeMap.js +43 -10
- package/dist/util/rangeMap.js.map +1 -1
- package/lib/core/change-family/changeFamily.d.ts +4 -1
- package/lib/core/change-family/changeFamily.d.ts.map +1 -1
- package/lib/core/change-family/changeFamily.js.map +1 -1
- package/lib/core/change-family/index.d.ts +1 -1
- package/lib/core/change-family/index.d.ts.map +1 -1
- package/lib/core/change-family/index.js.map +1 -1
- package/lib/core/index.d.ts +3 -3
- package/lib/core/index.d.ts.map +1 -1
- package/lib/core/index.js +2 -2
- package/lib/core/index.js.map +1 -1
- package/lib/core/rebase/changeRebaser.d.ts +6 -1
- package/lib/core/rebase/changeRebaser.d.ts.map +1 -1
- package/lib/core/rebase/changeRebaser.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 +1 -0
- package/lib/core/rebase/types.d.ts.map +1 -1
- package/lib/core/rebase/types.js +3 -0
- package/lib/core/rebase/types.js.map +1 -1
- package/lib/core/rebase/utils.d.ts.map +1 -1
- package/lib/core/rebase/utils.js +25 -7
- package/lib/core/rebase/utils.js.map +1 -1
- package/lib/core/tree/delta.d.ts +5 -0
- package/lib/core/tree/delta.d.ts.map +1 -1
- package/lib/core/tree/delta.js.map +1 -1
- package/lib/core/tree/detachedFieldIndex.d.ts +13 -1
- package/lib/core/tree/detachedFieldIndex.d.ts.map +1 -1
- package/lib/core/tree/detachedFieldIndex.js +15 -2
- package/lib/core/tree/detachedFieldIndex.js.map +1 -1
- package/lib/core/tree/detachedFieldIndexTypes.d.ts +4 -0
- package/lib/core/tree/detachedFieldIndexTypes.d.ts.map +1 -1
- package/lib/core/tree/detachedFieldIndexTypes.js.map +1 -1
- package/lib/core/tree/index.d.ts +2 -2
- package/lib/core/tree/index.d.ts.map +1 -1
- package/lib/core/tree/index.js +1 -1
- package/lib/core/tree/index.js.map +1 -1
- package/lib/core/tree/pathTree.d.ts +11 -3
- package/lib/core/tree/pathTree.d.ts.map +1 -1
- package/lib/core/tree/pathTree.js +12 -1
- package/lib/core/tree/pathTree.js.map +1 -1
- package/lib/core/tree/visitDelta.d.ts.map +1 -1
- package/lib/core/tree/visitDelta.js +17 -13
- package/lib/core/tree/visitDelta.js.map +1 -1
- package/lib/feature-libraries/changeAtomIdBTree.d.ts +3 -2
- package/lib/feature-libraries/changeAtomIdBTree.d.ts.map +1 -1
- package/lib/feature-libraries/changeAtomIdBTree.js +15 -3
- package/lib/feature-libraries/changeAtomIdBTree.js.map +1 -1
- package/lib/feature-libraries/default-schema/defaultEditBuilder.d.ts +92 -44
- package/lib/feature-libraries/default-schema/defaultEditBuilder.d.ts.map +1 -1
- package/lib/feature-libraries/default-schema/defaultEditBuilder.js +217 -69
- 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 +12 -2
- package/lib/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
- package/lib/feature-libraries/default-schema/index.d.ts +2 -1
- package/lib/feature-libraries/default-schema/index.d.ts.map +1 -1
- package/lib/feature-libraries/default-schema/index.js +2 -1
- package/lib/feature-libraries/default-schema/index.js.map +1 -1
- package/lib/feature-libraries/default-schema/locationBasedEditBuilder.d.ts +40 -0
- package/lib/feature-libraries/default-schema/locationBasedEditBuilder.d.ts.map +1 -0
- package/lib/feature-libraries/default-schema/locationBasedEditBuilder.js +149 -0
- package/lib/feature-libraries/default-schema/locationBasedEditBuilder.js.map +1 -0
- package/lib/feature-libraries/default-schema/mappedEditBuilder.d.ts +7 -6
- package/lib/feature-libraries/default-schema/mappedEditBuilder.d.ts.map +1 -1
- package/lib/feature-libraries/default-schema/mappedEditBuilder.js +15 -0
- package/lib/feature-libraries/default-schema/mappedEditBuilder.js.map +1 -1
- package/lib/feature-libraries/deltaUtils.d.ts +1 -0
- package/lib/feature-libraries/deltaUtils.d.ts.map +1 -1
- package/lib/feature-libraries/deltaUtils.js +5 -1
- package/lib/feature-libraries/deltaUtils.js.map +1 -1
- package/lib/feature-libraries/flex-tree/context.d.ts +9 -0
- package/lib/feature-libraries/flex-tree/context.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/context.js +6 -0
- package/lib/feature-libraries/flex-tree/context.js.map +1 -1
- package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts +6 -6
- 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/lazyField.d.ts +8 -7
- package/lib/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.js +40 -9
- package/lib/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/lib/feature-libraries/index.d.ts +3 -3
- package/lib/feature-libraries/index.d.ts.map +1 -1
- package/lib/feature-libraries/index.js +3 -3
- package/lib/feature-libraries/index.js.map +1 -1
- package/lib/feature-libraries/mitigatedChangeFamily.d.ts.map +1 -1
- package/lib/feature-libraries/mitigatedChangeFamily.js +2 -2
- package/lib/feature-libraries/mitigatedChangeFamily.js.map +1 -1
- package/lib/feature-libraries/modular-schema/crossFieldQueries.d.ts +100 -24
- package/lib/feature-libraries/modular-schema/crossFieldQueries.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/crossFieldQueries.js +7 -10
- package/lib/feature-libraries/modular-schema/crossFieldQueries.js.map +1 -1
- package/lib/feature-libraries/modular-schema/fieldChangeHandler.d.ts +85 -51
- 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 +4 -9
- package/lib/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
- package/lib/feature-libraries/modular-schema/index.d.ts +3 -3
- package/lib/feature-libraries/modular-schema/index.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/index.js +1 -1
- package/lib/feature-libraries/modular-schema/index.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecV1.d.ts +18 -22
- package/lib/feature-libraries/modular-schema/modularChangeCodecV1.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecV1.js +267 -144
- package/lib/feature-libraries/modular-schema/modularChangeCodecV1.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecV2.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecV2.js +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecV2.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecV3.d.ts +15 -0
- package/lib/feature-libraries/modular-schema/modularChangeCodecV3.d.ts.map +1 -0
- package/lib/feature-libraries/modular-schema/modularChangeCodecV3.js +292 -0
- package/lib/feature-libraries/modular-schema/modularChangeCodecV3.js.map +1 -0
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.d.ts +1 -0
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.js +8 -0
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts +56 -22
- package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFamily.js +1387 -468
- package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFormatV1.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFormatV1.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFormatV2.d.ts +1 -2
- package/lib/feature-libraries/modular-schema/modularChangeFormatV2.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFormatV2.js +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFormatV2.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFormatV3.d.ts +74 -0
- package/lib/feature-libraries/modular-schema/modularChangeFormatV3.d.ts.map +1 -0
- package/lib/feature-libraries/modular-schema/modularChangeFormatV3.js +32 -0
- package/lib/feature-libraries/modular-schema/modularChangeFormatV3.js.map +1 -0
- package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts +49 -10
- package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeTypes.js +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
- package/lib/feature-libraries/optional-field/optionalField.d.ts +13 -32
- package/lib/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
- package/lib/feature-libraries/optional-field/optionalField.js +254 -442
- package/lib/feature-libraries/optional-field/optionalField.js.map +1 -1
- package/lib/feature-libraries/optional-field/optionalFieldChangeFormatV3.d.ts +23 -0
- package/lib/feature-libraries/optional-field/optionalFieldChangeFormatV3.d.ts.map +1 -0
- package/lib/feature-libraries/optional-field/optionalFieldChangeFormatV3.js +27 -0
- package/lib/feature-libraries/optional-field/optionalFieldChangeFormatV3.js.map +1 -0
- package/lib/feature-libraries/optional-field/optionalFieldChangeTypes.d.ts +31 -31
- package/lib/feature-libraries/optional-field/optionalFieldChangeTypes.d.ts.map +1 -1
- package/lib/feature-libraries/optional-field/optionalFieldChangeTypes.js.map +1 -1
- package/lib/feature-libraries/optional-field/optionalFieldCodecV2.d.ts +1 -1
- package/lib/feature-libraries/optional-field/optionalFieldCodecV2.d.ts.map +1 -1
- package/lib/feature-libraries/optional-field/optionalFieldCodecV2.js +55 -26
- package/lib/feature-libraries/optional-field/optionalFieldCodecV2.js.map +1 -1
- package/lib/feature-libraries/optional-field/optionalFieldCodecV3.d.ts +12 -0
- package/lib/feature-libraries/optional-field/optionalFieldCodecV3.d.ts.map +1 -0
- package/lib/feature-libraries/optional-field/optionalFieldCodecV3.js +53 -0
- package/lib/feature-libraries/optional-field/optionalFieldCodecV3.js.map +1 -0
- package/lib/feature-libraries/optional-field/optionalFieldCodecs.d.ts.map +1 -1
- package/lib/feature-libraries/optional-field/optionalFieldCodecs.js +5 -1
- package/lib/feature-libraries/optional-field/optionalFieldCodecs.js.map +1 -1
- package/lib/feature-libraries/optional-field/requiredField.d.ts +3 -2
- package/lib/feature-libraries/optional-field/requiredField.d.ts.map +1 -1
- package/lib/feature-libraries/optional-field/requiredField.js +5 -1
- package/lib/feature-libraries/optional-field/requiredField.js.map +1 -1
- package/lib/feature-libraries/sequence-field/compose.d.ts +6 -7
- package/lib/feature-libraries/sequence-field/compose.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/compose.js +83 -261
- package/lib/feature-libraries/sequence-field/compose.js.map +1 -1
- package/lib/feature-libraries/sequence-field/helperTypes.d.ts +14 -10
- package/lib/feature-libraries/sequence-field/helperTypes.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/helperTypes.js.map +1 -1
- package/lib/feature-libraries/sequence-field/invert.d.ts +3 -3
- package/lib/feature-libraries/sequence-field/invert.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/invert.js +67 -169
- package/lib/feature-libraries/sequence-field/invert.js.map +1 -1
- package/lib/feature-libraries/sequence-field/markQueue.d.ts +2 -2
- package/lib/feature-libraries/sequence-field/markQueue.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/markQueue.js.map +1 -1
- package/lib/feature-libraries/sequence-field/moveEffectTable.d.ts +4 -56
- package/lib/feature-libraries/sequence-field/moveEffectTable.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/moveEffectTable.js +6 -84
- package/lib/feature-libraries/sequence-field/moveEffectTable.js.map +1 -1
- package/lib/feature-libraries/sequence-field/rebase.d.ts +3 -3
- package/lib/feature-libraries/sequence-field/rebase.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/rebase.js +111 -118
- package/lib/feature-libraries/sequence-field/rebase.js.map +1 -1
- package/lib/feature-libraries/sequence-field/replaceRevisions.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/replaceRevisions.js +19 -32
- package/lib/feature-libraries/sequence-field/replaceRevisions.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 -3
- package/lib/feature-libraries/sequence-field/sequenceFieldChangeHandler.js.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV2.d.ts +22 -4
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV2.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV2.js +379 -182
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV2.js.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV3.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV3.js +21 -63
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV3.js.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldEditor.d.ts +2 -2
- package/lib/feature-libraries/sequence-field/sequenceFieldEditor.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldEditor.js +13 -13
- package/lib/feature-libraries/sequence-field/sequenceFieldEditor.js.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts +3 -2
- package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.js +16 -111
- package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.js.map +1 -1
- package/lib/feature-libraries/sequence-field/types.d.ts +37 -74
- package/lib/feature-libraries/sequence-field/types.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/types.js.map +1 -1
- package/lib/feature-libraries/sequence-field/utils.d.ts +20 -25
- package/lib/feature-libraries/sequence-field/utils.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/utils.js +155 -313
- package/lib/feature-libraries/sequence-field/utils.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/shared-tree/independentView.d.ts.map +1 -1
- package/lib/shared-tree/independentView.js +1 -1
- package/lib/shared-tree/independentView.js.map +1 -1
- package/lib/shared-tree/index.d.ts +1 -1
- package/lib/shared-tree/index.d.ts.map +1 -1
- package/lib/shared-tree/index.js.map +1 -1
- package/lib/shared-tree/schematizeTree.d.ts +4 -4
- package/lib/shared-tree/schematizeTree.d.ts.map +1 -1
- package/lib/shared-tree/schematizeTree.js +3 -2
- package/lib/shared-tree/schematizeTree.js.map +1 -1
- package/lib/shared-tree/schematizingTreeView.d.ts +1 -5
- package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/lib/shared-tree/schematizingTreeView.js +24 -38
- package/lib/shared-tree/schematizingTreeView.js.map +1 -1
- package/lib/shared-tree/sharedTree.d.ts +9 -3
- package/lib/shared-tree/sharedTree.d.ts.map +1 -1
- package/lib/shared-tree/sharedTree.js +4 -1
- package/lib/shared-tree/sharedTree.js.map +1 -1
- package/lib/shared-tree/sharedTreeChangeCodecs.d.ts +1 -0
- package/lib/shared-tree/sharedTreeChangeCodecs.d.ts.map +1 -1
- package/lib/shared-tree/sharedTreeChangeCodecs.js +8 -0
- package/lib/shared-tree/sharedTreeChangeCodecs.js.map +1 -1
- package/lib/shared-tree/sharedTreeChangeFamily.d.ts +4 -4
- package/lib/shared-tree/sharedTreeChangeFamily.d.ts.map +1 -1
- package/lib/shared-tree/sharedTreeChangeFamily.js +3 -3
- package/lib/shared-tree/sharedTreeChangeFamily.js.map +1 -1
- package/lib/shared-tree/sharedTreeEditBuilder.d.ts +16 -6
- package/lib/shared-tree/sharedTreeEditBuilder.d.ts.map +1 -1
- package/lib/shared-tree/sharedTreeEditBuilder.js +12 -6
- package/lib/shared-tree/sharedTreeEditBuilder.js.map +1 -1
- package/lib/shared-tree/treeCheckout.d.ts +13 -11
- package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
- package/lib/shared-tree/treeCheckout.js +59 -9
- package/lib/shared-tree/treeCheckout.js.map +1 -1
- package/lib/shared-tree-core/branch.d.ts +3 -2
- package/lib/shared-tree-core/branch.d.ts.map +1 -1
- package/lib/shared-tree-core/branch.js +4 -3
- package/lib/shared-tree-core/branch.js.map +1 -1
- package/lib/shared-tree-core/editManager.d.ts +2 -2
- package/lib/shared-tree-core/editManager.d.ts.map +1 -1
- package/lib/shared-tree-core/editManager.js +9 -9
- package/lib/shared-tree-core/editManager.js.map +1 -1
- package/lib/shared-tree-core/editManagerCodecs.d.ts +4 -0
- package/lib/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerCodecs.js +8 -1
- package/lib/shared-tree-core/editManagerCodecs.js.map +1 -1
- package/lib/shared-tree-core/editManagerFormatCommons.d.ts +1 -0
- package/lib/shared-tree-core/editManagerFormatCommons.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerFormatCommons.js +6 -0
- package/lib/shared-tree-core/editManagerFormatCommons.js.map +1 -1
- package/lib/shared-tree-core/editManagerFormatV1toV4.d.ts +2 -2
- package/lib/shared-tree-core/editManagerFormatV1toV4.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerFormatV1toV4.js +1 -0
- package/lib/shared-tree-core/editManagerFormatV1toV4.js.map +1 -1
- package/lib/shared-tree-core/index.d.ts +2 -2
- package/lib/shared-tree-core/index.d.ts.map +1 -1
- package/lib/shared-tree-core/index.js +2 -2
- package/lib/shared-tree-core/index.js.map +1 -1
- package/lib/shared-tree-core/messageCodecV1ToV4.d.ts +1 -1
- package/lib/shared-tree-core/messageCodecV1ToV4.d.ts.map +1 -1
- package/lib/shared-tree-core/messageCodecV1ToV4.js.map +1 -1
- package/lib/shared-tree-core/messageCodecs.d.ts +4 -0
- package/lib/shared-tree-core/messageCodecs.d.ts.map +1 -1
- package/lib/shared-tree-core/messageCodecs.js +8 -1
- package/lib/shared-tree-core/messageCodecs.js.map +1 -1
- package/lib/shared-tree-core/messageFormat.d.ts +1 -0
- package/lib/shared-tree-core/messageFormat.d.ts.map +1 -1
- package/lib/shared-tree-core/messageFormat.js +6 -0
- package/lib/shared-tree-core/messageFormat.js.map +1 -1
- package/lib/shared-tree-core/messageFormatV1ToV4.d.ts +2 -2
- package/lib/shared-tree-core/messageFormatV1ToV4.d.ts.map +1 -1
- package/lib/shared-tree-core/messageFormatV1ToV4.js +1 -0
- package/lib/shared-tree-core/messageFormatV1ToV4.js.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.d.ts +1 -0
- package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.js +1 -1
- package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/lib/simple-tree/core/unhydratedFlexTree.d.ts +16 -12
- package/lib/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
- package/lib/simple-tree/core/unhydratedFlexTree.js +58 -8
- package/lib/simple-tree/core/unhydratedFlexTree.js.map +1 -1
- package/lib/simple-tree/fieldSchema.d.ts +4 -4
- package/lib/simple-tree/fieldSchema.d.ts.map +1 -1
- package/lib/simple-tree/fieldSchema.js.map +1 -1
- package/lib/simple-tree/index.d.ts +2 -2
- package/lib/simple-tree/index.d.ts.map +1 -1
- package/lib/simple-tree/index.js +1 -1
- package/lib/simple-tree/index.js.map +1 -1
- package/lib/simple-tree/node-kinds/array/arrayNode.d.ts.map +1 -1
- package/lib/simple-tree/node-kinds/array/arrayNode.js +6 -4
- package/lib/simple-tree/node-kinds/array/arrayNode.js.map +1 -1
- package/lib/simple-tree/node-kinds/common.d.ts.map +1 -1
- package/lib/simple-tree/node-kinds/common.js +2 -2
- package/lib/simple-tree/node-kinds/common.js.map +1 -1
- package/lib/simple-tree/node-kinds/map/mapNode.js +2 -2
- package/lib/simple-tree/node-kinds/map/mapNode.js.map +1 -1
- package/lib/simple-tree/node-kinds/object/objectNode.d.ts.map +1 -1
- package/lib/simple-tree/node-kinds/object/objectNode.js +20 -20
- package/lib/simple-tree/node-kinds/object/objectNode.js.map +1 -1
- package/lib/simple-tree/node-kinds/record/recordNode.d.ts.map +1 -1
- package/lib/simple-tree/node-kinds/record/recordNode.js +4 -2
- package/lib/simple-tree/node-kinds/record/recordNode.js.map +1 -1
- package/lib/simple-tree/prepareForInsertion.d.ts +54 -47
- package/lib/simple-tree/prepareForInsertion.d.ts.map +1 -1
- package/lib/simple-tree/prepareForInsertion.js +184 -125
- package/lib/simple-tree/prepareForInsertion.js.map +1 -1
- package/lib/simple-tree/unhydratedFlexTreeFromInsertable.d.ts +8 -3
- package/lib/simple-tree/unhydratedFlexTreeFromInsertable.d.ts.map +1 -1
- package/lib/simple-tree/unhydratedFlexTreeFromInsertable.js +23 -10
- package/lib/simple-tree/unhydratedFlexTreeFromInsertable.js.map +1 -1
- package/lib/treeFactory.d.ts.map +1 -1
- package/lib/treeFactory.js +13 -3
- package/lib/treeFactory.js.map +1 -1
- package/lib/util/index.d.ts +1 -1
- package/lib/util/index.d.ts.map +1 -1
- package/lib/util/index.js +1 -1
- package/lib/util/index.js.map +1 -1
- package/lib/util/rangeMap.d.ts +23 -11
- package/lib/util/rangeMap.d.ts.map +1 -1
- package/lib/util/rangeMap.js +41 -9
- package/lib/util/rangeMap.js.map +1 -1
- package/package.json +21 -21
- package/src/core/change-family/changeFamily.ts +5 -0
- package/src/core/change-family/index.ts +1 -0
- package/src/core/index.ts +4 -1
- package/src/core/rebase/changeRebaser.ts +6 -1
- package/src/core/rebase/index.ts +1 -0
- package/src/core/rebase/types.ts +4 -0
- package/src/core/rebase/utils.ts +31 -7
- package/src/core/tree/delta.ts +6 -0
- package/src/core/tree/detachedFieldIndex.ts +29 -1
- package/src/core/tree/detachedFieldIndexTypes.ts +5 -0
- package/src/core/tree/index.ts +13 -12
- package/src/core/tree/pathTree.ts +16 -4
- package/src/core/tree/visitDelta.ts +31 -11
- package/src/feature-libraries/changeAtomIdBTree.ts +28 -3
- package/src/feature-libraries/default-schema/defaultEditBuilder.ts +369 -127
- package/src/feature-libraries/default-schema/defaultFieldKinds.ts +13 -4
- package/src/feature-libraries/default-schema/index.ts +16 -5
- package/src/feature-libraries/default-schema/locationBasedEditBuilder.ts +231 -0
- package/src/feature-libraries/default-schema/mappedEditBuilder.ts +35 -9
- package/src/feature-libraries/deltaUtils.ts +6 -1
- package/src/feature-libraries/flex-tree/context.ts +17 -0
- package/src/feature-libraries/flex-tree/flexTreeTypes.ts +7 -8
- package/src/feature-libraries/flex-tree/lazyField.ts +65 -24
- package/src/feature-libraries/index.ts +22 -9
- package/src/feature-libraries/mitigatedChangeFamily.ts +3 -1
- package/src/feature-libraries/modular-schema/crossFieldQueries.ts +144 -47
- package/src/feature-libraries/modular-schema/fieldChangeHandler.ts +113 -58
- package/src/feature-libraries/modular-schema/genericFieldKind.ts +7 -18
- package/src/feature-libraries/modular-schema/index.ts +16 -16
- package/src/feature-libraries/modular-schema/modularChangeCodecV1.ts +623 -348
- package/src/feature-libraries/modular-schema/modularChangeCodecV2.ts +1 -0
- package/src/feature-libraries/modular-schema/modularChangeCodecV3.ts +649 -0
- package/src/feature-libraries/modular-schema/modularChangeCodecs.ts +14 -0
- package/src/feature-libraries/modular-schema/modularChangeFamily.ts +2694 -748
- package/src/feature-libraries/modular-schema/modularChangeFormatV1.ts +1 -0
- package/src/feature-libraries/modular-schema/modularChangeFormatV2.ts +1 -1
- package/src/feature-libraries/modular-schema/modularChangeFormatV3.ts +67 -0
- package/src/feature-libraries/modular-schema/modularChangeTypes.ts +62 -10
- package/src/feature-libraries/optional-field/optionalField.ts +359 -568
- package/src/feature-libraries/optional-field/optionalFieldChangeFormatV3.ts +45 -0
- package/src/feature-libraries/optional-field/optionalFieldChangeTypes.ts +31 -35
- package/src/feature-libraries/optional-field/optionalFieldCodecV2.ts +89 -35
- package/src/feature-libraries/optional-field/optionalFieldCodecV3.ts +94 -0
- package/src/feature-libraries/optional-field/optionalFieldCodecs.ts +5 -1
- package/src/feature-libraries/optional-field/requiredField.ts +15 -2
- package/src/feature-libraries/sequence-field/compose.ts +137 -522
- package/src/feature-libraries/sequence-field/helperTypes.ts +34 -19
- package/src/feature-libraries/sequence-field/invert.ts +102 -228
- package/src/feature-libraries/sequence-field/markQueue.ts +2 -2
- package/src/feature-libraries/sequence-field/moveEffectTable.ts +8 -195
- package/src/feature-libraries/sequence-field/rebase.ts +171 -207
- package/src/feature-libraries/sequence-field/replaceRevisions.ts +26 -52
- package/src/feature-libraries/sequence-field/sequenceFieldChangeHandler.ts +8 -3
- package/src/feature-libraries/sequence-field/sequenceFieldCodecV2.ts +677 -229
- package/src/feature-libraries/sequence-field/sequenceFieldCodecV3.ts +56 -70
- package/src/feature-libraries/sequence-field/sequenceFieldEditor.ts +28 -30
- package/src/feature-libraries/sequence-field/sequenceFieldToDelta.ts +21 -131
- package/src/feature-libraries/sequence-field/types.ts +40 -79
- package/src/feature-libraries/sequence-field/utils.ts +211 -370
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/independentView.ts +12 -6
- package/src/shared-tree/index.ts +3 -2
- package/src/shared-tree/schematizeTree.ts +21 -8
- package/src/shared-tree/schematizingTreeView.ts +38 -68
- package/src/shared-tree/sharedTree.ts +30 -15
- package/src/shared-tree/sharedTreeChangeCodecs.ts +8 -0
- package/src/shared-tree/sharedTreeChangeFamily.ts +7 -4
- package/src/shared-tree/sharedTreeEditBuilder.ts +43 -8
- package/src/shared-tree/treeCheckout.ts +93 -17
- package/src/shared-tree-core/branch.ts +8 -2
- package/src/shared-tree-core/editManager.ts +16 -2
- package/src/shared-tree-core/editManagerCodecs.ts +11 -1
- package/src/shared-tree-core/editManagerFormatCommons.ts +6 -0
- package/src/shared-tree-core/editManagerFormatV1toV4.ts +3 -1
- package/src/shared-tree-core/index.ts +2 -0
- package/src/shared-tree-core/messageCodecV1ToV4.ts +2 -1
- package/src/shared-tree-core/messageCodecs.ts +11 -1
- package/src/shared-tree-core/messageFormat.ts +6 -0
- package/src/shared-tree-core/messageFormatV1ToV4.ts +3 -1
- package/src/shared-tree-core/sharedTreeCore.ts +4 -1
- package/src/simple-tree/core/unhydratedFlexTree.ts +82 -35
- package/src/simple-tree/fieldSchema.ts +6 -4
- package/src/simple-tree/index.ts +2 -1
- package/src/simple-tree/node-kinds/array/arrayNode.ts +7 -5
- package/src/simple-tree/node-kinds/common.ts +2 -5
- package/src/simple-tree/node-kinds/map/mapNode.ts +4 -4
- package/src/simple-tree/node-kinds/object/objectNode.ts +26 -26
- package/src/simple-tree/node-kinds/record/recordNode.ts +10 -9
- package/src/simple-tree/prepareForInsertion.ts +342 -200
- package/src/simple-tree/unhydratedFlexTreeFromInsertable.ts +35 -15
- package/src/treeFactory.ts +16 -4
- package/src/util/index.ts +3 -0
- package/src/util/rangeMap.ts +68 -26
- package/dist/feature-libraries/sequence-field/relevantRemovedRoots.d.ts +0 -9
- package/dist/feature-libraries/sequence-field/relevantRemovedRoots.d.ts.map +0 -1
- package/dist/feature-libraries/sequence-field/relevantRemovedRoots.js +0 -50
- package/dist/feature-libraries/sequence-field/relevantRemovedRoots.js.map +0 -1
- package/docs/main/sequence-field/move-composition.md +0 -46
- package/lib/feature-libraries/sequence-field/relevantRemovedRoots.d.ts +0 -9
- package/lib/feature-libraries/sequence-field/relevantRemovedRoots.d.ts.map +0 -1
- package/lib/feature-libraries/sequence-field/relevantRemovedRoots.js +0 -46
- package/lib/feature-libraries/sequence-field/relevantRemovedRoots.js.map +0 -1
- package/src/feature-libraries/sequence-field/relevantRemovedRoots.ts +0 -57
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.normalizeFieldId = exports.
|
|
7
|
+
exports.newFieldIdKeyBTree = exports.validateChangeset = exports.addNodeRename = exports.getFirstAttachField = exports.getFirstDetachField = exports.cloneRootTable = exports.newRootTable = exports.normalizeNodeId = exports.normalizeFieldId = exports.getNodeParent = exports.buildModularChangesetFromField = 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 internal_2 = require("@fluidframework/telemetry-utils/internal");
|
|
10
10
|
const sorted_btree_es6_1 = require("@tylerbu/sorted-btree-es6");
|
|
@@ -72,21 +72,23 @@ class ModularChangeFamily {
|
|
|
72
72
|
return convertedChange;
|
|
73
73
|
}
|
|
74
74
|
compose(changes) {
|
|
75
|
-
const {
|
|
75
|
+
const { maxId } = getRevInfoFromTaggedChanges(changes);
|
|
76
76
|
const idState = { maxId };
|
|
77
77
|
const pairwiseDelegate = (left, right) => {
|
|
78
|
-
return this.composePair(left, right,
|
|
78
|
+
return this.composePair(left, right, idState);
|
|
79
79
|
};
|
|
80
80
|
const innerChanges = changes.map((change) => change.change);
|
|
81
81
|
return (0, index_js_3.balancedReduce)(innerChanges, pairwiseDelegate, makeModularChangeset);
|
|
82
82
|
}
|
|
83
|
-
composePair(change1, change2,
|
|
84
|
-
const
|
|
83
|
+
composePair(change1, change2, idState) {
|
|
84
|
+
const revInfos = composeRevInfos(change1.revisions, change2.revisions);
|
|
85
|
+
const { fieldChanges, nodeChanges, nodeToParent, nodeAliases, crossFieldKeys, rootNodes } = this.composeAllFields(change1, change2, revInfos, idState);
|
|
85
86
|
const { allBuilds, allDestroys, allRefreshers } = composeBuildsDestroysAndRefreshers(change1, change2);
|
|
86
87
|
// The composed changeset has a "no change" constraint if either change has one
|
|
87
88
|
const noChangeConstraint = change1.noChangeConstraint ?? change2.noChangeConstraint;
|
|
88
89
|
const noChangeConstraintOnRevert = change1.noChangeConstraintOnRevert ?? change2.noChangeConstraintOnRevert;
|
|
89
|
-
|
|
90
|
+
const composed = makeModularChangeset({
|
|
91
|
+
rebaseVersion: Math.max(change1.rebaseVersion, change2.rebaseVersion),
|
|
90
92
|
fieldChanges,
|
|
91
93
|
nodeChanges,
|
|
92
94
|
nodeToParent,
|
|
@@ -94,12 +96,16 @@ class ModularChangeFamily {
|
|
|
94
96
|
crossFieldKeys,
|
|
95
97
|
maxId: idState.maxId,
|
|
96
98
|
revisions: revInfos,
|
|
97
|
-
|
|
98
|
-
noChangeConstraintOnRevert,
|
|
99
|
+
rootNodes,
|
|
99
100
|
builds: allBuilds,
|
|
100
101
|
destroys: allDestroys,
|
|
101
102
|
refreshers: allRefreshers,
|
|
103
|
+
noChangeConstraint,
|
|
104
|
+
noChangeConstraintOnRevert,
|
|
102
105
|
});
|
|
106
|
+
// XXX: This is an expensive assert which should be disabled before merging.
|
|
107
|
+
validateChangeset(composed, this.fieldKinds);
|
|
108
|
+
return composed;
|
|
103
109
|
}
|
|
104
110
|
composeAllFields(potentiallyConflictedChange1, potentiallyConflictedChange2, revInfos, idState) {
|
|
105
111
|
// Our current cell ordering scheme in sequences depends on being able to rebase over a change with conflicts.
|
|
@@ -120,34 +126,50 @@ class ModularChangeFamily {
|
|
|
120
126
|
const composedNodeChanges = (0, index_js_3.brand)((0, index_js_3.mergeTupleBTrees)(change1.nodeChanges, change2.nodeChanges));
|
|
121
127
|
const composedNodeToParent = (0, index_js_3.brand)((0, index_js_3.mergeTupleBTrees)(change1.nodeToParent, change2.nodeToParent));
|
|
122
128
|
const composedNodeAliases = (0, index_js_3.brand)((0, index_js_3.mergeTupleBTrees)(change1.nodeAliases, change2.nodeAliases));
|
|
123
|
-
const
|
|
129
|
+
const pendingCompositions = {
|
|
130
|
+
nodeIdsToCompose: [],
|
|
131
|
+
affectedBaseFields: newFieldIdKeyBTree(),
|
|
132
|
+
};
|
|
133
|
+
const movedCrossFieldKeys = (0, modularChangeTypes_js_1.newCrossFieldRangeTable)();
|
|
134
|
+
const removedCrossFieldKeys = (0, modularChangeTypes_js_1.newCrossFieldRangeTable)();
|
|
135
|
+
const composedRoots = composeRootTables(change1, change2, composedNodeToParent, movedCrossFieldKeys, removedCrossFieldKeys, pendingCompositions);
|
|
136
|
+
const crossFieldTable = newComposeTable(change1, change2, composedRoots, movedCrossFieldKeys, removedCrossFieldKeys, pendingCompositions);
|
|
124
137
|
const composedFields = this.composeFieldMaps(change1.fieldChanges, change2.fieldChanges, undefined, genId, crossFieldTable, revisionMetadata);
|
|
125
138
|
this.composeInvalidatedElements(crossFieldTable, composedFields, composedNodeChanges, composedNodeToParent, composedNodeAliases, genId, revisionMetadata);
|
|
126
|
-
|
|
127
|
-
|
|
139
|
+
for (const entry of crossFieldTable.renamesToDelete.entries()) {
|
|
140
|
+
deleteNodeRenameFrom(crossFieldTable.composedRootNodes, entry.start, entry.length);
|
|
141
|
+
}
|
|
142
|
+
for (const [nodeId, location] of crossFieldTable.movedNodeToParent.entries()) {
|
|
143
|
+
// Moved nodes are from change2.
|
|
144
|
+
// If there is a corresponding node in change1, then composedNodeToParent will already have the correct entry,
|
|
145
|
+
// because the location of the node is the same in change1 and the composed change
|
|
146
|
+
// (since they have the same input context).
|
|
147
|
+
if (crossFieldTable.newToBaseNodeId.get(nodeId) === undefined) {
|
|
148
|
+
composedNodeToParent.set(nodeId, location);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
128
151
|
return {
|
|
129
152
|
fieldChanges: composedFields,
|
|
130
153
|
nodeChanges: composedNodeChanges,
|
|
131
154
|
nodeToParent: composedNodeToParent,
|
|
132
155
|
nodeAliases: composedNodeAliases,
|
|
133
|
-
crossFieldKeys:
|
|
156
|
+
crossFieldKeys: composeCrossFieldKeyTables(change1.crossFieldKeys, change2.crossFieldKeys, crossFieldTable.movedCrossFieldKeys, crossFieldTable.removedCrossFieldKeys),
|
|
157
|
+
rootNodes: composedRoots,
|
|
134
158
|
};
|
|
135
159
|
}
|
|
136
160
|
composeInvalidatedField(fieldChange, crossFieldTable, genId, revisionMetadata) {
|
|
137
161
|
const context = crossFieldTable.fieldToContext.get(fieldChange);
|
|
138
162
|
(0, internal_1.assert)(context !== undefined, 0x8cc /* Should have context for every invalidated field */);
|
|
139
|
-
const {
|
|
163
|
+
const { change1: fieldChange1, change2: fieldChange2, composedChange } = context;
|
|
164
|
+
crossFieldTable.pendingCompositions.affectedBaseFields.delete(fieldIdKeyFromFieldId(context.fieldId));
|
|
140
165
|
const rebaser = getChangeHandler(this.fieldKinds, composedChange.fieldKind).rebaser;
|
|
141
166
|
const composeNodes = (child1, child2) => {
|
|
142
|
-
if (child1 !== undefined &&
|
|
143
|
-
|
|
144
|
-
(0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(crossFieldTable.newToBaseNodeId, child2) === undefined) {
|
|
145
|
-
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(crossFieldTable.newToBaseNodeId, child2, child1);
|
|
146
|
-
crossFieldTable.pendingCompositions.nodeIdsToCompose.push([child1, child2]);
|
|
167
|
+
if (child1 !== undefined && child2 !== undefined) {
|
|
168
|
+
addNodesToCompose(crossFieldTable, child1, child2);
|
|
147
169
|
}
|
|
148
170
|
return child1 ?? child2 ?? (0, internal_1.fail)(0xb22 /* Should not compose two undefined nodes */);
|
|
149
171
|
};
|
|
150
|
-
const amendedChange = rebaser.compose(fieldChange1, fieldChange2, composeNodes, genId, new
|
|
172
|
+
const amendedChange = rebaser.compose(fieldChange1, fieldChange2, composeNodes, genId, new ComposeNodeManagerI(crossFieldTable, context.fieldId, false), revisionMetadata);
|
|
151
173
|
composedChange.change = (0, index_js_3.brand)(amendedChange);
|
|
152
174
|
}
|
|
153
175
|
/**
|
|
@@ -156,32 +178,23 @@ class ModularChangeFamily {
|
|
|
156
178
|
* - discovering that two node changesets refer to the same node (`nodeIdsToCompose`)
|
|
157
179
|
* - a previously composed field being invalidated by a cross field effect (`invalidatedFields`)
|
|
158
180
|
* - a field which was copied directly from an input changeset being invalidated by a cross field effect
|
|
159
|
-
* (`affectedBaseFields`
|
|
181
|
+
* (`affectedBaseFields`)
|
|
160
182
|
*
|
|
161
183
|
* Updating an element may invalidate further elements. This function runs until there is no more invalidation.
|
|
162
184
|
*/
|
|
163
185
|
composeInvalidatedElements(table, composedFields, composedNodes, composedNodeToParent, nodeAliases, genId, metadata) {
|
|
164
186
|
const pending = table.pendingCompositions;
|
|
165
|
-
while (
|
|
166
|
-
|
|
167
|
-
pending.affectedBaseFields
|
|
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);
|
|
187
|
+
while (pending.nodeIdsToCompose.length > 0 || pending.affectedBaseFields.length > 0) {
|
|
188
|
+
this.processPendingNodeCompositions(table, composedNodes, composedNodeToParent, nodeAliases, genId, metadata);
|
|
189
|
+
this.composeAffectedFields(table, table.baseChange, pending.affectedBaseFields, composedFields, composedNodes, genId, metadata);
|
|
177
190
|
}
|
|
178
191
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
this.composeInvalidatedField(fieldChange, table, genId, metadata);
|
|
192
|
+
processPendingNodeCompositions(table, composedNodes, composedNodeToParent, nodeAliases, genId, metadata) {
|
|
193
|
+
// Note that the call to `composeNodesById` can add entries to `crossFieldTable.nodeIdPairs`.
|
|
194
|
+
for (const [id1, id2] of table.pendingCompositions.nodeIdsToCompose) {
|
|
195
|
+
this.composeNodesById(table.baseChange, table.newChange, composedNodes, composedNodeToParent, nodeAliases, id1, id2, genId, table, metadata);
|
|
184
196
|
}
|
|
197
|
+
table.pendingCompositions.nodeIdsToCompose.length = 0;
|
|
185
198
|
}
|
|
186
199
|
/**
|
|
187
200
|
* Ensures that each field in `affectedFields` has been updated in the composition output.
|
|
@@ -194,39 +207,34 @@ class ModularChangeFamily {
|
|
|
194
207
|
* If not, they are assumed to be part of the new changeset.
|
|
195
208
|
* @param affectedFields - The set of fields to process.
|
|
196
209
|
*/
|
|
197
|
-
composeAffectedFields(table, change,
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
210
|
+
composeAffectedFields(table, change, affectedFields, composedFields, composedNodes, genId, metadata) {
|
|
211
|
+
const fieldsToProcess = affectedFields.clone();
|
|
212
|
+
affectedFields.clear();
|
|
213
|
+
for (const fieldIdKey of fieldsToProcess.keys()) {
|
|
214
|
+
const fieldId = fieldIdFromFieldIdKey(fieldIdKey);
|
|
215
|
+
const fieldChange = fieldChangeFromId(change, fieldId);
|
|
201
216
|
if (table.fieldToContext.has(fieldChange) ||
|
|
202
217
|
table.newFieldToBaseField.has(fieldChange)) {
|
|
203
|
-
|
|
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(fieldId, change1, change2, genId, table, metadata);
|
|
213
|
-
if (fieldId.nodeId === undefined) {
|
|
214
|
-
composedFields.set(fieldId.field, composedField);
|
|
215
|
-
continue;
|
|
218
|
+
this.composeInvalidatedField(fieldChange, table, genId, metadata);
|
|
216
219
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if (!table.composedNodes.has(nodeChangeset)) {
|
|
220
|
-
nodeChangeset = cloneNodeChangeset(nodeChangeset);
|
|
221
|
-
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(composedNodes, nodeId, nodeChangeset);
|
|
222
|
-
}
|
|
223
|
-
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- using ??= could change behavior if value is falsy
|
|
224
|
-
if (nodeChangeset.fieldChanges === undefined) {
|
|
225
|
-
nodeChangeset.fieldChanges = new Map();
|
|
220
|
+
else {
|
|
221
|
+
this.composeFieldWithNoNewChange(table, fieldChange, fieldId, composedFields, composedNodes, genId, metadata);
|
|
226
222
|
}
|
|
227
|
-
nodeChangeset.fieldChanges.set(fieldId.field, composedField);
|
|
228
223
|
}
|
|
229
|
-
|
|
224
|
+
}
|
|
225
|
+
composeFieldWithNoNewChange(table, baseFieldChange, fieldId, composedFields, composedNodes, genId, metadata) {
|
|
226
|
+
const emptyChange = this.createEmptyFieldChange(baseFieldChange.fieldKind);
|
|
227
|
+
const composedField = this.composeFieldChanges(fieldId, baseFieldChange, emptyChange, genId, table, metadata);
|
|
228
|
+
if (fieldId.nodeId === undefined) {
|
|
229
|
+
composedFields.set(fieldId.field, composedField);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const nodeId = normalizeNodeId((0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(table.newToBaseNodeId, fieldId.nodeId) ?? fieldId.nodeId, table.baseChange.nodeAliases);
|
|
233
|
+
// We clone the node changeset before mutating it, as it may be from one of the input changesets.
|
|
234
|
+
const nodeChangeset = cloneNodeChangeset(nodeChangeFromId(composedNodes, table.baseChange.nodeAliases, nodeId));
|
|
235
|
+
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(composedNodes, nodeId, nodeChangeset);
|
|
236
|
+
nodeChangeset.fieldChanges ??= new Map();
|
|
237
|
+
nodeChangeset.fieldChanges.set(fieldId.field, composedField);
|
|
230
238
|
}
|
|
231
239
|
composeFieldMaps(change1, change2, parentId, genId, crossFieldTable, revisionMetadata) {
|
|
232
240
|
const composedFields = new Map();
|
|
@@ -236,6 +244,14 @@ class ModularChangeFamily {
|
|
|
236
244
|
for (const [field, fieldChange1] of change1) {
|
|
237
245
|
const fieldId = { nodeId: parentId, field };
|
|
238
246
|
const fieldChange2 = change2.get(field);
|
|
247
|
+
const cachedComposedFieldChange = crossFieldTable.fieldToContext.get(fieldChange1)?.composedChange;
|
|
248
|
+
if (fieldChange2 === undefined && cachedComposedFieldChange !== undefined) {
|
|
249
|
+
// This can happen if the field was previous processed in `composeFieldWithNoNewChange`.
|
|
250
|
+
// If `change2` does not have a change for this field, then without this check we would
|
|
251
|
+
// lose the composed field change and instead simply have `change1`'s change.
|
|
252
|
+
composedFields.set(field, cachedComposedFieldChange);
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
239
255
|
const composedField = fieldChange2 === undefined
|
|
240
256
|
? fieldChange1
|
|
241
257
|
: this.composeFieldChanges(fieldId, fieldChange1, fieldChange2, genId, crossFieldTable, revisionMetadata);
|
|
@@ -255,17 +271,16 @@ class ModularChangeFamily {
|
|
|
255
271
|
* will be added to `crossFieldTable.pendingCompositions.nodeIdsToCompose`.
|
|
256
272
|
*
|
|
257
273
|
* Any fields which had cross-field information sent to them as part of this field composition
|
|
258
|
-
* will be added to
|
|
274
|
+
* will be added to `affectedBaseFields` in `crossFieldTable.pendingCompositions`.
|
|
259
275
|
*
|
|
260
276
|
* Any composed `FieldChange` which is invalidated by new cross-field information will be added to `crossFieldTable.invalidatedFields`.
|
|
261
277
|
*/
|
|
262
278
|
composeFieldChanges(fieldId, change1, change2, idAllocator, crossFieldTable, revisionMetadata) {
|
|
263
279
|
const { fieldKind, changeHandler, change1: change1Normalized, change2: change2Normalized, } = this.normalizeFieldChanges(change1, change2);
|
|
264
|
-
const manager = new
|
|
280
|
+
const manager = new ComposeNodeManagerI(crossFieldTable, fieldId);
|
|
265
281
|
const composedChange = changeHandler.rebaser.compose(change1Normalized, change2Normalized, (child1, child2) => {
|
|
266
282
|
if (child1 !== undefined && child2 !== undefined) {
|
|
267
|
-
(
|
|
268
|
-
crossFieldTable.pendingCompositions.nodeIdsToCompose.push([child1, child2]);
|
|
283
|
+
addNodesToCompose(crossFieldTable, child1, child2);
|
|
269
284
|
}
|
|
270
285
|
return child1 ?? child2 ?? (0, internal_1.fail)(0xb23 /* Should not compose two undefined nodes */);
|
|
271
286
|
}, idAllocator, manager, revisionMetadata);
|
|
@@ -282,19 +297,18 @@ class ModularChangeFamily {
|
|
|
282
297
|
crossFieldTable.newFieldToBaseField.set(change2, change1);
|
|
283
298
|
return composedField;
|
|
284
299
|
}
|
|
285
|
-
composeNodesById(
|
|
286
|
-
const nodeChangeset1 = nodeChangeFromId(
|
|
287
|
-
const nodeChangeset2 = nodeChangeFromId(
|
|
300
|
+
composeNodesById(change1, change2, composedNodes, composedNodeToParent, composedAliases, id1, id2, idAllocator, crossFieldTable, revisionMetadata) {
|
|
301
|
+
const nodeChangeset1 = nodeChangeFromId(change1.nodeChanges, change1.nodeAliases, id1);
|
|
302
|
+
const nodeChangeset2 = nodeChangeFromId(change2.nodeChanges, change2.nodeAliases, id2);
|
|
288
303
|
const composedNodeChangeset = this.composeNodeChanges(id1, nodeChangeset1, nodeChangeset2, idAllocator, crossFieldTable, revisionMetadata);
|
|
289
304
|
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(composedNodes, id1, composedNodeChangeset);
|
|
290
305
|
if (!(0, index_js_2.areEqualChangeAtomIds)(id1, id2)) {
|
|
291
306
|
composedNodes.delete([id2.revision, id2.localId]);
|
|
292
307
|
composedNodeToParent.delete([id2.revision, id2.localId]);
|
|
293
|
-
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(
|
|
308
|
+
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(composedAliases, id2, id1);
|
|
294
309
|
// We need to delete id1 to avoid forming a cycle in case id1 already had an alias.
|
|
295
|
-
|
|
310
|
+
composedAliases.delete([id1.revision, id1.localId]);
|
|
296
311
|
}
|
|
297
|
-
crossFieldTable.composedNodes.add(composedNodeChangeset);
|
|
298
312
|
}
|
|
299
313
|
composeNodeChanges(nodeId, change1, change2, genId, crossFieldTable, revisionMetadata) {
|
|
300
314
|
// WARNING: this composition logic assumes that we never make compositions of the following form:
|
|
@@ -340,16 +354,24 @@ class ModularChangeFamily {
|
|
|
340
354
|
const noChangeConstraintOnRevert = change.change.noChangeConstraint;
|
|
341
355
|
if (hasConflicts(change.change)) {
|
|
342
356
|
return makeModularChangeset({
|
|
357
|
+
rebaseVersion: change.change.rebaseVersion,
|
|
343
358
|
maxId: change.change.maxId,
|
|
344
359
|
revisions: revInfos,
|
|
345
360
|
destroys,
|
|
346
361
|
});
|
|
347
362
|
}
|
|
348
363
|
const genId = (0, index_js_3.idAllocatorFromMaxId)(change.change.maxId ?? -1);
|
|
364
|
+
const invertedNodeToParent = (0, index_js_3.brand)(change.change.nodeToParent.clone());
|
|
349
365
|
const crossFieldTable = {
|
|
350
|
-
|
|
366
|
+
change: change.change,
|
|
367
|
+
isRollback,
|
|
368
|
+
entries: (0, index_js_2.newChangeAtomIdRangeMap)(),
|
|
351
369
|
originalFieldToContext: new Map(),
|
|
352
|
-
|
|
370
|
+
invertRevision: revisionForInvert,
|
|
371
|
+
invertedNodeToParent,
|
|
372
|
+
invalidatedFields: new Set(),
|
|
373
|
+
invertedRoots: invertRootTable(change.change, invertedNodeToParent, isRollback),
|
|
374
|
+
attachToDetachId: (0, index_js_2.newChangeAtomIdTransform)(),
|
|
353
375
|
};
|
|
354
376
|
const { revInfos: oldRevInfos } = getRevInfoFromTaggedChanges([change]);
|
|
355
377
|
const revisionMetadata = (0, index_js_2.revisionMetadataSourceFromInfo)(oldRevInfos);
|
|
@@ -365,16 +387,19 @@ class ModularChangeFamily {
|
|
|
365
387
|
const originalFieldChange = fieldChange.change;
|
|
366
388
|
const context = crossFieldTable.originalFieldToContext.get(fieldChange);
|
|
367
389
|
(0, internal_1.assert)(context !== undefined, 0x851 /* Should have context for every invalidated field */);
|
|
368
|
-
const { invertedField
|
|
369
|
-
const amendedChange = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).rebaser.invert(originalFieldChange, isRollback, genId, revisionForInvert, new
|
|
390
|
+
const { invertedField } = context;
|
|
391
|
+
const amendedChange = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).rebaser.invert(originalFieldChange, isRollback, genId, revisionForInvert, new InvertNodeManagerI(crossFieldTable, context.fieldId), revisionMetadata);
|
|
370
392
|
invertedField.change = (0, index_js_3.brand)(amendedChange);
|
|
371
393
|
}
|
|
372
394
|
}
|
|
373
395
|
const crossFieldKeys = this.makeCrossFieldKeyTable(invertedFields, invertedNodes);
|
|
396
|
+
this.processInvertRenames(crossFieldTable);
|
|
374
397
|
return makeModularChangeset({
|
|
398
|
+
rebaseVersion: change.change.rebaseVersion,
|
|
375
399
|
fieldChanges: invertedFields,
|
|
376
400
|
nodeChanges: invertedNodes,
|
|
377
401
|
nodeToParent: crossFieldTable.invertedNodeToParent,
|
|
402
|
+
rootNodes: crossFieldTable.invertedRoots,
|
|
378
403
|
nodeAliases: change.change.nodeAliases,
|
|
379
404
|
crossFieldKeys,
|
|
380
405
|
maxId: genId.getMaxId(),
|
|
@@ -390,7 +415,7 @@ class ModularChangeFamily {
|
|
|
390
415
|
const invertedFields = new Map();
|
|
391
416
|
for (const [field, fieldChange] of changes) {
|
|
392
417
|
const fieldId = { nodeId: parentId, field };
|
|
393
|
-
const manager = new
|
|
418
|
+
const manager = new InvertNodeManagerI(crossFieldTable, fieldId);
|
|
394
419
|
const invertedChange = getChangeHandler(this.fieldKinds, fieldChange.fieldKind).rebaser.invert(fieldChange.change, isRollback, genId, revisionForInvert, manager, revisionMetadata);
|
|
395
420
|
const invertedFieldChange = {
|
|
396
421
|
...fieldChange,
|
|
@@ -422,6 +447,12 @@ class ModularChangeFamily {
|
|
|
422
447
|
}
|
|
423
448
|
return inverse;
|
|
424
449
|
}
|
|
450
|
+
processInvertRenames(table) {
|
|
451
|
+
for (const { start: newAttachId, value: originalDetachId, length, } of table.attachToDetachId.entries()) {
|
|
452
|
+
// Note that the detach location is already set in `invertDetach`.
|
|
453
|
+
addNodeRename(table.invertedRoots, originalDetachId, newAttachId, length, undefined);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
425
456
|
rebase(taggedChange, potentiallyConflictedOver, revisionMetadata) {
|
|
426
457
|
// Our current cell ordering scheme in sequences depends on being able to rebase over a change with conflicts.
|
|
427
458
|
// This means that we must rebase over a muted version of the conflicted changeset.
|
|
@@ -432,17 +463,26 @@ class ModularChangeFamily {
|
|
|
432
463
|
const maxId = Math.max(change.maxId ?? -1, over.change.maxId ?? -1);
|
|
433
464
|
const idState = { maxId };
|
|
434
465
|
const genId = (0, index_js_3.idAllocatorFromState)(idState);
|
|
466
|
+
const affectedBaseFields = newFieldIdKeyBTree();
|
|
467
|
+
const nodesToRebase = [];
|
|
468
|
+
const rebasedNodeToParent = (0, index_js_3.brand)(change.nodeToParent.clone());
|
|
469
|
+
const rebaseVersion = Math.max(change.rebaseVersion, over.change.rebaseVersion);
|
|
470
|
+
const rebasedRootNodes = rebaseRoots(change, over.change, affectedBaseFields, nodesToRebase, rebasedNodeToParent, rebaseVersion);
|
|
435
471
|
const crossFieldTable = {
|
|
436
|
-
|
|
472
|
+
rebaseVersion,
|
|
473
|
+
entries: newDetachedEntryMap(),
|
|
437
474
|
newChange: change,
|
|
438
475
|
baseChange: over.change,
|
|
439
476
|
baseFieldToContext: new Map(),
|
|
477
|
+
baseRoots: over.change.rootNodes,
|
|
478
|
+
rebasedRootNodes,
|
|
440
479
|
baseToRebasedNodeId: (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
441
480
|
rebasedFields: new Set(),
|
|
442
|
-
rebasedNodeToParent
|
|
443
|
-
|
|
481
|
+
rebasedNodeToParent,
|
|
482
|
+
rebasedDetachLocations: (0, index_js_2.newChangeAtomIdRangeMap)(),
|
|
483
|
+
movedDetaches: (0, index_js_2.newChangeAtomIdRangeMap)(),
|
|
444
484
|
nodeIdPairs: [],
|
|
445
|
-
affectedBaseFields
|
|
485
|
+
affectedBaseFields,
|
|
446
486
|
fieldsWithUnattachedChild: new Set(),
|
|
447
487
|
};
|
|
448
488
|
const getBaseRevisions = () => revisionInfoFromTaggedChange(over).map((info) => info.revision);
|
|
@@ -452,8 +492,9 @@ class ModularChangeFamily {
|
|
|
452
492
|
getBaseRevisions,
|
|
453
493
|
};
|
|
454
494
|
const rebasedNodes = (0, index_js_3.brand)(change.nodeChanges.clone());
|
|
455
|
-
const rebasedFields = this.rebaseIntersectingFields(crossFieldTable, rebasedNodes, genId, rebaseMetadata);
|
|
456
|
-
this.
|
|
495
|
+
const rebasedFields = this.rebaseIntersectingFields(nodesToRebase, crossFieldTable, rebasedNodes, genId, rebaseMetadata);
|
|
496
|
+
this.rebaseInvalidatedFields(rebasedFields, rebasedNodes, crossFieldTable, rebaseMetadata, genId);
|
|
497
|
+
fixupRebasedDetachLocations(crossFieldTable);
|
|
457
498
|
const constraintState = newConstraintState(change.constraintViolationCount ?? 0);
|
|
458
499
|
const revertConstraintState = newConstraintState(change.constraintViolationCountOnRevert ?? 0);
|
|
459
500
|
let noChangeConstraint = change.noChangeConstraint;
|
|
@@ -461,13 +502,17 @@ class ModularChangeFamily {
|
|
|
461
502
|
noChangeConstraint = { violated: true };
|
|
462
503
|
constraintState.violationCount += 1;
|
|
463
504
|
}
|
|
464
|
-
this.
|
|
505
|
+
this.updateConstraints(rebasedFields, rebasedNodes, rebasedRootNodes, constraintState, revertConstraintState);
|
|
506
|
+
const fieldsWithRootMoves = getFieldsWithRootMoves(crossFieldTable.rebasedRootNodes, change.nodeAliases);
|
|
507
|
+
const fieldToRootChanges = getFieldToRootChanges(crossFieldTable.rebasedRootNodes, change.nodeAliases);
|
|
465
508
|
const rebased = makeModularChangeset({
|
|
466
|
-
fieldChanges: this.pruneFieldMap(rebasedFields, rebasedNodes),
|
|
509
|
+
fieldChanges: this.pruneFieldMap(rebasedFields, undefined, rebasedNodes, crossFieldTable.rebasedNodeToParent, change.nodeAliases, crossFieldTable.rebasedRootNodes, fieldsWithRootMoves, fieldToRootChanges),
|
|
467
510
|
nodeChanges: rebasedNodes,
|
|
468
511
|
nodeToParent: crossFieldTable.rebasedNodeToParent,
|
|
512
|
+
rootNodes: this.pruneRoots(crossFieldTable.rebasedRootNodes, rebasedNodes, crossFieldTable.rebasedNodeToParent, change.nodeAliases, fieldsWithRootMoves, fieldToRootChanges),
|
|
513
|
+
// TODO: Do we need to include aliases for node changesets added during rebasing?
|
|
469
514
|
nodeAliases: change.nodeAliases,
|
|
470
|
-
crossFieldKeys: crossFieldTable.
|
|
515
|
+
crossFieldKeys: rebaseCrossFieldKeys(change.crossFieldKeys, crossFieldTable.movedDetaches, crossFieldTable.rebasedDetachLocations),
|
|
471
516
|
maxId: idState.maxId,
|
|
472
517
|
revisions: change.revisions,
|
|
473
518
|
constraintViolationCount: constraintState.violationCount,
|
|
@@ -477,15 +522,22 @@ class ModularChangeFamily {
|
|
|
477
522
|
builds: change.builds,
|
|
478
523
|
destroys: change.destroys,
|
|
479
524
|
refreshers: change.refreshers,
|
|
525
|
+
rebaseVersion,
|
|
480
526
|
});
|
|
527
|
+
// XXX: This is an expensive assert which should be disabled before merging.
|
|
528
|
+
validateChangeset(rebased, this.fieldKinds);
|
|
481
529
|
return rebased;
|
|
482
530
|
}
|
|
483
531
|
// This performs a first pass on all fields which have both new and base changes.
|
|
484
532
|
// TODO: Can we also handle additional passes in this method?
|
|
485
|
-
rebaseIntersectingFields(crossFieldTable, rebasedNodes, genId, metadata) {
|
|
533
|
+
rebaseIntersectingFields(rootChanges, crossFieldTable, rebasedNodes, genId, metadata) {
|
|
486
534
|
const change = crossFieldTable.newChange;
|
|
487
535
|
const baseChange = crossFieldTable.baseChange;
|
|
488
536
|
const rebasedFields = this.rebaseFieldMap(change.fieldChanges, baseChange.fieldChanges, undefined, genId, crossFieldTable, metadata);
|
|
537
|
+
for (const [newChildChange, baseChildChange] of rootChanges) {
|
|
538
|
+
const rebasedNode = this.rebaseNodeChange(newChildChange, baseChildChange, genId, crossFieldTable, metadata);
|
|
539
|
+
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(rebasedNodes, newChildChange, rebasedNode);
|
|
540
|
+
}
|
|
489
541
|
// This loop processes all fields which have both base and new changes.
|
|
490
542
|
// Note that the call to `rebaseNodeChange` can add entries to `crossFieldTable.nodeIdPairs`.
|
|
491
543
|
for (const [newId, baseId, _attachState] of crossFieldTable.nodeIdPairs) {
|
|
@@ -494,83 +546,85 @@ class ModularChangeFamily {
|
|
|
494
546
|
}
|
|
495
547
|
return rebasedFields;
|
|
496
548
|
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
(0, internal_1.assert)(
|
|
506
|
-
if (
|
|
507
|
-
|
|
508
|
-
|
|
549
|
+
rebaseFieldWithoutNewChanges(baseFieldChange, baseFieldId, crossFieldTable, rebasedFields, rebasedNodes, genId, metadata,
|
|
550
|
+
/**
|
|
551
|
+
* The ID of a node in `baseFieldChange` which should be included in the rebased field change.
|
|
552
|
+
*/
|
|
553
|
+
baseNodeId) {
|
|
554
|
+
// This field has no changes in the new changeset, otherwise it would have been added to
|
|
555
|
+
// `crossFieldTable.baseFieldToContext` when processing fields with both base and new changes.
|
|
556
|
+
const rebaseChild = (child, baseChild, stateChange) => {
|
|
557
|
+
(0, internal_1.assert)(child === undefined, 0x9c3 /* There should be no new changes in this field */);
|
|
558
|
+
if (baseChild === undefined || baseNodeId === undefined) {
|
|
559
|
+
return undefined;
|
|
560
|
+
}
|
|
561
|
+
return (0, index_js_2.areEqualChangeAtomIds)(normalizeNodeId(baseChild, crossFieldTable.baseChange.nodeAliases), baseNodeId)
|
|
562
|
+
? baseNodeId
|
|
563
|
+
: undefined;
|
|
564
|
+
};
|
|
565
|
+
const handler = getChangeHandler(this.fieldKinds, baseFieldChange.fieldKind);
|
|
566
|
+
const fieldChange = {
|
|
567
|
+
...baseFieldChange,
|
|
568
|
+
change: (0, index_js_3.brand)(handler.createEmpty()),
|
|
569
|
+
};
|
|
570
|
+
const rebasedNodeId = baseFieldId.nodeId === undefined
|
|
571
|
+
? undefined
|
|
572
|
+
: rebasedNodeIdFromBaseNodeId(crossFieldTable, baseFieldId.nodeId);
|
|
573
|
+
const fieldId = { nodeId: rebasedNodeId, field: baseFieldId.field };
|
|
574
|
+
const rebasedField = handler.rebaser.rebase(fieldChange.change, baseFieldChange.change, rebaseChild, genId, new RebaseNodeManagerI(crossFieldTable, fieldId), metadata, crossFieldTable.rebaseVersion);
|
|
575
|
+
const rebasedFieldChange = {
|
|
576
|
+
...baseFieldChange,
|
|
577
|
+
change: (0, index_js_3.brand)(rebasedField),
|
|
578
|
+
};
|
|
579
|
+
const context = {
|
|
580
|
+
newChange: fieldChange,
|
|
581
|
+
baseChange: baseFieldChange,
|
|
582
|
+
rebasedChange: rebasedFieldChange,
|
|
583
|
+
fieldId,
|
|
584
|
+
baseNodeIds: (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
585
|
+
};
|
|
586
|
+
if (baseNodeId !== undefined) {
|
|
587
|
+
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(context.baseNodeIds, baseNodeId, true);
|
|
588
|
+
}
|
|
589
|
+
crossFieldTable.baseFieldToContext.set(baseFieldChange, context);
|
|
590
|
+
crossFieldTable.rebasedFields.add(rebasedFieldChange);
|
|
591
|
+
this.attachRebasedField(rebasedFields, rebasedNodes, crossFieldTable, rebasedFieldChange, fieldId, genId, metadata);
|
|
592
|
+
}
|
|
593
|
+
rebaseInvalidatedFields(rebasedFields, rebasedNodes, crossFieldTable, rebaseMetadata, genId) {
|
|
594
|
+
while (crossFieldTable.affectedBaseFields.size > 0) {
|
|
595
|
+
const baseFields = crossFieldTable.affectedBaseFields.clone();
|
|
596
|
+
crossFieldTable.affectedBaseFields.clear();
|
|
597
|
+
for (const baseFieldIdKey of baseFields.keys()) {
|
|
598
|
+
const baseFieldId = normalizeFieldId(fieldIdFromFieldIdKey(baseFieldIdKey), crossFieldTable.baseChange.nodeAliases);
|
|
599
|
+
const baseField = fieldChangeFromId(crossFieldTable.baseChange, baseFieldId);
|
|
600
|
+
(0, internal_1.assert)(baseField !== undefined, 0x9c2 /* Cross field key registered for empty field */);
|
|
601
|
+
const context = crossFieldTable.baseFieldToContext.get(baseField);
|
|
602
|
+
if (context === undefined) {
|
|
603
|
+
this.rebaseFieldWithoutNewChanges(baseField, baseFieldId, crossFieldTable, rebasedFields, rebasedNodes, genId, rebaseMetadata);
|
|
604
|
+
}
|
|
605
|
+
else {
|
|
606
|
+
this.rebaseInvalidatedField(baseField, crossFieldTable, context, rebaseMetadata, genId);
|
|
607
|
+
}
|
|
509
608
|
}
|
|
510
|
-
// This field has no changes in the new changeset, otherwise it would have been added to
|
|
511
|
-
// `crossFieldTable.baseFieldToContext` when processing fields with both base and new changes.
|
|
512
|
-
const handler = getChangeHandler(this.fieldKinds, baseFieldChange.fieldKind);
|
|
513
|
-
const fieldChange = {
|
|
514
|
-
...baseFieldChange,
|
|
515
|
-
change: (0, index_js_3.brand)(handler.createEmpty()),
|
|
516
|
-
};
|
|
517
|
-
const rebasedNodeId = baseNodeId === undefined
|
|
518
|
-
? undefined
|
|
519
|
-
: rebasedNodeIdFromBaseNodeId(crossFieldTable, baseNodeId);
|
|
520
|
-
const fieldId = { nodeId: rebasedNodeId, field: fieldKey };
|
|
521
|
-
const rebasedField = handler.rebaser.rebase(fieldChange.change, baseFieldChange.change, noNewChangesRebaseChild, genId, new RebaseManager(crossFieldTable, baseFieldChange, fieldId), metadata);
|
|
522
|
-
const rebasedFieldChange = {
|
|
523
|
-
...baseFieldChange,
|
|
524
|
-
change: (0, index_js_3.brand)(rebasedField),
|
|
525
|
-
};
|
|
526
|
-
// TODO: Deduplicate
|
|
527
|
-
crossFieldTable.baseFieldToContext.set(baseFieldChange, {
|
|
528
|
-
newChange: fieldChange,
|
|
529
|
-
baseChange: baseFieldChange,
|
|
530
|
-
rebasedChange: rebasedFieldChange,
|
|
531
|
-
fieldId,
|
|
532
|
-
baseNodeIds: [],
|
|
533
|
-
});
|
|
534
|
-
crossFieldTable.rebasedFields.add(rebasedFieldChange);
|
|
535
|
-
this.attachRebasedField(rebasedFields, rebasedNodes, crossFieldTable, rebasedFieldChange, fieldId, genId, metadata);
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
rebaseInvalidatedElements(rebasedFields, rebasedNodes, table, metadata, idAllocator) {
|
|
539
|
-
this.rebaseFieldsWithoutNewChanges(rebasedFields, rebasedNodes, table, idAllocator, metadata);
|
|
540
|
-
this.rebaseFieldsWithUnattachedChild(table, metadata, idAllocator);
|
|
541
|
-
this.rebaseInvalidatedFields(table, metadata, idAllocator);
|
|
542
|
-
}
|
|
543
|
-
rebaseInvalidatedFields(crossFieldTable, rebaseMetadata, genId) {
|
|
544
|
-
const fieldsToUpdate = crossFieldTable.invalidatedFields;
|
|
545
|
-
crossFieldTable.invalidatedFields = new Set();
|
|
546
|
-
for (const field of fieldsToUpdate) {
|
|
547
|
-
this.rebaseInvalidatedField(field, crossFieldTable, rebaseMetadata, genId);
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
rebaseFieldsWithUnattachedChild(table, metadata, idAllocator) {
|
|
551
|
-
for (const field of table.fieldsWithUnattachedChild) {
|
|
552
|
-
table.invalidatedFields.delete(field);
|
|
553
|
-
this.rebaseInvalidatedField(field, table, metadata, idAllocator, true);
|
|
554
609
|
}
|
|
555
610
|
}
|
|
556
|
-
rebaseInvalidatedField(baseField, crossFieldTable, rebaseMetadata, genId
|
|
557
|
-
const context = crossFieldTable.baseFieldToContext.get(baseField);
|
|
558
|
-
(0, internal_1.assert)(context !== undefined, 0x852 /* Every field should have a context */);
|
|
611
|
+
rebaseInvalidatedField(baseField, crossFieldTable, context, rebaseMetadata, genId) {
|
|
559
612
|
const { changeHandler, change1: fieldChangeset, change2: baseChangeset, } = this.normalizeFieldChanges(context.newChange, context.baseChange);
|
|
560
613
|
const rebaseChild = (curr, base) => {
|
|
561
614
|
if (curr !== undefined) {
|
|
562
615
|
return curr;
|
|
563
616
|
}
|
|
564
|
-
if (base !== undefined) {
|
|
565
|
-
|
|
566
|
-
if ((0, index_js_2.areEqualChangeAtomIds)(base, id)) {
|
|
567
|
-
return base;
|
|
568
|
-
}
|
|
569
|
-
}
|
|
617
|
+
if (base !== undefined && (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(context.baseNodeIds, base) === true) {
|
|
618
|
+
return base;
|
|
570
619
|
}
|
|
571
620
|
return undefined;
|
|
572
621
|
};
|
|
573
|
-
|
|
622
|
+
let allowInval = false;
|
|
623
|
+
if (crossFieldTable.fieldsWithUnattachedChild.has(baseField)) {
|
|
624
|
+
crossFieldTable.fieldsWithUnattachedChild.delete(baseField);
|
|
625
|
+
allowInval = true;
|
|
626
|
+
}
|
|
627
|
+
context.rebasedChange.change = (0, index_js_3.brand)(changeHandler.rebaser.rebase(fieldChangeset, baseChangeset, rebaseChild, genId, new RebaseNodeManagerI(crossFieldTable, context.fieldId, allowInval), rebaseMetadata, crossFieldTable.rebaseVersion));
|
|
574
628
|
}
|
|
575
629
|
attachRebasedField(rebasedFields, rebasedNodes, table, rebasedField, { nodeId, field: fieldKey }, idAllocator, metadata) {
|
|
576
630
|
if (nodeId === undefined) {
|
|
@@ -579,12 +633,14 @@ class ModularChangeFamily {
|
|
|
579
633
|
}
|
|
580
634
|
const rebasedNode = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(rebasedNodes, nodeId);
|
|
581
635
|
if (rebasedNode !== undefined) {
|
|
582
|
-
|
|
583
|
-
|
|
636
|
+
const updatedRebasedNode = cloneNodeChangeset(rebasedNode);
|
|
637
|
+
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(rebasedNodes, nodeId, updatedRebasedNode);
|
|
638
|
+
if (updatedRebasedNode.fieldChanges === undefined) {
|
|
639
|
+
updatedRebasedNode.fieldChanges = new Map([[fieldKey, rebasedField]]);
|
|
584
640
|
return;
|
|
585
641
|
}
|
|
586
|
-
(0, internal_1.assert)(!
|
|
587
|
-
|
|
642
|
+
(0, internal_1.assert)(!updatedRebasedNode.fieldChanges.has(fieldKey), 0x9c4 /* Expected an empty field */);
|
|
643
|
+
updatedRebasedNode.fieldChanges.set(fieldKey, rebasedField);
|
|
588
644
|
return;
|
|
589
645
|
}
|
|
590
646
|
const newNode = {
|
|
@@ -592,39 +648,51 @@ class ModularChangeFamily {
|
|
|
592
648
|
};
|
|
593
649
|
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(rebasedNodes, nodeId, newNode);
|
|
594
650
|
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(table.baseToRebasedNodeId, nodeId, nodeId);
|
|
595
|
-
const
|
|
596
|
-
this.attachRebasedNode(rebasedFields, rebasedNodes, table, nodeId,
|
|
597
|
-
}
|
|
598
|
-
attachRebasedNode(rebasedFields, rebasedNodes, table, baseNodeId,
|
|
599
|
-
|
|
651
|
+
const parentBase = getNodeParent(table.baseChange, nodeId);
|
|
652
|
+
this.attachRebasedNode(rebasedFields, rebasedNodes, table, nodeId, parentBase, idAllocator, metadata);
|
|
653
|
+
}
|
|
654
|
+
attachRebasedNode(rebasedFields, rebasedNodes, table, baseNodeId, parentBase, idAllocator, metadata) {
|
|
655
|
+
if (parentBase.root !== undefined) {
|
|
656
|
+
const renamedRoot = firstAttachIdFromDetachId(table.baseChange.rootNodes, parentBase.root, 1).value;
|
|
657
|
+
const attachField = table.baseChange.crossFieldKeys.getFirst({ ...renamedRoot, target: crossFieldQueries_js_1.NodeMoveType.Attach }, 1).value;
|
|
658
|
+
if (attachField === undefined) {
|
|
659
|
+
const baseDetachLocation = table.baseChange.rootNodes.detachLocations.getFirst(parentBase.root, 1).value;
|
|
660
|
+
assignRootChange(table.rebasedRootNodes, table.rebasedNodeToParent, renamedRoot, baseNodeId, baseDetachLocation, table.rebaseVersion);
|
|
661
|
+
// We need to make sure the rebased changeset includes the detach location,
|
|
662
|
+
// so we add that field to `affectedBaseFields` unless it's already been processed.
|
|
663
|
+
if (baseDetachLocation !== undefined &&
|
|
664
|
+
!table.baseFieldToContext.has(fieldChangeFromId(table.baseChange, baseDetachLocation))) {
|
|
665
|
+
table.affectedBaseFields.set(fieldIdKeyFromFieldId(baseDetachLocation), true);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
else {
|
|
669
|
+
// The base change inserts this node into `attachField`, so the rebased change should represent this node there.
|
|
670
|
+
const normalizedAttachField = normalizeFieldId(attachField, table.baseChange.nodeAliases);
|
|
671
|
+
const entry = table.entries.getFirst(renamedRoot, 1).value ?? {};
|
|
672
|
+
table.entries.set(renamedRoot, 1, { ...entry, nodeChange: baseNodeId });
|
|
673
|
+
table.affectedBaseFields.set(fieldIdKeyFromFieldId(normalizedAttachField), true);
|
|
674
|
+
this.attachRebasedNode(rebasedFields, rebasedNodes, table, baseNodeId, { field: normalizedAttachField }, idAllocator, metadata);
|
|
675
|
+
}
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
const parentFieldIdBase = parentBase.field;
|
|
679
|
+
const baseFieldChange = fieldChangeFromId(table.baseChange, parentFieldIdBase);
|
|
600
680
|
const rebasedFieldId = rebasedFieldIdFromBaseId(table, parentFieldIdBase);
|
|
601
|
-
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(table.rebasedNodeToParent, baseNodeId, rebasedFieldId);
|
|
681
|
+
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(table.rebasedNodeToParent, baseNodeId, { field: rebasedFieldId });
|
|
602
682
|
const context = table.baseFieldToContext.get(baseFieldChange);
|
|
603
683
|
if (context !== undefined) {
|
|
604
684
|
// We've already processed this field.
|
|
605
|
-
// The new child node will be attached in
|
|
606
|
-
|
|
607
|
-
|
|
685
|
+
// The new child node will be attached in the next pass.
|
|
686
|
+
// Note that adding to `fieldsWithUnattachedChild` allows that field to generate new invalidations,
|
|
687
|
+
// so to avoid invalidation cycles we make sure we only add to it once per new unattached child.
|
|
688
|
+
// This is done by checking whether `context.baseNodeIds` already contained `baseNodeId`.
|
|
689
|
+
if ((0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(context.baseNodeIds, baseNodeId, true)) {
|
|
690
|
+
table.fieldsWithUnattachedChild.add(baseFieldChange);
|
|
691
|
+
table.affectedBaseFields.set(fieldIdKeyFromFieldId(parentFieldIdBase), true);
|
|
692
|
+
}
|
|
608
693
|
return;
|
|
609
694
|
}
|
|
610
|
-
|
|
611
|
-
const fieldChange = {
|
|
612
|
-
...baseFieldChange,
|
|
613
|
-
change: (0, index_js_3.brand)(handler.createEmpty()),
|
|
614
|
-
};
|
|
615
|
-
const rebasedChangeset = handler.rebaser.rebase(handler.createEmpty(), baseFieldChange.change, (_idNew, idBase) => idBase !== undefined && (0, index_js_2.areEqualChangeAtomIds)(idBase, baseNodeId)
|
|
616
|
-
? baseNodeId
|
|
617
|
-
: undefined, idAllocator, new RebaseManager(table, baseFieldChange, rebasedFieldId), metadata);
|
|
618
|
-
const rebasedField = { ...baseFieldChange, change: (0, index_js_3.brand)(rebasedChangeset) };
|
|
619
|
-
table.rebasedFields.add(rebasedField);
|
|
620
|
-
table.baseFieldToContext.set(baseFieldChange, {
|
|
621
|
-
newChange: fieldChange,
|
|
622
|
-
baseChange: baseFieldChange,
|
|
623
|
-
rebasedChange: rebasedField,
|
|
624
|
-
fieldId: rebasedFieldId,
|
|
625
|
-
baseNodeIds: [],
|
|
626
|
-
});
|
|
627
|
-
this.attachRebasedField(rebasedFields, rebasedNodes, table, rebasedField, rebasedFieldId, idAllocator, metadata);
|
|
695
|
+
this.rebaseFieldWithoutNewChanges(baseFieldChange, parentFieldIdBase, table, rebasedFields, rebasedNodes, idAllocator, metadata, baseNodeId);
|
|
628
696
|
}
|
|
629
697
|
rebaseFieldMap(change, over, parentId, genId, crossFieldTable, revisionMetadata) {
|
|
630
698
|
const rebasedFields = new Map();
|
|
@@ -642,8 +710,8 @@ class ModularChangeFamily {
|
|
|
642
710
|
continue;
|
|
643
711
|
}
|
|
644
712
|
const { fieldKind, changeHandler, change1: fieldChangeset, change2: baseChangeset, } = this.normalizeFieldChanges(fieldChange, baseChange);
|
|
645
|
-
const manager = new
|
|
646
|
-
const rebasedField = changeHandler.rebaser.rebase(fieldChangeset, baseChangeset, rebaseChild, genId, manager, revisionMetadata);
|
|
713
|
+
const manager = new RebaseNodeManagerI(crossFieldTable, fieldId);
|
|
714
|
+
const rebasedField = changeHandler.rebaser.rebase(fieldChangeset, baseChangeset, rebaseChild, genId, manager, revisionMetadata, crossFieldTable.rebaseVersion);
|
|
647
715
|
const rebasedFieldChange = {
|
|
648
716
|
fieldKind,
|
|
649
717
|
change: (0, index_js_3.brand)(rebasedField),
|
|
@@ -654,15 +722,15 @@ class ModularChangeFamily {
|
|
|
654
722
|
newChange: fieldChange,
|
|
655
723
|
rebasedChange: rebasedFieldChange,
|
|
656
724
|
fieldId,
|
|
657
|
-
baseNodeIds:
|
|
725
|
+
baseNodeIds: (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
658
726
|
});
|
|
659
727
|
crossFieldTable.rebasedFields.add(rebasedFieldChange);
|
|
660
728
|
}
|
|
661
729
|
return rebasedFields;
|
|
662
730
|
}
|
|
663
731
|
rebaseNodeChange(newId, baseId, genId, crossFieldTable, revisionMetadata) {
|
|
664
|
-
const change = nodeChangeFromId(crossFieldTable.newChange.nodeChanges, newId);
|
|
665
|
-
const over = nodeChangeFromId(crossFieldTable.baseChange.nodeChanges, baseId);
|
|
732
|
+
const change = nodeChangeFromId(crossFieldTable.newChange.nodeChanges, crossFieldTable.newChange.nodeAliases, newId);
|
|
733
|
+
const over = nodeChangeFromId(crossFieldTable.baseChange.nodeChanges, crossFieldTable.baseChange.nodeAliases, baseId);
|
|
666
734
|
const baseMap = over?.fieldChanges ?? new Map();
|
|
667
735
|
const fieldChanges = change.fieldChanges !== undefined && over.fieldChanges !== undefined
|
|
668
736
|
? this.rebaseFieldMap(change?.fieldChanges ?? new Map(), baseMap, newId, genId, crossFieldTable, revisionMetadata)
|
|
@@ -680,28 +748,37 @@ class ModularChangeFamily {
|
|
|
680
748
|
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(crossFieldTable.baseToRebasedNodeId, baseId, newId);
|
|
681
749
|
return rebasedChange;
|
|
682
750
|
}
|
|
751
|
+
updateConstraints(rebasedFields, rebasedNodes, rebasedRoots, constraintState, revertConstraintState) {
|
|
752
|
+
this.updateConstraintsForFields(rebasedFields, fieldChangeHandler_js_1.NodeAttachState.Attached, fieldChangeHandler_js_1.NodeAttachState.Attached, constraintState, revertConstraintState, rebasedNodes);
|
|
753
|
+
for (const [_detachId, nodeId] of rebasedRoots.nodeChanges.entries()) {
|
|
754
|
+
// XXX: This is incorrect if the rebased changeset attaches the node.
|
|
755
|
+
// Efficiently computing whether the changeset attaches the node would require maintaining a mapping from node ID to attach ID.
|
|
756
|
+
const detachedInOutput = true;
|
|
757
|
+
this.updateConstraintsForNode(nodeId, fieldChangeHandler_js_1.NodeAttachState.Detached, detachedInOutput ? fieldChangeHandler_js_1.NodeAttachState.Detached : fieldChangeHandler_js_1.NodeAttachState.Attached, rebasedNodes, constraintState, revertConstraintState);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
683
760
|
updateConstraintsForFields(fields, parentInputAttachState, parentOutputAttachState, constraintState, revertConstraintState, nodes) {
|
|
684
761
|
for (const field of fields.values()) {
|
|
685
762
|
const handler = getChangeHandler(this.fieldKinds, field.fieldKind);
|
|
686
|
-
for (const [nodeId
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
: fieldChangeHandler_js_1.NodeAttachState.Attached;
|
|
691
|
-
const isOutputDetached = outputIndex === undefined;
|
|
763
|
+
for (const [nodeId] of handler.getNestedChanges(field.change)) {
|
|
764
|
+
// XXX: This is incorrect if the rebased changeset detaches this node.
|
|
765
|
+
// Efficiently computing whether the changeset detaches the node would require maintaining a mapping from node ID to detach ID.
|
|
766
|
+
const isOutputDetached = false;
|
|
692
767
|
const outputAttachState = parentOutputAttachState === fieldChangeHandler_js_1.NodeAttachState.Detached || isOutputDetached
|
|
693
768
|
? fieldChangeHandler_js_1.NodeAttachState.Detached
|
|
694
769
|
: fieldChangeHandler_js_1.NodeAttachState.Attached;
|
|
695
|
-
this.updateConstraintsForNode(nodeId,
|
|
770
|
+
this.updateConstraintsForNode(nodeId, parentInputAttachState, outputAttachState, nodes, constraintState, revertConstraintState);
|
|
696
771
|
}
|
|
697
772
|
}
|
|
698
773
|
}
|
|
699
774
|
updateConstraintsForNode(nodeId, inputAttachState, outputAttachState, nodes, constraintState, revertConstraintState) {
|
|
700
|
-
const node =
|
|
775
|
+
const node = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(nodes, nodeId) ?? (0, internal_1.fail)(0xb24 /* Unknown node ID */);
|
|
776
|
+
const updatedNode = { ...node };
|
|
777
|
+
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(nodes, nodeId, updatedNode);
|
|
701
778
|
if (node.nodeExistsConstraint !== undefined) {
|
|
702
779
|
const isNowViolated = inputAttachState === fieldChangeHandler_js_1.NodeAttachState.Detached;
|
|
703
780
|
if (node.nodeExistsConstraint.violated !== isNowViolated) {
|
|
704
|
-
|
|
781
|
+
updatedNode.nodeExistsConstraint = {
|
|
705
782
|
...node.nodeExistsConstraint,
|
|
706
783
|
violated: isNowViolated,
|
|
707
784
|
};
|
|
@@ -711,7 +788,7 @@ class ModularChangeFamily {
|
|
|
711
788
|
if (node.nodeExistsConstraintOnRevert !== undefined) {
|
|
712
789
|
const isNowViolated = outputAttachState === fieldChangeHandler_js_1.NodeAttachState.Detached;
|
|
713
790
|
if (node.nodeExistsConstraintOnRevert.violated !== isNowViolated) {
|
|
714
|
-
|
|
791
|
+
updatedNode.nodeExistsConstraintOnRevert = {
|
|
715
792
|
...node.nodeExistsConstraintOnRevert,
|
|
716
793
|
violated: isNowViolated,
|
|
717
794
|
};
|
|
@@ -722,35 +799,73 @@ class ModularChangeFamily {
|
|
|
722
799
|
this.updateConstraintsForFields(node.fieldChanges, inputAttachState, outputAttachState, constraintState, revertConstraintState, nodes);
|
|
723
800
|
}
|
|
724
801
|
}
|
|
725
|
-
pruneFieldMap(changeset, nodeMap) {
|
|
802
|
+
pruneFieldMap(changeset, parentId, nodeMap, nodeToParent, aliases, roots, fieldsWithRootMoves, fieldsToRootChanges) {
|
|
726
803
|
if (changeset === undefined) {
|
|
727
804
|
return undefined;
|
|
728
805
|
}
|
|
729
806
|
const prunedChangeset = new Map();
|
|
730
807
|
for (const [field, fieldChange] of changeset) {
|
|
731
808
|
const handler = getChangeHandler(this.fieldKinds, fieldChange.fieldKind);
|
|
732
|
-
const prunedFieldChangeset = handler.rebaser.prune(fieldChange.change, (nodeId) => this.pruneNodeChange(nodeId, nodeMap));
|
|
733
|
-
|
|
809
|
+
const prunedFieldChangeset = handler.rebaser.prune(fieldChange.change, (nodeId) => this.pruneNodeChange(nodeId, nodeMap, nodeToParent, aliases, roots, fieldsWithRootMoves, fieldsToRootChanges));
|
|
810
|
+
const fieldId = { nodeId: parentId, field };
|
|
811
|
+
const fieldIdKey = fieldIdKeyFromFieldId(fieldId);
|
|
812
|
+
const rootsWithChanges = fieldsToRootChanges.get(fieldIdKey) ?? [];
|
|
813
|
+
let hasRootWithNodeChange = false;
|
|
814
|
+
for (const rootId of rootsWithChanges) {
|
|
815
|
+
const nodeId = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(roots.nodeChanges, rootId) ?? (0, internal_1.fail)("No root change found");
|
|
816
|
+
const isRootChangeEmpty = this.pruneNodeChange(nodeId, nodeMap, nodeToParent, aliases, roots, fieldsWithRootMoves, fieldsToRootChanges) === undefined;
|
|
817
|
+
if (isRootChangeEmpty) {
|
|
818
|
+
roots.nodeChanges.delete([rootId.revision, rootId.localId]);
|
|
819
|
+
tryRemoveDetachLocation(roots, rootId, 1);
|
|
820
|
+
}
|
|
821
|
+
else {
|
|
822
|
+
hasRootWithNodeChange = true;
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
const hasRootChanges = hasRootWithNodeChange || fieldsWithRootMoves.get(fieldIdKey) === true;
|
|
826
|
+
if (!handler.isEmpty(prunedFieldChangeset) || hasRootChanges) {
|
|
734
827
|
prunedChangeset.set(field, { ...fieldChange, change: (0, index_js_3.brand)(prunedFieldChangeset) });
|
|
735
828
|
}
|
|
736
829
|
}
|
|
737
830
|
return prunedChangeset.size > 0 ? prunedChangeset : undefined;
|
|
738
831
|
}
|
|
739
|
-
|
|
740
|
-
const
|
|
832
|
+
pruneRoots(roots, nodeMap, nodeToParent, aliases, fieldsWithRootMoves, fieldsToRootChanges) {
|
|
833
|
+
const pruned = { ...roots, nodeChanges: (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)() };
|
|
834
|
+
for (const [rootIdKey, nodeId] of roots.nodeChanges.entries()) {
|
|
835
|
+
const rootId = { revision: rootIdKey[0], localId: rootIdKey[1] };
|
|
836
|
+
const hasDetachLocation = roots.detachLocations.getFirst(rootId, 1).value !== undefined;
|
|
837
|
+
// If the root has a detach location it should be pruned by recursion when pruning the field it was detached from.
|
|
838
|
+
const prunedId = hasDetachLocation
|
|
839
|
+
? nodeId
|
|
840
|
+
: this.pruneNodeChange(nodeId, nodeMap, nodeToParent, aliases, roots, fieldsWithRootMoves, fieldsToRootChanges);
|
|
841
|
+
if (prunedId !== undefined) {
|
|
842
|
+
pruned.nodeChanges.set(rootIdKey, prunedId);
|
|
843
|
+
}
|
|
844
|
+
tryRemoveDetachLocation(pruned, rootId, 1);
|
|
845
|
+
}
|
|
846
|
+
return pruned;
|
|
847
|
+
}
|
|
848
|
+
pruneNodeChange(nodeId, nodes, nodeToParent, aliases, roots, fieldsWithRootMoves, fieldsToRootChanges) {
|
|
849
|
+
const changeset = nodeChangeFromId(nodes, aliases, nodeId);
|
|
741
850
|
const prunedFields = changeset.fieldChanges === undefined
|
|
742
851
|
? undefined
|
|
743
|
-
: this.pruneFieldMap(changeset.fieldChanges,
|
|
852
|
+
: this.pruneFieldMap(changeset.fieldChanges, nodeId, nodes, nodeToParent, aliases, roots, fieldsWithRootMoves, fieldsToRootChanges);
|
|
744
853
|
const prunedChange = { ...changeset, fieldChanges: prunedFields };
|
|
745
854
|
if (prunedChange.fieldChanges === undefined) {
|
|
746
855
|
delete prunedChange.fieldChanges;
|
|
747
856
|
}
|
|
748
857
|
if (isEmptyNodeChangeset(prunedChange)) {
|
|
749
|
-
|
|
858
|
+
const nodeIdKey = [
|
|
859
|
+
nodeId.revision,
|
|
860
|
+
nodeId.localId,
|
|
861
|
+
];
|
|
862
|
+
// TODO: Shouldn't we also delete all aliases associated with this node?
|
|
863
|
+
nodes.delete(nodeIdKey);
|
|
864
|
+
nodeToParent.delete(nodeIdKey);
|
|
750
865
|
return undefined;
|
|
751
866
|
}
|
|
752
867
|
else {
|
|
753
|
-
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(
|
|
868
|
+
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(nodes, nodeId, prunedChange);
|
|
754
869
|
return nodeId;
|
|
755
870
|
}
|
|
756
871
|
}
|
|
@@ -767,12 +882,13 @@ class ModularChangeFamily {
|
|
|
767
882
|
changeRevision(change, replacer) {
|
|
768
883
|
const updatedFields = this.replaceFieldMapRevisions(change.fieldChanges, replacer);
|
|
769
884
|
const updatedNodes = replaceIdMapRevisions(change.nodeChanges, replacer, (nodeChangeset) => this.replaceNodeChangesetRevisions(nodeChangeset, replacer));
|
|
770
|
-
const updatedNodeToParent = replaceIdMapRevisions(change.nodeToParent, replacer, (
|
|
885
|
+
const updatedNodeToParent = replaceIdMapRevisions(change.nodeToParent, replacer, (location) => replaceNodeLocationRevision(normalizeNodeLocation(location, change.nodeAliases), replacer));
|
|
771
886
|
const updated = {
|
|
772
887
|
...change,
|
|
773
888
|
fieldChanges: updatedFields,
|
|
774
889
|
nodeChanges: updatedNodes,
|
|
775
890
|
nodeToParent: updatedNodeToParent,
|
|
891
|
+
rootNodes: replaceRootTableRevision(change.rootNodes, replacer, change.nodeAliases),
|
|
776
892
|
// We've updated all references to old node IDs, so we no longer need an alias table.
|
|
777
893
|
nodeAliases: (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
778
894
|
crossFieldKeys: replaceCrossFieldKeyTableRevisions(change.crossFieldKeys, replacer, change.nodeAliases),
|
|
@@ -805,7 +921,7 @@ class ModularChangeFamily {
|
|
|
805
921
|
return updatedFields;
|
|
806
922
|
}
|
|
807
923
|
makeCrossFieldKeyTable(fields, nodes) {
|
|
808
|
-
const keys = (0, modularChangeTypes_js_1.
|
|
924
|
+
const keys = (0, modularChangeTypes_js_1.newCrossFieldRangeTable)();
|
|
809
925
|
this.populateCrossFieldKeyTableForFieldMap(keys, fields, undefined);
|
|
810
926
|
nodes.forEachPair(([revision, localId], node) => {
|
|
811
927
|
if (node.fieldChanges !== undefined) {
|
|
@@ -825,49 +941,13 @@ class ModularChangeFamily {
|
|
|
825
941
|
}
|
|
826
942
|
}
|
|
827
943
|
}
|
|
828
|
-
buildEditor(mintRevisionTag, changeReceiver) {
|
|
829
|
-
return new ModularEditBuilder(this, this.fieldKinds, changeReceiver, this.codecOptions);
|
|
944
|
+
buildEditor(mintRevisionTag, changeReceiver, editorOptions) {
|
|
945
|
+
return new ModularEditBuilder(this, this.fieldKinds, changeReceiver, this.codecOptions, editorOptions);
|
|
830
946
|
}
|
|
831
947
|
createEmptyFieldChange(fieldKind) {
|
|
832
948
|
const emptyChange = getChangeHandler(this.fieldKinds, fieldKind).createEmpty();
|
|
833
949
|
return { fieldKind, change: (0, index_js_3.brand)(emptyChange) };
|
|
834
950
|
}
|
|
835
|
-
validateChangeset(change) {
|
|
836
|
-
let numNodes = this.validateFieldChanges(change, change.fieldChanges, undefined);
|
|
837
|
-
for (const [[revision, localId], node] of change.nodeChanges.entries()) {
|
|
838
|
-
if (node.fieldChanges === undefined) {
|
|
839
|
-
continue;
|
|
840
|
-
}
|
|
841
|
-
const nodeId = { revision, localId };
|
|
842
|
-
const numChildren = this.validateFieldChanges(change, node.fieldChanges, nodeId);
|
|
843
|
-
numNodes += numChildren;
|
|
844
|
-
}
|
|
845
|
-
(0, internal_1.assert)(numNodes === change.nodeChanges.size, 0xa4d /* Node table contains unparented nodes */);
|
|
846
|
-
}
|
|
847
|
-
/**
|
|
848
|
-
* Asserts that each child and cross field key in each field has a correct entry in
|
|
849
|
-
* `nodeToParent` or `crossFieldKeyTable`.
|
|
850
|
-
* @returns the number of children found.
|
|
851
|
-
*/
|
|
852
|
-
validateFieldChanges(change, fieldChanges, nodeParent) {
|
|
853
|
-
let numChildren = 0;
|
|
854
|
-
for (const [field, fieldChange] of fieldChanges.entries()) {
|
|
855
|
-
const fieldId = { nodeId: nodeParent, field };
|
|
856
|
-
const handler = getChangeHandler(this.fieldKinds, fieldChange.fieldKind);
|
|
857
|
-
for (const [child, _index] of handler.getNestedChanges(fieldChange.change)) {
|
|
858
|
-
const parentFieldId = getParentFieldId(change, child);
|
|
859
|
-
(0, internal_1.assert)(areEqualFieldIds(parentFieldId, fieldId), 0xa4e /* Inconsistent node parentage */);
|
|
860
|
-
numChildren += 1;
|
|
861
|
-
}
|
|
862
|
-
for (const keyRange of handler.getCrossFieldKeys(fieldChange.change)) {
|
|
863
|
-
const fields = getFieldsForCrossFieldKey(change, keyRange.key, keyRange.count);
|
|
864
|
-
(0, internal_1.assert)(fields.length === 1 &&
|
|
865
|
-
fields[0] !== undefined &&
|
|
866
|
-
areEqualFieldIds(fields[0], fieldId), 0xa4f /* Inconsistent cross field keys */);
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
return numChildren;
|
|
870
|
-
}
|
|
871
951
|
getEffectiveChange(change) {
|
|
872
952
|
if (hasConflicts(change)) {
|
|
873
953
|
return this.muteChange(change);
|
|
@@ -880,7 +960,8 @@ class ModularChangeFamily {
|
|
|
880
960
|
muteChange(change) {
|
|
881
961
|
const muted = {
|
|
882
962
|
...change,
|
|
883
|
-
|
|
963
|
+
rootNodes: muteRootChanges(change.rootNodes),
|
|
964
|
+
crossFieldKeys: (0, modularChangeTypes_js_1.newCrossFieldRangeTable)(),
|
|
884
965
|
fieldChanges: this.muteFieldChanges(change.fieldChanges),
|
|
885
966
|
nodeChanges: (0, index_js_3.brand)(change.nodeChanges.mapValues((v) => this.muteNodeChange(v))),
|
|
886
967
|
};
|
|
@@ -909,7 +990,7 @@ class ModularChangeFamily {
|
|
|
909
990
|
exports.ModularChangeFamily = ModularChangeFamily;
|
|
910
991
|
ModularChangeFamily.emptyChange = makeModularChangeset();
|
|
911
992
|
function replaceCrossFieldKeyTableRevisions(table, replacer, nodeAliases) {
|
|
912
|
-
const updated = (0, modularChangeTypes_js_1.
|
|
993
|
+
const updated = (0, modularChangeTypes_js_1.newCrossFieldRangeTable)();
|
|
913
994
|
for (const entry of table.entries()) {
|
|
914
995
|
const key = entry.start;
|
|
915
996
|
const updatedKey = replacer.getUpdatedAtomId(key, entry.length);
|
|
@@ -968,6 +1049,19 @@ function composeBuildsDestroysAndRefreshers(change1, change2) {
|
|
|
968
1049
|
}
|
|
969
1050
|
}
|
|
970
1051
|
}
|
|
1052
|
+
// It's possible to have a build and a refresher for the same root because an attach operation need not be performed in the same changeset as the corresponding build.
|
|
1053
|
+
if (change1.builds !== undefined && change2.refreshers !== undefined) {
|
|
1054
|
+
for (const [key, chunk] of change2.refreshers.entries()) {
|
|
1055
|
+
(0, internal_1.assert)(chunk.topLevelLength === 1, "Expected refresher chunk to have length 1");
|
|
1056
|
+
const match = change1.builds.getPairOrNextLower(key);
|
|
1057
|
+
if (match !== undefined) {
|
|
1058
|
+
const [buildKey, buildChunk] = match;
|
|
1059
|
+
if (buildKey[0] === key[0] && buildKey[1] + buildChunk.topLevelLength > key[1]) {
|
|
1060
|
+
allRefreshers.delete(key);
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
971
1065
|
return { allBuilds, allDestroys, allRefreshers };
|
|
972
1066
|
}
|
|
973
1067
|
function invertBuilds(builds) {
|
|
@@ -992,20 +1086,45 @@ function invertBuilds(builds) {
|
|
|
992
1086
|
* @param fieldKinds - The field kinds to delegate to.
|
|
993
1087
|
*/
|
|
994
1088
|
function* relevantRemovedRoots(change, fieldKinds) {
|
|
995
|
-
|
|
1089
|
+
const rootIds = (0, index_js_2.newChangeAtomIdRangeMap)();
|
|
1090
|
+
addAttachesToSet(change, rootIds);
|
|
1091
|
+
addRenamesToSet(change, rootIds);
|
|
1092
|
+
for (const [[revision, localId]] of change.rootNodes.nodeChanges.entries()) {
|
|
1093
|
+
rootIds.set({ revision, localId }, 1, true);
|
|
1094
|
+
}
|
|
1095
|
+
for (const entry of rootIds.entries()) {
|
|
1096
|
+
for (let offset = 0; offset < entry.length; offset++) {
|
|
1097
|
+
const detachId = (0, index_js_2.offsetChangeAtomId)(entry.start, offset);
|
|
1098
|
+
yield (0, index_js_2.makeDetachedNodeId)(detachId.revision, detachId.localId);
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
996
1101
|
}
|
|
997
1102
|
exports.relevantRemovedRoots = relevantRemovedRoots;
|
|
998
|
-
function
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1103
|
+
function addAttachesToSet(change, rootIds) {
|
|
1104
|
+
// This includes each attach which does not have a corresponding detach.
|
|
1105
|
+
for (const entry of change.crossFieldKeys.entries()) {
|
|
1106
|
+
if (entry.start.target !== crossFieldQueries_js_1.NodeMoveType.Attach) {
|
|
1107
|
+
continue;
|
|
1108
|
+
}
|
|
1109
|
+
for (const detachIdEntry of change.rootNodes.newToOldId.getAll2(entry.start, entry.length)) {
|
|
1110
|
+
const detachId = detachIdEntry.value ?? (0, index_js_2.offsetChangeAtomId)(entry.start, detachIdEntry.offset);
|
|
1111
|
+
for (const detachEntry of change.crossFieldKeys.getAll2({ ...detachId, target: crossFieldQueries_js_1.NodeMoveType.Detach }, detachIdEntry.length)) {
|
|
1112
|
+
if (detachEntry.value === undefined) {
|
|
1113
|
+
rootIds.set((0, index_js_2.offsetChangeAtomId)(detachId, detachEntry.offset), detachEntry.length, true);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1002
1117
|
}
|
|
1003
1118
|
}
|
|
1004
|
-
function
|
|
1005
|
-
const
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1119
|
+
function addRenamesToSet(change, rootIds) {
|
|
1120
|
+
for (const renameEntry of change.rootNodes.oldToNewId.entries()) {
|
|
1121
|
+
for (const detachEntry of change.crossFieldKeys.getAll2({ ...renameEntry.start, target: crossFieldQueries_js_1.NodeMoveType.Detach }, renameEntry.length)) {
|
|
1122
|
+
// We only want to include renames of nodes which are detached in the input context of the changeset.
|
|
1123
|
+
// So if there is a detach for the node, the rename is not relevant.
|
|
1124
|
+
if (detachEntry.value === undefined) {
|
|
1125
|
+
rootIds.set(renameEntry.start, renameEntry.length, true);
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1009
1128
|
}
|
|
1010
1129
|
}
|
|
1011
1130
|
/**
|
|
@@ -1051,13 +1170,15 @@ function updateRefreshers(change, getDetachedNode, removedRoots, requireRefreshe
|
|
|
1051
1170
|
refreshers.set([root.major, (0, index_js_3.brand)(root.minor)], node);
|
|
1052
1171
|
}
|
|
1053
1172
|
}
|
|
1054
|
-
const { fieldChanges, nodeChanges, nodeToParent, nodeAliases, crossFieldKeys, maxId, revisions, constraintViolationCount, constraintViolationCountOnRevert, builds, destroys, } = change;
|
|
1173
|
+
const { rebaseVersion, fieldChanges, nodeChanges, nodeToParent, nodeAliases, crossFieldKeys, maxId, revisions, constraintViolationCount, constraintViolationCountOnRevert, builds, destroys, rootNodes, } = change;
|
|
1055
1174
|
return makeModularChangeset({
|
|
1175
|
+
rebaseVersion,
|
|
1056
1176
|
fieldChanges,
|
|
1057
1177
|
nodeChanges,
|
|
1058
1178
|
nodeToParent,
|
|
1059
1179
|
nodeAliases,
|
|
1060
1180
|
crossFieldKeys,
|
|
1181
|
+
rootNodes,
|
|
1061
1182
|
maxId: maxId,
|
|
1062
1183
|
revisions,
|
|
1063
1184
|
constraintViolationCount,
|
|
@@ -1077,11 +1198,24 @@ exports.updateRefreshers = updateRefreshers;
|
|
|
1077
1198
|
function intoDelta(taggedChange, fieldKinds) {
|
|
1078
1199
|
const change = taggedChange.change;
|
|
1079
1200
|
const rootDelta = {};
|
|
1080
|
-
const global = [];
|
|
1081
|
-
const rename = [];
|
|
1082
1201
|
if (!hasConflicts(change)) {
|
|
1083
1202
|
// If there are no constraint violations, then tree changes apply.
|
|
1084
|
-
const fieldDeltas = intoDeltaImpl(change.fieldChanges, change.nodeChanges,
|
|
1203
|
+
const fieldDeltas = intoDeltaImpl(change.fieldChanges, change.nodeChanges, change.nodeAliases, fieldKinds);
|
|
1204
|
+
const global = [];
|
|
1205
|
+
for (const [[major, minor], nodeId] of change.rootNodes.nodeChanges.entries()) {
|
|
1206
|
+
global.push({
|
|
1207
|
+
id: { major, minor },
|
|
1208
|
+
fields: deltaFromNodeChange(nodeChangeFromId(change.nodeChanges, change.nodeAliases, nodeId), change.nodeChanges, change.nodeAliases, fieldKinds),
|
|
1209
|
+
});
|
|
1210
|
+
}
|
|
1211
|
+
const rename = [];
|
|
1212
|
+
for (const { start: oldId, value: newId, length, } of change.rootNodes.oldToNewId.entries()) {
|
|
1213
|
+
rename.push({
|
|
1214
|
+
count: length,
|
|
1215
|
+
oldId: (0, index_js_2.makeDetachedNodeId)(oldId.revision, oldId.localId),
|
|
1216
|
+
newId: (0, index_js_2.makeDetachedNodeId)(newId.revision, newId.localId),
|
|
1217
|
+
});
|
|
1218
|
+
}
|
|
1085
1219
|
if (fieldDeltas.size > 0) {
|
|
1086
1220
|
rootDelta.fields = fieldDeltas;
|
|
1087
1221
|
}
|
|
@@ -1128,28 +1262,22 @@ function copyDetachedNodes(detachedNodes) {
|
|
|
1128
1262
|
/**
|
|
1129
1263
|
* @param change - The change to convert into a delta.
|
|
1130
1264
|
*/
|
|
1131
|
-
function intoDeltaImpl(change, nodeChanges,
|
|
1265
|
+
function intoDeltaImpl(change, nodeChanges, nodeAliases, fieldKinds) {
|
|
1132
1266
|
const delta = new Map();
|
|
1133
1267
|
for (const [field, fieldChange] of change) {
|
|
1134
|
-
const
|
|
1135
|
-
const nodeChange = nodeChangeFromId(nodeChanges, childChange);
|
|
1136
|
-
return deltaFromNodeChange(nodeChange, nodeChanges,
|
|
1268
|
+
const fieldDelta = getChangeHandler(fieldKinds, fieldChange.fieldKind).intoDelta(fieldChange.change, (childChange) => {
|
|
1269
|
+
const nodeChange = nodeChangeFromId(nodeChanges, nodeAliases, childChange);
|
|
1270
|
+
return deltaFromNodeChange(nodeChange, nodeChanges, nodeAliases, fieldKinds);
|
|
1137
1271
|
});
|
|
1138
|
-
if (
|
|
1139
|
-
delta.set(field,
|
|
1140
|
-
}
|
|
1141
|
-
for (const c of fieldGlobal ?? []) {
|
|
1142
|
-
global.push(c);
|
|
1143
|
-
}
|
|
1144
|
-
for (const r of fieldRename ?? []) {
|
|
1145
|
-
rename.push(r);
|
|
1272
|
+
if (fieldDelta !== undefined && fieldDelta.marks.length > 0) {
|
|
1273
|
+
delta.set(field, fieldDelta);
|
|
1146
1274
|
}
|
|
1147
1275
|
}
|
|
1148
1276
|
return delta;
|
|
1149
1277
|
}
|
|
1150
|
-
function deltaFromNodeChange(change, nodeChanges,
|
|
1278
|
+
function deltaFromNodeChange(change, nodeChanges, nodeAliases, fieldKinds) {
|
|
1151
1279
|
if (change.fieldChanges !== undefined) {
|
|
1152
|
-
return intoDeltaImpl(change.fieldChanges, nodeChanges,
|
|
1280
|
+
return intoDeltaImpl(change.fieldChanges, nodeChanges, nodeAliases, fieldKinds);
|
|
1153
1281
|
}
|
|
1154
1282
|
// TODO: update the API to allow undefined to be returned here
|
|
1155
1283
|
return new Map();
|
|
@@ -1199,30 +1327,22 @@ function getChangeHandler(fieldKinds, kind) {
|
|
|
1199
1327
|
return getFieldKind(fieldKinds, kind).changeHandler;
|
|
1200
1328
|
}
|
|
1201
1329
|
exports.getChangeHandler = getChangeHandler;
|
|
1202
|
-
function newComposeTable(baseChange, newChange,
|
|
1330
|
+
function newComposeTable(baseChange, newChange, composedRootNodes, movedCrossFieldKeys, removedCrossFieldKeys, pendingCompositions) {
|
|
1203
1331
|
return {
|
|
1204
|
-
|
|
1332
|
+
rebaseVersion: Math.max(baseChange.rebaseVersion, newChange.rebaseVersion),
|
|
1333
|
+
entries: newDetachedEntryMap(),
|
|
1205
1334
|
baseChange,
|
|
1206
1335
|
newChange,
|
|
1207
1336
|
fieldToContext: new Map(),
|
|
1208
1337
|
newFieldToBaseField: new Map(),
|
|
1209
1338
|
newToBaseNodeId: (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
1210
1339
|
composedNodes: new Set(),
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
};
|
|
1218
|
-
}
|
|
1219
|
-
function newCrossFieldTable() {
|
|
1220
|
-
return {
|
|
1221
|
-
srcTable: (0, index_js_2.newChangeAtomIdRangeMap)(),
|
|
1222
|
-
dstTable: (0, index_js_2.newChangeAtomIdRangeMap)(),
|
|
1223
|
-
srcDependents: (0, index_js_2.newChangeAtomIdRangeMap)(),
|
|
1224
|
-
dstDependents: (0, index_js_2.newChangeAtomIdRangeMap)(),
|
|
1225
|
-
invalidatedFields: new Set(),
|
|
1340
|
+
movedNodeToParent: (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
1341
|
+
composedRootNodes,
|
|
1342
|
+
movedCrossFieldKeys,
|
|
1343
|
+
removedCrossFieldKeys,
|
|
1344
|
+
renamesToDelete: (0, index_js_2.newChangeAtomIdRangeMap)(),
|
|
1345
|
+
pendingCompositions,
|
|
1226
1346
|
};
|
|
1227
1347
|
}
|
|
1228
1348
|
function newConstraintState(violationCount) {
|
|
@@ -1230,146 +1350,348 @@ function newConstraintState(violationCount) {
|
|
|
1230
1350
|
violationCount,
|
|
1231
1351
|
};
|
|
1232
1352
|
}
|
|
1233
|
-
class
|
|
1234
|
-
constructor(
|
|
1235
|
-
this.
|
|
1236
|
-
this.
|
|
1237
|
-
this.allowInval = allowInval;
|
|
1353
|
+
class InvertNodeManagerI {
|
|
1354
|
+
constructor(table, fieldId) {
|
|
1355
|
+
this.table = table;
|
|
1356
|
+
this.fieldId = fieldId;
|
|
1238
1357
|
}
|
|
1239
|
-
|
|
1240
|
-
if (
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1358
|
+
invertDetach(detachId, count, nodeChange, newAttachId) {
|
|
1359
|
+
if (nodeChange !== undefined) {
|
|
1360
|
+
(0, internal_1.assert)(count === 1, "A node change should only affect one node");
|
|
1361
|
+
const attachEntry = firstAttachIdFromDetachId(this.table.change.rootNodes, detachId, count);
|
|
1362
|
+
const attachFieldEntry = this.table.change.crossFieldKeys.getFirst({ target: crossFieldQueries_js_1.NodeMoveType.Attach, ...attachEntry.value }, count);
|
|
1363
|
+
if (attachFieldEntry.value === undefined) {
|
|
1364
|
+
assignRootChange(this.table.invertedRoots, this.table.invertedNodeToParent, attachEntry.value, nodeChange, this.fieldId, this.table.change.rebaseVersion);
|
|
1365
|
+
}
|
|
1366
|
+
else {
|
|
1367
|
+
(0, crossFieldQueries_js_1.setInCrossFieldMap)(this.table.entries, attachEntry.value, count, nodeChange);
|
|
1368
|
+
this.table.invalidatedFields.add(fieldChangeFromId(this.table.change, attachFieldEntry.value));
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
if (!(0, index_js_2.areEqualChangeAtomIds)(detachId, newAttachId)) {
|
|
1372
|
+
for (const entry of doesChangeAttachNodes(this.table.change.crossFieldKeys, detachId, count)) {
|
|
1373
|
+
if (!entry.value) {
|
|
1374
|
+
this.table.attachToDetachId.set(newAttachId, count, detachId);
|
|
1375
|
+
this.table.invertedRoots.detachLocations.set(detachId, count, this.fieldId);
|
|
1247
1376
|
}
|
|
1248
|
-
firstId = (0, index_js_3.brand)(firstId + dependentEntry.length);
|
|
1249
1377
|
}
|
|
1250
1378
|
}
|
|
1251
|
-
(0, crossFieldQueries_js_1.setInCrossFieldMap)(this.getMap(target), revision, id, count, newValue);
|
|
1252
1379
|
}
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1380
|
+
invertAttach(attachId, count) {
|
|
1381
|
+
let countToProcess = count;
|
|
1382
|
+
const detachIdEntry = firstDetachIdFromAttachId(this.table.change.rootNodes, attachId, countToProcess);
|
|
1383
|
+
countToProcess = detachIdEntry.length;
|
|
1384
|
+
const detachEntry = getFirstFieldForCrossFieldKey(this.table.change, { target: crossFieldQueries_js_1.NodeMoveType.Detach, ...detachIdEntry.value }, countToProcess);
|
|
1385
|
+
countToProcess = detachEntry.length;
|
|
1386
|
+
let result;
|
|
1387
|
+
if (detachEntry.value === undefined) {
|
|
1388
|
+
// This node is detached in the input context of the original change.
|
|
1389
|
+
const nodeIdEntry = (0, changeAtomIdBTree_js_1.rangeQueryChangeAtomIdMap)(this.table.change.rootNodes.nodeChanges, detachIdEntry.value, countToProcess);
|
|
1390
|
+
countToProcess = nodeIdEntry.length;
|
|
1391
|
+
const detachLocationEntry = this.table.change.rootNodes.detachLocations.getFirst(detachIdEntry.value, countToProcess);
|
|
1392
|
+
countToProcess = detachLocationEntry.length;
|
|
1393
|
+
if (this.table.isRollback &&
|
|
1394
|
+
detachLocationEntry.value !== undefined &&
|
|
1395
|
+
!areEqualFieldIds(normalizeFieldId(detachLocationEntry.value, this.table.change.nodeAliases), this.fieldId)) {
|
|
1396
|
+
// These nodes are detached in the input context of the original change,
|
|
1397
|
+
// and the change attaches these nodes in a different location from their detach location.
|
|
1398
|
+
// The rollback change should send them back to that prior detach location.
|
|
1399
|
+
this.table.invertedRoots.outputDetachLocations.set(detachIdEntry.value, countToProcess, detachLocationEntry.value);
|
|
1400
|
+
}
|
|
1401
|
+
result = {
|
|
1402
|
+
value: {
|
|
1403
|
+
nodeChange: nodeIdEntry.value,
|
|
1404
|
+
detachId: detachIdEntry.value,
|
|
1405
|
+
},
|
|
1406
|
+
length: countToProcess,
|
|
1407
|
+
};
|
|
1259
1408
|
}
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
: this.crossFieldTable.dstDependents;
|
|
1271
|
-
}
|
|
1272
|
-
}
|
|
1273
|
-
class InvertManager extends CrossFieldManagerI {
|
|
1274
|
-
constructor(table, field, fieldId, allowInval = true) {
|
|
1275
|
-
super(table, field, allowInval);
|
|
1276
|
-
this.fieldId = fieldId;
|
|
1277
|
-
}
|
|
1278
|
-
onMoveIn(id) {
|
|
1279
|
-
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(this.table.invertedNodeToParent, id, this.fieldId);
|
|
1280
|
-
}
|
|
1281
|
-
moveKey(target, revision, id, count) {
|
|
1282
|
-
(0, internal_1.assert)(false, 0x9c5 /* Keys should not be moved manually during invert */);
|
|
1283
|
-
}
|
|
1284
|
-
get table() {
|
|
1285
|
-
return this.crossFieldTable;
|
|
1409
|
+
else {
|
|
1410
|
+
const moveEntry = this.table.entries.getFirst(attachId, countToProcess);
|
|
1411
|
+
result = { ...moveEntry, value: { nodeChange: moveEntry.value } };
|
|
1412
|
+
}
|
|
1413
|
+
if (result.value?.nodeChange !== undefined) {
|
|
1414
|
+
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(this.table.invertedNodeToParent, result.value.nodeChange, {
|
|
1415
|
+
field: this.fieldId,
|
|
1416
|
+
});
|
|
1417
|
+
}
|
|
1418
|
+
return result;
|
|
1286
1419
|
}
|
|
1287
1420
|
}
|
|
1288
|
-
class
|
|
1289
|
-
constructor(table,
|
|
1290
|
-
|
|
1421
|
+
class RebaseNodeManagerI {
|
|
1422
|
+
constructor(table, fieldId, allowInval = true) {
|
|
1423
|
+
this.table = table;
|
|
1291
1424
|
this.fieldId = fieldId;
|
|
1425
|
+
this.allowInval = allowInval;
|
|
1292
1426
|
}
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1427
|
+
getNewChangesForBaseAttach(baseAttachId, count) {
|
|
1428
|
+
let countToProcess = count;
|
|
1429
|
+
const detachEntry = firstDetachIdFromAttachId(this.table.baseChange.rootNodes, baseAttachId, countToProcess);
|
|
1430
|
+
countToProcess = detachEntry.length;
|
|
1431
|
+
const nodeEntry = (0, changeAtomIdBTree_js_1.rangeQueryChangeAtomIdMap)(this.table.newChange.rootNodes.nodeChanges, detachEntry.value, countToProcess);
|
|
1432
|
+
countToProcess = nodeEntry.length;
|
|
1433
|
+
const newNodeId = nodeEntry.value;
|
|
1434
|
+
const newRenameEntry = this.table.newChange.rootNodes.oldToNewId.getFirst(detachEntry.value, countToProcess);
|
|
1435
|
+
countToProcess = newRenameEntry.length;
|
|
1436
|
+
let result;
|
|
1437
|
+
// eslint-disable-next-line unicorn/prefer-ternary
|
|
1438
|
+
if (newNodeId !== undefined || newRenameEntry.value !== undefined) {
|
|
1439
|
+
result = {
|
|
1440
|
+
...newRenameEntry,
|
|
1441
|
+
value: { detachId: newRenameEntry.value, nodeChange: newNodeId },
|
|
1442
|
+
};
|
|
1443
|
+
}
|
|
1444
|
+
else {
|
|
1445
|
+
// This handles the case where the base changeset has moved these nodes,
|
|
1446
|
+
// meaning they were attached in the input context of the base changeset.
|
|
1447
|
+
result = this.table.entries.getFirst(baseAttachId, countToProcess);
|
|
1448
|
+
}
|
|
1449
|
+
// TODO: Consider moving these two checks into a separate method so that this function has no side effects.
|
|
1450
|
+
if (result.value?.detachId !== undefined) {
|
|
1451
|
+
this.table.rebasedDetachLocations.set(result.value.detachId, result.length, this.fieldId);
|
|
1452
|
+
}
|
|
1453
|
+
if (result.value?.nodeChange !== undefined) {
|
|
1454
|
+
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(this.table.rebasedNodeToParent, result.value.nodeChange, {
|
|
1455
|
+
field: this.fieldId,
|
|
1456
|
+
});
|
|
1457
|
+
}
|
|
1458
|
+
return result;
|
|
1459
|
+
}
|
|
1460
|
+
rebaseOverDetach(baseDetachId, count, newDetachId, nodeChange, cellRename) {
|
|
1461
|
+
let countToProcess = count;
|
|
1462
|
+
const attachIdEntry = firstAttachIdFromDetachId(this.table.baseRoots, baseDetachId, countToProcess);
|
|
1463
|
+
const baseAttachId = attachIdEntry.value;
|
|
1464
|
+
countToProcess = attachIdEntry.length;
|
|
1465
|
+
const attachFieldEntry = getFirstFieldForCrossFieldKey(this.table.baseChange, { ...baseAttachId, target: crossFieldQueries_js_1.NodeMoveType.Attach }, countToProcess);
|
|
1466
|
+
countToProcess = attachFieldEntry.length;
|
|
1467
|
+
const detachedMoveEntry = this.table.baseChange.rootNodes.outputDetachLocations.getFirst(baseDetachId, countToProcess);
|
|
1468
|
+
countToProcess = detachedMoveEntry.length;
|
|
1469
|
+
const destinationField = attachFieldEntry.value ?? detachedMoveEntry.value;
|
|
1470
|
+
if (destinationField !== undefined) {
|
|
1471
|
+
// The base detach is part of a move (or move of detach location) in the base changeset.
|
|
1472
|
+
(0, crossFieldQueries_js_1.setInCrossFieldMap)(this.table.entries, baseAttachId, countToProcess, {
|
|
1473
|
+
nodeChange,
|
|
1474
|
+
detachId: newDetachId,
|
|
1475
|
+
cellRename,
|
|
1476
|
+
});
|
|
1477
|
+
if (nodeChange !== undefined || newDetachId !== undefined) {
|
|
1478
|
+
this.invalidateBaseFields([destinationField]);
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
if (attachFieldEntry.value === undefined) {
|
|
1482
|
+
// These nodes are detached in the output context of the base changeset.
|
|
1483
|
+
if (nodeChange !== undefined) {
|
|
1484
|
+
assignRootChange(this.table.rebasedRootNodes, this.table.rebasedNodeToParent, baseAttachId, nodeChange, this.fieldId, this.table.rebaseVersion);
|
|
1485
|
+
}
|
|
1486
|
+
if (newDetachId !== undefined) {
|
|
1487
|
+
addNodeRename(this.table.rebasedRootNodes, baseAttachId, newDetachId, countToProcess, this.fieldId);
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
if (newDetachId !== undefined) {
|
|
1491
|
+
this.table.movedDetaches.set(newDetachId, countToProcess, true);
|
|
1492
|
+
}
|
|
1493
|
+
if (countToProcess < count) {
|
|
1494
|
+
const remainingCount = count - countToProcess;
|
|
1495
|
+
const nextDetachId = newDetachId === undefined
|
|
1496
|
+
? undefined
|
|
1497
|
+
: (0, index_js_2.offsetChangeAtomId)(newDetachId, countToProcess);
|
|
1498
|
+
this.rebaseOverDetach((0, index_js_2.offsetChangeAtomId)(baseDetachId, countToProcess), remainingCount, nextDetachId, nodeChange);
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
addDetach(id, count) {
|
|
1502
|
+
this.table.rebasedDetachLocations.set(id, count, this.fieldId);
|
|
1503
|
+
}
|
|
1504
|
+
removeDetach(id, count) {
|
|
1505
|
+
this.table.movedDetaches.set(id, count, true);
|
|
1506
|
+
}
|
|
1507
|
+
doesBaseAttachNodes(id, count) {
|
|
1508
|
+
let countToProcess = count;
|
|
1509
|
+
const attachEntry = getFirstAttachField(this.table.baseChange.crossFieldKeys, id, countToProcess);
|
|
1510
|
+
countToProcess = attachEntry.length;
|
|
1511
|
+
return { start: id, value: attachEntry.value !== undefined, length: countToProcess };
|
|
1512
|
+
}
|
|
1513
|
+
getBaseRename(id, count) {
|
|
1514
|
+
return this.table.baseChange.rootNodes.oldToNewId.getFirst(id, count);
|
|
1515
|
+
}
|
|
1516
|
+
getNewRenameForBaseRename(baseRenameTo, count) {
|
|
1517
|
+
let countToProcess = count;
|
|
1518
|
+
const inputEntry = firstDetachIdFromAttachId(this.table.baseChange.rootNodes, baseRenameTo, countToProcess);
|
|
1519
|
+
const attachEntry = getFirstAttachField(this.table.baseChange.crossFieldKeys, baseRenameTo, countToProcess);
|
|
1520
|
+
countToProcess = attachEntry.length;
|
|
1521
|
+
if (attachEntry.value !== undefined) {
|
|
1522
|
+
// These nodes are attached in the output context of the base changeset.
|
|
1523
|
+
return { value: undefined, length: countToProcess };
|
|
1524
|
+
}
|
|
1525
|
+
countToProcess = inputEntry.length;
|
|
1526
|
+
const inputId = inputEntry.value;
|
|
1527
|
+
const moveEntry = this.table.entries.getFirst(inputId, countToProcess);
|
|
1528
|
+
countToProcess = moveEntry.length;
|
|
1529
|
+
if (moveEntry.value !== undefined) {
|
|
1530
|
+
return { ...moveEntry, value: moveEntry.value.cellRename ?? moveEntry.value.detachId };
|
|
1531
|
+
}
|
|
1532
|
+
return this.table.newChange.rootNodes.oldToNewId.getFirst(inputId, countToProcess);
|
|
1533
|
+
}
|
|
1534
|
+
invalidateBaseFields(fields) {
|
|
1535
|
+
if (this.allowInval) {
|
|
1536
|
+
for (const fieldId of fields) {
|
|
1537
|
+
this.table.affectedBaseFields.set(fieldIdKeyFromFieldId(fieldId), true);
|
|
1309
1538
|
}
|
|
1310
1539
|
}
|
|
1311
|
-
super.set(target, revision, id, count, newValue, invalidateDependents);
|
|
1312
|
-
}
|
|
1313
|
-
onMoveIn(id) {
|
|
1314
|
-
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(this.table.rebasedNodeToParent, id, this.fieldId);
|
|
1315
|
-
}
|
|
1316
|
-
moveKey(target, revision, id, count) {
|
|
1317
|
-
this.table.rebasedCrossFieldKeys.set({ target, revision, localId: id }, count, this.fieldId);
|
|
1318
|
-
}
|
|
1319
|
-
get table() {
|
|
1320
|
-
return this.crossFieldTable;
|
|
1321
1540
|
}
|
|
1322
1541
|
}
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1542
|
+
function assignRootChange(table, nodeToParent, detachId, nodeId, detachLocation, rebaseVersion) {
|
|
1543
|
+
(0, internal_1.assert)(rebaseVersion >= 2 || detachLocation !== undefined, "All root changes need a detach location to support compatibility with older client versions");
|
|
1544
|
+
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(table.nodeChanges, detachId, nodeId);
|
|
1545
|
+
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(nodeToParent, nodeId, { root: detachId });
|
|
1546
|
+
table.detachLocations.set(detachId, 1, detachLocation);
|
|
1547
|
+
}
|
|
1548
|
+
class ComposeNodeManagerI {
|
|
1549
|
+
constructor(table, fieldId, allowInval = true) {
|
|
1550
|
+
this.table = table;
|
|
1327
1551
|
this.fieldId = fieldId;
|
|
1552
|
+
this.allowInval = allowInval;
|
|
1328
1553
|
}
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1554
|
+
getNewChangesForBaseDetach(baseDetachId, count) {
|
|
1555
|
+
let countToProcess = count;
|
|
1556
|
+
const baseAttachEntry = getFirstFieldForCrossFieldKey(this.table.baseChange, { target: crossFieldQueries_js_1.NodeMoveType.Attach, ...baseDetachId }, countToProcess);
|
|
1557
|
+
countToProcess = baseAttachEntry.length;
|
|
1558
|
+
let result;
|
|
1559
|
+
if (baseAttachEntry.value === undefined) {
|
|
1560
|
+
// The detached nodes are still detached in the new change's input context.
|
|
1561
|
+
const rootEntry = (0, changeAtomIdBTree_js_1.rangeQueryChangeAtomIdMap)(this.table.newChange.rootNodes.nodeChanges, baseDetachId, countToProcess);
|
|
1562
|
+
countToProcess = rootEntry.length;
|
|
1563
|
+
const newRenameEntry = this.table.newChange.rootNodes.oldToNewId.getFirst(baseDetachId, countToProcess);
|
|
1564
|
+
countToProcess = newRenameEntry.length;
|
|
1565
|
+
result = {
|
|
1566
|
+
value: { nodeChange: rootEntry.value, detachId: newRenameEntry.value },
|
|
1567
|
+
length: countToProcess,
|
|
1568
|
+
};
|
|
1569
|
+
}
|
|
1570
|
+
else {
|
|
1571
|
+
// The base detach was part of a move.
|
|
1572
|
+
// We check if we've previously seen a node change at the move destination.
|
|
1573
|
+
const entry = this.table.entries.getFirst(baseDetachId, countToProcess);
|
|
1574
|
+
result = { value: entry.value, length: entry.length };
|
|
1575
|
+
}
|
|
1576
|
+
// TODO: Consider moving this to a separate method so that this method can be side-effect free.
|
|
1577
|
+
if (result.value?.nodeChange !== undefined) {
|
|
1578
|
+
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(this.table.movedNodeToParent, result.value.nodeChange, {
|
|
1579
|
+
field: this.fieldId,
|
|
1580
|
+
});
|
|
1581
|
+
}
|
|
1582
|
+
return result;
|
|
1583
|
+
}
|
|
1584
|
+
composeAttachDetach(baseAttachId, newDetachId, count) {
|
|
1585
|
+
let countToProcess = count;
|
|
1586
|
+
const newAttachEntry = getFirstAttachField(this.table.newChange.crossFieldKeys, newDetachId, countToProcess);
|
|
1587
|
+
countToProcess = newAttachEntry.length;
|
|
1588
|
+
// Both changes can have the same ID if they came from inverse changesets.
|
|
1589
|
+
// If the new detach is part of a move,
|
|
1590
|
+
// then both input changesets contain the attach cross-field key for this ID.
|
|
1591
|
+
// The new attach may still exist in the composed changeset so we do not remove it here.
|
|
1592
|
+
// The new attach will typically cancel with a base detach,
|
|
1593
|
+
// in which case the cross-field key will be removed in `composeDetachAttach`.
|
|
1594
|
+
const hasNewAttachWithBaseAttachId = (0, index_js_2.areEqualChangeAtomIds)(baseAttachId, newDetachId) && newAttachEntry.value !== undefined;
|
|
1595
|
+
if (!hasNewAttachWithBaseAttachId) {
|
|
1596
|
+
this.table.removedCrossFieldKeys.set({ ...baseAttachId, target: crossFieldQueries_js_1.NodeMoveType.Attach }, countToProcess, true);
|
|
1597
|
+
}
|
|
1598
|
+
const baseDetachEntry = getFirstDetachField(this.table.baseChange.crossFieldKeys, baseAttachId, countToProcess);
|
|
1599
|
+
countToProcess = baseDetachEntry.length;
|
|
1600
|
+
const baseRootIdEntry = firstDetachIdFromAttachId(this.table.baseChange.rootNodes, baseAttachId, countToProcess);
|
|
1601
|
+
countToProcess = baseRootIdEntry.length;
|
|
1602
|
+
const baseDetachId = baseRootIdEntry.value;
|
|
1603
|
+
if (baseDetachEntry.value === undefined) {
|
|
1604
|
+
const baseDetachLocationEntry = this.table.baseChange.rootNodes.detachLocations.getFirst(baseDetachId, countToProcess);
|
|
1605
|
+
countToProcess = baseDetachLocationEntry.length;
|
|
1606
|
+
// These nodes were detached in the base change's input context,
|
|
1607
|
+
// so the net effect of the two changes is a rename.
|
|
1608
|
+
appendNodeRename(this.table.composedRootNodes, baseAttachId, newDetachId, baseDetachEntry.length, this.table.baseChange.rootNodes, baseDetachLocationEntry.value ?? this.fieldId);
|
|
1609
|
+
this.table.removedCrossFieldKeys.set({ ...newDetachId, target: crossFieldQueries_js_1.NodeMoveType.Detach }, countToProcess, true);
|
|
1610
|
+
}
|
|
1611
|
+
else {
|
|
1612
|
+
// The base change moves these nodes.
|
|
1613
|
+
const prevEntry = this.table.entries.getFirst(baseAttachId, baseDetachEntry.length).value ?? {};
|
|
1614
|
+
this.table.entries.set(baseAttachId, baseDetachEntry.length, {
|
|
1615
|
+
...prevEntry,
|
|
1616
|
+
detachId: newDetachId,
|
|
1617
|
+
});
|
|
1618
|
+
// The new detach will replace the base detach, so we remove the key for the base detach, unless they have the same ID.
|
|
1619
|
+
if (!(0, index_js_2.areEqualChangeAtomIds)(baseAttachId, newDetachId)) {
|
|
1620
|
+
this.table.removedCrossFieldKeys.set({ ...baseAttachId, target: crossFieldQueries_js_1.NodeMoveType.Detach }, countToProcess, true);
|
|
1621
|
+
}
|
|
1622
|
+
this.table.movedCrossFieldKeys.set({ ...newDetachId, target: crossFieldQueries_js_1.NodeMoveType.Detach }, countToProcess, baseDetachEntry.value);
|
|
1623
|
+
this.invalidateBaseFields([baseDetachEntry.value]);
|
|
1624
|
+
}
|
|
1625
|
+
if (newAttachEntry.value === undefined) {
|
|
1626
|
+
const newOutputDetachLocationEntry = this.table.newChange.rootNodes.outputDetachLocations.getFirst(newDetachId, countToProcess);
|
|
1627
|
+
countToProcess = newOutputDetachLocationEntry.length;
|
|
1628
|
+
this.table.composedRootNodes.outputDetachLocations.set(newDetachId, countToProcess, newOutputDetachLocationEntry.value ?? this.fieldId);
|
|
1629
|
+
}
|
|
1630
|
+
if (countToProcess < count) {
|
|
1631
|
+
const remainingCount = count - countToProcess;
|
|
1632
|
+
this.composeAttachDetach((0, index_js_2.offsetChangeAtomId)(baseAttachId, countToProcess), (0, index_js_2.offsetChangeAtomId)(newDetachId, countToProcess), remainingCount);
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
sendNewChangesToBaseSourceLocation(baseAttachId, newChanges) {
|
|
1636
|
+
const { value: baseDetachId } = firstDetachIdFromAttachId(this.table.baseChange.rootNodes, baseAttachId, 1);
|
|
1637
|
+
const detachFields = getFieldsForCrossFieldKey(this.table.baseChange, {
|
|
1638
|
+
...baseDetachId,
|
|
1639
|
+
target: crossFieldQueries_js_1.NodeMoveType.Detach,
|
|
1640
|
+
}, 1);
|
|
1641
|
+
if (detachFields.length > 0) {
|
|
1642
|
+
// The base attach is part of a move in the base changeset.
|
|
1643
|
+
const prevEntry = this.table.entries.getFirst(baseDetachId, 1).value ?? {};
|
|
1644
|
+
this.table.entries.set(baseDetachId, 1, { ...prevEntry, nodeChange: newChanges });
|
|
1645
|
+
if (newChanges !== undefined) {
|
|
1646
|
+
this.invalidateBaseFields(detachFields);
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
else {
|
|
1650
|
+
const baseNodeId = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(this.table.baseChange.rootNodes.nodeChanges, baseDetachId);
|
|
1651
|
+
if (baseNodeId === undefined) {
|
|
1652
|
+
assignRootChange(this.table.composedRootNodes, this.table.movedNodeToParent, baseDetachId, newChanges, this.fieldId, this.table.rebaseVersion);
|
|
1340
1653
|
}
|
|
1341
1654
|
else {
|
|
1342
|
-
|
|
1343
|
-
target,
|
|
1344
|
-
revision,
|
|
1345
|
-
localId: id,
|
|
1346
|
-
}, count);
|
|
1347
|
-
(0, internal_1.assert)(baseFieldIds.length > 0, 0x9c8 /* Cross field key not registered in base or new change */);
|
|
1348
|
-
for (const baseFieldId of baseFieldIds) {
|
|
1349
|
-
this.table.pendingCompositions.affectedBaseFields.set([baseFieldId.nodeId?.revision, baseFieldId.nodeId?.localId, baseFieldId.field], true);
|
|
1350
|
-
}
|
|
1655
|
+
addNodesToCompose(this.table, baseNodeId, newChanges);
|
|
1351
1656
|
}
|
|
1352
1657
|
}
|
|
1353
|
-
super.set(target, revision, id, count, newValue, invalidateDependents);
|
|
1354
1658
|
}
|
|
1355
|
-
|
|
1356
|
-
(
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1659
|
+
composeDetachAttach(baseDetachId, newAttachId, count, composeToPin) {
|
|
1660
|
+
if (composeToPin) {
|
|
1661
|
+
this.table.movedCrossFieldKeys.set({ target: crossFieldQueries_js_1.NodeMoveType.Detach, ...newAttachId }, count, this.fieldId);
|
|
1662
|
+
if (!(0, index_js_2.areEqualChangeAtomIds)(baseDetachId, newAttachId)) {
|
|
1663
|
+
// The pin will have `newAttachId` as both its detach and attach ID.
|
|
1664
|
+
// So we remove `baseDetachId` unless that is equal to the pin's detach ID.
|
|
1665
|
+
this.table.removedCrossFieldKeys.set({ target: crossFieldQueries_js_1.NodeMoveType.Detach, ...baseDetachId }, count, true);
|
|
1666
|
+
}
|
|
1667
|
+
// Note that while change2 should already have this key, change1 may have a rollback for the same ID in a different location.
|
|
1668
|
+
// In that case, change1's attach should be canceled out by a detach from change2.
|
|
1669
|
+
// Here we make sure that the composed change has the correct location (this field) for the attach ID.
|
|
1670
|
+
this.table.movedCrossFieldKeys.set({ target: crossFieldQueries_js_1.NodeMoveType.Attach, ...newAttachId }, count, this.fieldId);
|
|
1671
|
+
}
|
|
1672
|
+
else {
|
|
1673
|
+
this.table.removedCrossFieldKeys.set({ target: crossFieldQueries_js_1.NodeMoveType.Detach, ...baseDetachId }, count, true);
|
|
1674
|
+
this.table.removedCrossFieldKeys.set({ target: crossFieldQueries_js_1.NodeMoveType.Attach, ...newAttachId }, count, true);
|
|
1675
|
+
}
|
|
1360
1676
|
}
|
|
1361
|
-
|
|
1362
|
-
|
|
1677
|
+
invalidateBaseFields(fields) {
|
|
1678
|
+
if (this.allowInval) {
|
|
1679
|
+
for (const fieldId of fields) {
|
|
1680
|
+
this.table.pendingCompositions.affectedBaseFields.set(fieldIdKeyFromFieldId(fieldId), true);
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1363
1683
|
}
|
|
1364
1684
|
}
|
|
1365
1685
|
function makeModularChangeset(props) {
|
|
1366
|
-
const p = props ?? { maxId: -1 };
|
|
1686
|
+
const p = props ?? { maxId: -1, rebaseVersion: 1 };
|
|
1367
1687
|
const changeset = {
|
|
1688
|
+
rebaseVersion: p.rebaseVersion,
|
|
1368
1689
|
fieldChanges: p.fieldChanges ?? new Map(),
|
|
1369
1690
|
nodeChanges: p.nodeChanges ?? (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
1691
|
+
rootNodes: p.rootNodes ?? newRootTable(),
|
|
1370
1692
|
nodeToParent: p.nodeToParent ?? (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
1371
1693
|
nodeAliases: p.nodeAliases ?? (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
1372
|
-
crossFieldKeys: p.crossFieldKeys ?? (0, modularChangeTypes_js_1.
|
|
1694
|
+
crossFieldKeys: p.crossFieldKeys ?? (0, modularChangeTypes_js_1.newCrossFieldRangeTable)(),
|
|
1373
1695
|
};
|
|
1374
1696
|
if (p.revisions !== undefined && p.revisions.length > 0) {
|
|
1375
1697
|
changeset.revisions = p.revisions;
|
|
@@ -1402,12 +1724,19 @@ function makeModularChangeset(props) {
|
|
|
1402
1724
|
return changeset;
|
|
1403
1725
|
}
|
|
1404
1726
|
class ModularEditBuilder extends index_js_2.EditBuilder {
|
|
1405
|
-
constructor(family, fieldKinds, changeReceiver, codecOptions) {
|
|
1727
|
+
constructor(family, fieldKinds, changeReceiver, codecOptions, editorOptions) {
|
|
1406
1728
|
super(family, changeReceiver);
|
|
1407
1729
|
this.fieldKinds = fieldKinds;
|
|
1408
1730
|
this.transactionDepth = 0;
|
|
1409
1731
|
this.idAllocator = (0, index_js_3.idAllocatorFromMaxId)();
|
|
1410
1732
|
this.codecOptions = codecOptions;
|
|
1733
|
+
// TODO: make this dependent on the CodecWriteOptions once there is an FF version that supports RebaseVersion 2
|
|
1734
|
+
this.rebaseVersion =
|
|
1735
|
+
editorOptions?.rebaseVersionOverride ??
|
|
1736
|
+
(editorOptions?.enableDetachedRootEditing === true ? 2 : 1);
|
|
1737
|
+
}
|
|
1738
|
+
isInTransaction() {
|
|
1739
|
+
return this.transactionDepth > 0;
|
|
1411
1740
|
}
|
|
1412
1741
|
enterTransaction() {
|
|
1413
1742
|
this.transactionDepth += 1;
|
|
@@ -1455,11 +1784,13 @@ class ModularEditBuilder extends index_js_2.EditBuilder {
|
|
|
1455
1784
|
submitChange(field, fieldKind, change, revision) {
|
|
1456
1785
|
const localCrossFieldKeys = getChangeHandler(this.fieldKinds, fieldKind).getCrossFieldKeys(change);
|
|
1457
1786
|
const modularChange = buildModularChangesetFromField({
|
|
1787
|
+
rebaseVersion: this.rebaseVersion,
|
|
1458
1788
|
path: field,
|
|
1459
1789
|
fieldChange: { fieldKind, change },
|
|
1460
1790
|
nodeChanges: (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
1461
1791
|
nodeToParent: (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
1462
|
-
crossFieldKeys: (0, modularChangeTypes_js_1.
|
|
1792
|
+
crossFieldKeys: (0, modularChangeTypes_js_1.newCrossFieldRangeTable)(),
|
|
1793
|
+
rootNodes: newRootTable(),
|
|
1463
1794
|
idAllocator: this.idAllocator,
|
|
1464
1795
|
localCrossFieldKeys,
|
|
1465
1796
|
revision,
|
|
@@ -1476,11 +1807,14 @@ class ModularEditBuilder extends index_js_2.EditBuilder {
|
|
|
1476
1807
|
revisions.add(change.revision);
|
|
1477
1808
|
return (0, index_js_2.makeAnonChange)(change.type === "global"
|
|
1478
1809
|
? makeModularChangeset({
|
|
1810
|
+
rebaseVersion: this.rebaseVersion,
|
|
1479
1811
|
maxId: this.idAllocator.getMaxId(),
|
|
1480
1812
|
builds: change.builds,
|
|
1813
|
+
rootNodes: renameTableFromRenameDescriptions(change.renames ?? []),
|
|
1481
1814
|
revisions: [{ revision: change.revision }],
|
|
1482
1815
|
})
|
|
1483
1816
|
: buildModularChangesetFromField({
|
|
1817
|
+
rebaseVersion: this.rebaseVersion,
|
|
1484
1818
|
path: change.field,
|
|
1485
1819
|
fieldChange: {
|
|
1486
1820
|
fieldKind: change.fieldKind,
|
|
@@ -1488,7 +1822,8 @@ class ModularEditBuilder extends index_js_2.EditBuilder {
|
|
|
1488
1822
|
},
|
|
1489
1823
|
nodeChanges: (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
1490
1824
|
nodeToParent: (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
1491
|
-
crossFieldKeys: (0, modularChangeTypes_js_1.
|
|
1825
|
+
crossFieldKeys: (0, modularChangeTypes_js_1.newCrossFieldRangeTable)(),
|
|
1826
|
+
rootNodes: newRootTable(),
|
|
1492
1827
|
idAllocator: this.idAllocator,
|
|
1493
1828
|
localCrossFieldKeys: getChangeHandler(this.fieldKinds, change.fieldKind).getCrossFieldKeys(change.change),
|
|
1494
1829
|
revision: change.revision,
|
|
@@ -1513,11 +1848,13 @@ class ModularEditBuilder extends index_js_2.EditBuilder {
|
|
|
1513
1848
|
nodeExistsConstraint: { violated: false },
|
|
1514
1849
|
};
|
|
1515
1850
|
this.applyChange((0, index_js_2.tagChange)(buildModularChangesetFromNode({
|
|
1851
|
+
rebaseVersion: this.rebaseVersion,
|
|
1516
1852
|
path,
|
|
1517
1853
|
nodeChange,
|
|
1518
1854
|
nodeChanges: (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
1519
1855
|
nodeToParent: (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
1520
|
-
crossFieldKeys: (0, modularChangeTypes_js_1.
|
|
1856
|
+
crossFieldKeys: (0, modularChangeTypes_js_1.newCrossFieldRangeTable)(),
|
|
1857
|
+
rootNodes: newRootTable(),
|
|
1521
1858
|
idAllocator: this.idAllocator,
|
|
1522
1859
|
revision,
|
|
1523
1860
|
}), revision));
|
|
@@ -1527,11 +1864,13 @@ class ModularEditBuilder extends index_js_2.EditBuilder {
|
|
|
1527
1864
|
nodeExistsConstraintOnRevert: { violated: false },
|
|
1528
1865
|
};
|
|
1529
1866
|
this.applyChange((0, index_js_2.tagChange)(buildModularChangesetFromNode({
|
|
1867
|
+
rebaseVersion: this.rebaseVersion,
|
|
1530
1868
|
path,
|
|
1531
1869
|
nodeChange,
|
|
1532
1870
|
nodeChanges: (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
1533
1871
|
nodeToParent: (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
1534
|
-
crossFieldKeys: (0, modularChangeTypes_js_1.
|
|
1872
|
+
crossFieldKeys: (0, modularChangeTypes_js_1.newCrossFieldRangeTable)(),
|
|
1873
|
+
rootNodes: newRootTable(),
|
|
1535
1874
|
idAllocator: this.idAllocator,
|
|
1536
1875
|
revision,
|
|
1537
1876
|
}), revision));
|
|
@@ -1541,6 +1880,7 @@ class ModularEditBuilder extends index_js_2.EditBuilder {
|
|
|
1541
1880
|
throw new internal_2.UsageError(`No change constraints require min client version of at least ${index_js_1.FluidClientVersion.v2_80}`);
|
|
1542
1881
|
}
|
|
1543
1882
|
const changeset = makeModularChangeset({
|
|
1883
|
+
rebaseVersion: this.rebaseVersion,
|
|
1544
1884
|
maxId: -1,
|
|
1545
1885
|
noChangeConstraint: { violated: false },
|
|
1546
1886
|
});
|
|
@@ -1551,6 +1891,7 @@ class ModularEditBuilder extends index_js_2.EditBuilder {
|
|
|
1551
1891
|
throw new internal_2.UsageError(`No change constraints require min client version of at least ${index_js_1.FluidClientVersion.v2_80}`);
|
|
1552
1892
|
}
|
|
1553
1893
|
const changeset = makeModularChangeset({
|
|
1894
|
+
rebaseVersion: this.rebaseVersion,
|
|
1554
1895
|
maxId: -1,
|
|
1555
1896
|
noChangeConstraintOnRevert: { violated: false },
|
|
1556
1897
|
});
|
|
@@ -1559,23 +1900,28 @@ class ModularEditBuilder extends index_js_2.EditBuilder {
|
|
|
1559
1900
|
}
|
|
1560
1901
|
exports.ModularEditBuilder = ModularEditBuilder;
|
|
1561
1902
|
function buildModularChangesetFromField(props) {
|
|
1562
|
-
const { path, fieldChange, nodeChanges, nodeToParent, crossFieldKeys, idAllocator = (0, index_js_3.idAllocatorFromMaxId)(), localCrossFieldKeys = [], childId, revision, } = props;
|
|
1903
|
+
const { rebaseVersion, path, fieldChange, nodeChanges, nodeToParent, crossFieldKeys, rootNodes, idAllocator = (0, index_js_3.idAllocatorFromMaxId)(), localCrossFieldKeys = [], childId, revision, } = props;
|
|
1563
1904
|
const fieldChanges = new Map([[path.field, fieldChange]]);
|
|
1564
1905
|
if (path.parent === undefined) {
|
|
1906
|
+
const field = { nodeId: undefined, field: path.field };
|
|
1565
1907
|
for (const { key, count } of localCrossFieldKeys) {
|
|
1566
|
-
crossFieldKeys.set(key, count,
|
|
1908
|
+
crossFieldKeys.set(key, count, field);
|
|
1567
1909
|
}
|
|
1568
1910
|
if (childId !== undefined) {
|
|
1569
1911
|
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(nodeToParent, childId, {
|
|
1570
|
-
|
|
1571
|
-
|
|
1912
|
+
field: {
|
|
1913
|
+
nodeId: undefined,
|
|
1914
|
+
field: path.field,
|
|
1915
|
+
},
|
|
1572
1916
|
});
|
|
1573
1917
|
}
|
|
1574
1918
|
return makeModularChangeset({
|
|
1919
|
+
rebaseVersion,
|
|
1575
1920
|
fieldChanges,
|
|
1576
1921
|
nodeChanges,
|
|
1577
1922
|
nodeToParent,
|
|
1578
1923
|
crossFieldKeys,
|
|
1924
|
+
rootNodes,
|
|
1579
1925
|
maxId: idAllocator.getMaxId(),
|
|
1580
1926
|
revisions: [{ revision }],
|
|
1581
1927
|
});
|
|
@@ -1584,43 +1930,67 @@ function buildModularChangesetFromField(props) {
|
|
|
1584
1930
|
fieldChanges,
|
|
1585
1931
|
};
|
|
1586
1932
|
const parentId = { localId: (0, index_js_3.brand)(idAllocator.allocate()), revision };
|
|
1933
|
+
const fieldId = { nodeId: parentId, field: path.field };
|
|
1587
1934
|
for (const { key, count } of localCrossFieldKeys) {
|
|
1588
1935
|
crossFieldKeys.set(key, count, { nodeId: parentId, field: path.field });
|
|
1589
1936
|
}
|
|
1590
1937
|
if (childId !== undefined) {
|
|
1591
1938
|
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(nodeToParent, childId, {
|
|
1592
|
-
|
|
1593
|
-
field: path.field,
|
|
1939
|
+
field: fieldId,
|
|
1594
1940
|
});
|
|
1595
1941
|
}
|
|
1596
1942
|
return buildModularChangesetFromNode({
|
|
1943
|
+
rebaseVersion,
|
|
1597
1944
|
path: path.parent,
|
|
1598
1945
|
nodeChange: nodeChangeset,
|
|
1599
1946
|
nodeChanges,
|
|
1600
1947
|
nodeToParent,
|
|
1601
1948
|
crossFieldKeys,
|
|
1949
|
+
rootNodes,
|
|
1602
1950
|
idAllocator,
|
|
1603
1951
|
revision,
|
|
1604
1952
|
nodeId: parentId,
|
|
1605
1953
|
});
|
|
1606
1954
|
}
|
|
1955
|
+
exports.buildModularChangesetFromField = buildModularChangesetFromField;
|
|
1607
1956
|
function buildModularChangesetFromNode(props) {
|
|
1608
1957
|
const { path, idAllocator, revision, nodeChanges, nodeChange, nodeId = { localId: (0, index_js_3.brand)(idAllocator.allocate()), revision }, } = props;
|
|
1609
1958
|
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(nodeChanges, nodeId, nodeChange);
|
|
1610
|
-
|
|
1611
|
-
[path.
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1959
|
+
if ((0, index_js_2.isDetachedUpPathRoot)(path)) {
|
|
1960
|
+
props.rootNodes.nodeChanges.set([path.detachedNodeId.major, (0, index_js_3.brand)(path.detachedNodeId.minor)], nodeId);
|
|
1961
|
+
return makeModularChangeset({
|
|
1962
|
+
rebaseVersion: props.rebaseVersion,
|
|
1963
|
+
rootNodes: props.rootNodes,
|
|
1964
|
+
nodeChanges: props.nodeChanges,
|
|
1965
|
+
nodeToParent: props.nodeToParent,
|
|
1966
|
+
crossFieldKeys: props.crossFieldKeys,
|
|
1967
|
+
maxId: props.idAllocator.getMaxId(),
|
|
1968
|
+
revisions: [{ revision: props.revision }],
|
|
1969
|
+
});
|
|
1970
|
+
}
|
|
1971
|
+
else {
|
|
1972
|
+
const fieldChangeset = genericFieldKind_js_1.genericFieldKind.changeHandler.editor.buildChildChanges([
|
|
1973
|
+
[path.parentIndex, nodeId],
|
|
1974
|
+
]);
|
|
1975
|
+
const fieldChange = {
|
|
1976
|
+
fieldKind: genericFieldKind_js_1.genericFieldKind.identifier,
|
|
1977
|
+
change: fieldChangeset,
|
|
1978
|
+
};
|
|
1979
|
+
return buildModularChangesetFromField({
|
|
1980
|
+
...props,
|
|
1981
|
+
path: { parent: path.parent, field: path.parentField },
|
|
1982
|
+
fieldChange,
|
|
1983
|
+
localCrossFieldKeys: [],
|
|
1984
|
+
childId: nodeId,
|
|
1985
|
+
});
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
function renameTableFromRenameDescriptions(renames) {
|
|
1989
|
+
const table = newRootTable();
|
|
1990
|
+
for (const rename of renames) {
|
|
1991
|
+
addNodeRename(table, rename.oldId, rename.newId, rename.count, rename.detachLocation);
|
|
1992
|
+
}
|
|
1993
|
+
return table;
|
|
1624
1994
|
}
|
|
1625
1995
|
function getRevInfoFromTaggedChanges(changes) {
|
|
1626
1996
|
let maxId = -1;
|
|
@@ -1637,18 +2007,6 @@ function getRevInfoFromTaggedChanges(changes) {
|
|
|
1637
2007
|
}
|
|
1638
2008
|
}
|
|
1639
2009
|
}
|
|
1640
|
-
const rolledBackRevisions = [];
|
|
1641
|
-
for (const info of revInfos) {
|
|
1642
|
-
if (info.rollbackOf !== undefined) {
|
|
1643
|
-
rolledBackRevisions.push(info.rollbackOf);
|
|
1644
|
-
}
|
|
1645
|
-
}
|
|
1646
|
-
rolledBackRevisions.reverse();
|
|
1647
|
-
for (const revision of rolledBackRevisions) {
|
|
1648
|
-
if (!revisions.has(revision)) {
|
|
1649
|
-
revInfos.push({ revision });
|
|
1650
|
-
}
|
|
1651
|
-
}
|
|
1652
2010
|
return { maxId: (0, index_js_3.brand)(maxId), revInfos };
|
|
1653
2011
|
}
|
|
1654
2012
|
function revisionInfoFromTaggedChange(taggedChange) {
|
|
@@ -1665,15 +2023,16 @@ function revisionInfoFromTaggedChange(taggedChange) {
|
|
|
1665
2023
|
}
|
|
1666
2024
|
return revInfos;
|
|
1667
2025
|
}
|
|
1668
|
-
function fieldChangeFromId(
|
|
1669
|
-
const
|
|
2026
|
+
function fieldChangeFromId(change, id) {
|
|
2027
|
+
const fieldId = normalizeFieldId(id, change.nodeAliases);
|
|
2028
|
+
const fieldMap = fieldMapFromNodeId(change.fieldChanges, change.nodeChanges, change.nodeAliases, fieldId.nodeId);
|
|
1670
2029
|
return fieldMap.get(id.field) ?? (0, internal_1.fail)(0xb25 /* No field exists for the given ID */);
|
|
1671
2030
|
}
|
|
1672
|
-
function fieldMapFromNodeId(rootFieldMap, nodes, nodeId) {
|
|
2031
|
+
function fieldMapFromNodeId(rootFieldMap, nodes, aliases, nodeId) {
|
|
1673
2032
|
if (nodeId === undefined) {
|
|
1674
2033
|
return rootFieldMap;
|
|
1675
2034
|
}
|
|
1676
|
-
const node = nodeChangeFromId(nodes, nodeId);
|
|
2035
|
+
const node = nodeChangeFromId(nodes, aliases, nodeId);
|
|
1677
2036
|
(0, internal_1.assert)(node.fieldChanges !== undefined, 0x9c9 /* Expected node to have field changes */);
|
|
1678
2037
|
return node.fieldChanges;
|
|
1679
2038
|
}
|
|
@@ -1686,8 +2045,9 @@ function rebasedFieldIdFromBaseId(table, baseId) {
|
|
|
1686
2045
|
function rebasedNodeIdFromBaseNodeId(table, baseId) {
|
|
1687
2046
|
return (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(table.baseToRebasedNodeId, baseId) ?? baseId;
|
|
1688
2047
|
}
|
|
1689
|
-
function nodeChangeFromId(nodes, id) {
|
|
1690
|
-
const
|
|
2048
|
+
function nodeChangeFromId(nodes, aliases, id) {
|
|
2049
|
+
const normalizedId = normalizeNodeId(id, aliases);
|
|
2050
|
+
const node = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(nodes, normalizedId);
|
|
1691
2051
|
(0, internal_1.assert)(node !== undefined, 0x9ca /* Unknown node ID */);
|
|
1692
2052
|
return node;
|
|
1693
2053
|
}
|
|
@@ -1695,12 +2055,20 @@ function fieldIdFromFieldIdKey([revision, localId, field]) {
|
|
|
1695
2055
|
const nodeId = localId === undefined ? undefined : { revision, localId };
|
|
1696
2056
|
return { nodeId, field };
|
|
1697
2057
|
}
|
|
2058
|
+
function fieldIdKeyFromFieldId(fieldId) {
|
|
2059
|
+
return [fieldId.nodeId?.revision, fieldId.nodeId?.localId, fieldId.field];
|
|
2060
|
+
}
|
|
1698
2061
|
function cloneNodeChangeset(nodeChangeset) {
|
|
1699
2062
|
if (nodeChangeset.fieldChanges !== undefined) {
|
|
1700
2063
|
return { ...nodeChangeset, fieldChanges: new Map(nodeChangeset.fieldChanges) };
|
|
1701
2064
|
}
|
|
1702
2065
|
return { ...nodeChangeset };
|
|
1703
2066
|
}
|
|
2067
|
+
function replaceNodeLocationRevision(location, replacer) {
|
|
2068
|
+
return location.field === undefined
|
|
2069
|
+
? { root: replacer.getUpdatedAtomId(location.root) }
|
|
2070
|
+
: { field: replaceFieldIdRevision(location.field, replacer) };
|
|
2071
|
+
}
|
|
1704
2072
|
function replaceFieldIdRevision(fieldId, replacer) {
|
|
1705
2073
|
if (fieldId.nodeId === undefined) {
|
|
1706
2074
|
return fieldId;
|
|
@@ -1710,17 +2078,34 @@ function replaceFieldIdRevision(fieldId, replacer) {
|
|
|
1710
2078
|
nodeId: replacer.getUpdatedAtomId(fieldId.nodeId),
|
|
1711
2079
|
};
|
|
1712
2080
|
}
|
|
1713
|
-
function
|
|
1714
|
-
const
|
|
1715
|
-
(0,
|
|
1716
|
-
|
|
2081
|
+
function getNodeParent(changeset, nodeId) {
|
|
2082
|
+
const normalizedNodeId = normalizeNodeId(nodeId, changeset.nodeAliases);
|
|
2083
|
+
const location = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(changeset.nodeToParent, normalizedNodeId);
|
|
2084
|
+
(0, internal_1.assert)(location !== undefined, 0x9cb /* Parent field should be defined */);
|
|
2085
|
+
if (location.field !== undefined) {
|
|
2086
|
+
return { field: normalizeFieldId(location.field, changeset.nodeAliases) };
|
|
2087
|
+
}
|
|
2088
|
+
return location;
|
|
1717
2089
|
}
|
|
1718
|
-
exports.
|
|
2090
|
+
exports.getNodeParent = getNodeParent;
|
|
1719
2091
|
function getFieldsForCrossFieldKey(changeset, key, count) {
|
|
1720
2092
|
return changeset.crossFieldKeys
|
|
1721
2093
|
.getAll(key, count)
|
|
1722
2094
|
.map(({ value: fieldId }) => normalizeFieldId(fieldId, changeset.nodeAliases));
|
|
1723
2095
|
}
|
|
2096
|
+
function getFirstFieldForCrossFieldKey(changeset, key, count) {
|
|
2097
|
+
const result = changeset.crossFieldKeys.getFirst(key, count);
|
|
2098
|
+
if (result.value === undefined) {
|
|
2099
|
+
return result;
|
|
2100
|
+
}
|
|
2101
|
+
return { ...result, value: normalizeFieldId(result.value, changeset.nodeAliases) };
|
|
2102
|
+
}
|
|
2103
|
+
function normalizeNodeLocation(location, nodeAliases) {
|
|
2104
|
+
if (location.field !== undefined) {
|
|
2105
|
+
return { field: normalizeFieldId(location.field, nodeAliases) };
|
|
2106
|
+
}
|
|
2107
|
+
return location;
|
|
2108
|
+
}
|
|
1724
2109
|
// This is only exported for use in test utilities.
|
|
1725
2110
|
function normalizeFieldId(fieldId, nodeAliases) {
|
|
1726
2111
|
return fieldId.nodeId === undefined
|
|
@@ -1733,6 +2118,7 @@ exports.normalizeFieldId = normalizeFieldId;
|
|
|
1733
2118
|
*/
|
|
1734
2119
|
function normalizeNodeId(nodeId, nodeAliases) {
|
|
1735
2120
|
let currentId = nodeId;
|
|
2121
|
+
let cycleProbeId = nodeId;
|
|
1736
2122
|
// eslint-disable-next-line no-constant-condition
|
|
1737
2123
|
while (true) {
|
|
1738
2124
|
const dealiased = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(nodeAliases, currentId);
|
|
@@ -1740,25 +2126,567 @@ function normalizeNodeId(nodeId, nodeAliases) {
|
|
|
1740
2126
|
return currentId;
|
|
1741
2127
|
}
|
|
1742
2128
|
currentId = dealiased;
|
|
2129
|
+
if (cycleProbeId !== undefined) {
|
|
2130
|
+
cycleProbeId = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(nodeAliases, cycleProbeId);
|
|
2131
|
+
}
|
|
2132
|
+
if (cycleProbeId !== undefined) {
|
|
2133
|
+
cycleProbeId = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(nodeAliases, cycleProbeId);
|
|
2134
|
+
}
|
|
2135
|
+
(0, internal_1.assert)(!(0, index_js_2.areEqualChangeAtomIdOpts)(cycleProbeId, currentId), "Alias cycle detected");
|
|
1743
2136
|
}
|
|
1744
2137
|
}
|
|
2138
|
+
exports.normalizeNodeId = normalizeNodeId;
|
|
1745
2139
|
function hasConflicts(change) {
|
|
1746
2140
|
return (change.constraintViolationCount ?? 0) > 0;
|
|
1747
2141
|
}
|
|
2142
|
+
function areEqualFieldIds(a, b) {
|
|
2143
|
+
return (0, index_js_2.areEqualChangeAtomIdOpts)(a.nodeId, b.nodeId) && a.field === b.field;
|
|
2144
|
+
}
|
|
2145
|
+
function firstAttachIdFromDetachId(roots, detachId, count) {
|
|
2146
|
+
const result = roots.oldToNewId.getFirst(detachId, count);
|
|
2147
|
+
return { ...result, value: result.value ?? detachId };
|
|
2148
|
+
}
|
|
2149
|
+
function firstDetachIdFromAttachId(roots, attachId, count) {
|
|
2150
|
+
const result = roots.newToOldId.getFirst(attachId, count);
|
|
2151
|
+
return { ...result, start: attachId, value: result.value ?? attachId };
|
|
2152
|
+
}
|
|
2153
|
+
function rebaseCrossFieldKeys(sourceTable, movedDetaches, newDetachLocations) {
|
|
2154
|
+
const rebasedTable = sourceTable.clone();
|
|
2155
|
+
for (const entry of movedDetaches.entries()) {
|
|
2156
|
+
rebasedTable.delete({ ...entry.start, target: crossFieldQueries_js_1.NodeMoveType.Detach }, entry.length);
|
|
2157
|
+
}
|
|
2158
|
+
for (const entry of newDetachLocations.entries()) {
|
|
2159
|
+
rebasedTable.set({ ...entry.start, target: crossFieldQueries_js_1.NodeMoveType.Detach }, entry.length, entry.value);
|
|
2160
|
+
}
|
|
2161
|
+
return rebasedTable;
|
|
2162
|
+
}
|
|
2163
|
+
function newRootTable() {
|
|
2164
|
+
return {
|
|
2165
|
+
newToOldId: (0, index_js_2.newChangeAtomIdTransform)(),
|
|
2166
|
+
oldToNewId: (0, index_js_2.newChangeAtomIdTransform)(),
|
|
2167
|
+
nodeChanges: (0, changeAtomIdBTree_js_1.newChangeAtomIdBTree)(),
|
|
2168
|
+
detachLocations: (0, index_js_2.newChangeAtomIdRangeMap)(),
|
|
2169
|
+
outputDetachLocations: (0, index_js_2.newChangeAtomIdRangeMap)(),
|
|
2170
|
+
};
|
|
2171
|
+
}
|
|
2172
|
+
exports.newRootTable = newRootTable;
|
|
2173
|
+
function rebaseRoots(change, base, affectedBaseFields, nodesToRebase, rebasedNodeToParent, rebaseVersion) {
|
|
2174
|
+
const rebasedRoots = newRootTable();
|
|
2175
|
+
for (const renameEntry of change.rootNodes.oldToNewId.entries()) {
|
|
2176
|
+
rebaseRename(change.rootNodes, rebasedRoots, renameEntry, base, affectedBaseFields);
|
|
2177
|
+
}
|
|
2178
|
+
for (const [detachIdKey, nodeId] of change.rootNodes.nodeChanges.entries()) {
|
|
2179
|
+
const changes = base.rootNodes.nodeChanges.get(detachIdKey);
|
|
2180
|
+
if (changes !== undefined) {
|
|
2181
|
+
nodesToRebase.push([nodeId, changes]);
|
|
2182
|
+
}
|
|
2183
|
+
const detachId = (0, index_js_2.makeChangeAtomId)(detachIdKey[1], detachIdKey[0]);
|
|
2184
|
+
const attachId = firstAttachIdFromDetachId(base.rootNodes, detachId, 1).value;
|
|
2185
|
+
const baseAttachEntry = base.crossFieldKeys.getFirst({ target: crossFieldQueries_js_1.NodeMoveType.Attach, ...attachId }, 1);
|
|
2186
|
+
if (baseAttachEntry.value === undefined) {
|
|
2187
|
+
const renamedDetachId = firstAttachIdFromDetachId(base.rootNodes, detachId, 1).value;
|
|
2188
|
+
const baseOutputDetachLocation = base.rootNodes.outputDetachLocations.getFirst(renamedDetachId, 1).value;
|
|
2189
|
+
if (baseOutputDetachLocation !== undefined) {
|
|
2190
|
+
affectedBaseFields.set(fieldIdKeyFromFieldId(baseOutputDetachLocation), true);
|
|
2191
|
+
}
|
|
2192
|
+
const detachLocation = baseOutputDetachLocation ??
|
|
2193
|
+
change.rootNodes.detachLocations.getFirst(detachId, 1).value;
|
|
2194
|
+
// Note that `baseOutputDetachLocation` may contain a node ID from the base changeset.
|
|
2195
|
+
// We will replace the detach location entry with the node ID from the rebased changeset in `fixupRebasedDetachLocations`
|
|
2196
|
+
assignRootChange(rebasedRoots, rebasedNodeToParent, renamedDetachId, nodeId, detachLocation, rebaseVersion);
|
|
2197
|
+
}
|
|
2198
|
+
else {
|
|
2199
|
+
affectedBaseFields.set(fieldIdKeyFromFieldId(baseAttachEntry.value), true);
|
|
2200
|
+
rebasedNodeToParent.delete(detachIdKey);
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
for (const entry of change.rootNodes.outputDetachLocations.entries()) {
|
|
2204
|
+
rebasedRoots.outputDetachLocations.set(entry.start, entry.length, entry.value);
|
|
2205
|
+
}
|
|
2206
|
+
return rebasedRoots;
|
|
2207
|
+
}
|
|
2208
|
+
function rebaseRename(newRoots, rebasedRoots, renameEntry, base, affectedBaseFields) {
|
|
2209
|
+
let count = renameEntry.length;
|
|
2210
|
+
const baseRenameEntry = firstAttachIdFromDetachId(base.rootNodes, renameEntry.start, count);
|
|
2211
|
+
count = baseRenameEntry.length;
|
|
2212
|
+
const baseAttachEntry = base.crossFieldKeys.getFirst({
|
|
2213
|
+
...baseRenameEntry.value,
|
|
2214
|
+
target: crossFieldQueries_js_1.NodeMoveType.Attach,
|
|
2215
|
+
}, count);
|
|
2216
|
+
count = baseAttachEntry.length;
|
|
2217
|
+
if (baseAttachEntry.value === undefined) {
|
|
2218
|
+
const baseOutputDetachLocation = base.rootNodes.outputDetachLocations.getFirst(baseRenameEntry.value, 1).value;
|
|
2219
|
+
if (baseOutputDetachLocation !== undefined) {
|
|
2220
|
+
affectedBaseFields.set(fieldIdKeyFromFieldId(baseOutputDetachLocation), true);
|
|
2221
|
+
}
|
|
2222
|
+
const detachEntry = newRoots.detachLocations.getFirst(renameEntry.start, count);
|
|
2223
|
+
count = detachEntry.length;
|
|
2224
|
+
const detachLocation = baseOutputDetachLocation ?? detachEntry.value;
|
|
2225
|
+
// Note that `baseOutputDetachLocation` may contain a node ID from the base changeset.
|
|
2226
|
+
// We will replace the detach location entry with the node ID from the rebased changeset in `fixupRebasedDetachLocations`
|
|
2227
|
+
addNodeRename(rebasedRoots, baseRenameEntry.value, renameEntry.value, count, detachLocation);
|
|
2228
|
+
}
|
|
2229
|
+
else {
|
|
2230
|
+
// This rename represents an intention to detach these nodes.
|
|
2231
|
+
// The rebased change should have a detach in the field where the base change attaches the nodes,
|
|
2232
|
+
// so we need to ensure that field is processed.
|
|
2233
|
+
affectedBaseFields.set(fieldIdKeyFromFieldId(normalizeFieldId(baseAttachEntry.value, base.nodeAliases)), true);
|
|
2234
|
+
}
|
|
2235
|
+
const countRemaining = renameEntry.length - count;
|
|
2236
|
+
if (countRemaining > 0) {
|
|
2237
|
+
rebaseRename(newRoots, rebasedRoots, {
|
|
2238
|
+
start: (0, index_js_2.offsetChangeAtomId)(renameEntry.start, count),
|
|
2239
|
+
value: (0, index_js_2.offsetChangeAtomId)(renameEntry.value, count),
|
|
2240
|
+
length: countRemaining,
|
|
2241
|
+
}, base, affectedBaseFields);
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
1748
2244
|
/**
|
|
1749
|
-
*
|
|
1750
|
-
*
|
|
2245
|
+
* For each root detach location, replaces any node ID from the base changeset
|
|
2246
|
+
* with the corresponding ID in the new changeset.
|
|
1751
2247
|
*/
|
|
1752
|
-
function
|
|
1753
|
-
|
|
1754
|
-
|
|
2248
|
+
function fixupRebasedDetachLocations(table) {
|
|
2249
|
+
for (const { start, length, value: detachLocation, } of table.rebasedRootNodes.detachLocations.entries()) {
|
|
2250
|
+
const normalizedDetachLocation = normalizeFieldId(detachLocation, table.baseChange.nodeAliases);
|
|
2251
|
+
if (normalizedDetachLocation.nodeId !== undefined) {
|
|
2252
|
+
const rebasedNodeId = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(table.baseToRebasedNodeId, normalizedDetachLocation.nodeId);
|
|
2253
|
+
if (rebasedNodeId !== undefined) {
|
|
2254
|
+
table.rebasedRootNodes.detachLocations.set(start, length, {
|
|
2255
|
+
...normalizedDetachLocation,
|
|
2256
|
+
nodeId: rebasedNodeId,
|
|
2257
|
+
});
|
|
2258
|
+
}
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
1755
2261
|
}
|
|
1756
|
-
function
|
|
1757
|
-
|
|
2262
|
+
function addNodesToCompose(table, id1, id2) {
|
|
2263
|
+
const normalizedId1 = normalizeNodeId(id1, table.baseChange.nodeAliases);
|
|
2264
|
+
const normalizedId2 = normalizeNodeId(id2, table.newChange.nodeAliases);
|
|
2265
|
+
if ((0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(table.newToBaseNodeId, normalizedId2) === undefined) {
|
|
2266
|
+
(0, changeAtomIdBTree_js_1.setInChangeAtomIdMap)(table.newToBaseNodeId, normalizedId2, normalizedId1);
|
|
2267
|
+
table.pendingCompositions.nodeIdsToCompose.push([normalizedId1, normalizedId2]);
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
function composeRevInfos(revisions1, revisions2) {
|
|
2271
|
+
if (revisions1?.length === 1 &&
|
|
2272
|
+
revisions2?.length === 1 &&
|
|
2273
|
+
revisions1[0]?.revision === revisions2[0]?.revision) {
|
|
2274
|
+
// This is a special case where we are composing two changesets from the same transaction.
|
|
2275
|
+
// We return one of the input arrays to avoid duplicating revision entries.
|
|
2276
|
+
return revisions1;
|
|
2277
|
+
}
|
|
2278
|
+
const result = [...(revisions1 ?? []), ...(revisions2 ?? [])];
|
|
2279
|
+
return result;
|
|
2280
|
+
}
|
|
2281
|
+
function composeCrossFieldKeyTables(table1, table2, movedCrossFieldKeys, removedCrossFieldKeys) {
|
|
2282
|
+
const composedTable = index_js_3.RangeMap.union(table1, table2);
|
|
2283
|
+
for (const entry of movedCrossFieldKeys.entries()) {
|
|
2284
|
+
composedTable.set(entry.start, entry.length, entry.value);
|
|
2285
|
+
}
|
|
2286
|
+
for (const entry of removedCrossFieldKeys.entries()) {
|
|
2287
|
+
composedTable.delete(entry.start, entry.length);
|
|
2288
|
+
}
|
|
2289
|
+
return composedTable;
|
|
2290
|
+
}
|
|
2291
|
+
function composeRootTables(change1, change2, composedNodeToParent, movedCrossFieldKeys, removedCrossFieldKeys, pendingCompositions) {
|
|
2292
|
+
const composedTable = cloneRootTable(change1.rootNodes);
|
|
2293
|
+
for (const renameEntry of change2.rootNodes.oldToNewId.entries()) {
|
|
2294
|
+
composeRename(change1, change2, composedTable, renameEntry.start, renameEntry.value, renameEntry.length, movedCrossFieldKeys, removedCrossFieldKeys, pendingCompositions);
|
|
2295
|
+
}
|
|
2296
|
+
for (const [[revision2, id2], nodeId2] of change2.rootNodes.nodeChanges.entries()) {
|
|
2297
|
+
const detachId2 = { revision: revision2, localId: id2 };
|
|
2298
|
+
const detachId1 = firstDetachIdFromAttachId(change1.rootNodes, detachId2, 1).value;
|
|
2299
|
+
const nodeId1 = (0, changeAtomIdBTree_js_1.getFromChangeAtomIdMap)(change1.rootNodes.nodeChanges, detachId1);
|
|
2300
|
+
if (nodeId1 === undefined) {
|
|
2301
|
+
const fieldId = getFieldsForCrossFieldKey(change1, { ...detachId1, target: crossFieldQueries_js_1.NodeMoveType.Detach }, 1)[0];
|
|
2302
|
+
if (fieldId === undefined) {
|
|
2303
|
+
assignRootChange(composedTable, composedNodeToParent, detachId1, nodeId2, change1.rootNodes.detachLocations.getFirst(detachId1, 1).value ??
|
|
2304
|
+
change2.rootNodes.detachLocations.getFirst(detachId2, 1).value, Math.max(change1.rebaseVersion, change2.rebaseVersion));
|
|
2305
|
+
}
|
|
2306
|
+
else {
|
|
2307
|
+
// In this case, this node is attached in the input context of change1,
|
|
2308
|
+
// and is represented in detachFieldId.
|
|
2309
|
+
pendingCompositions.affectedBaseFields.set([fieldId.nodeId?.revision, fieldId.nodeId?.localId, fieldId.field], true);
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
else {
|
|
2313
|
+
pendingCompositions.nodeIdsToCompose.push([nodeId1, nodeId2]);
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
for (const outputDetachEntry of change1.rootNodes.outputDetachLocations.entries()) {
|
|
2317
|
+
composeOutputDetachLocation(outputDetachEntry.start, outputDetachEntry.length, outputDetachEntry.value, change2, composedTable);
|
|
2318
|
+
}
|
|
2319
|
+
for (const entry of change2.rootNodes.outputDetachLocations.entries()) {
|
|
2320
|
+
composedTable.outputDetachLocations.set(entry.start, entry.length, entry.value);
|
|
2321
|
+
}
|
|
2322
|
+
return composedTable;
|
|
2323
|
+
}
|
|
2324
|
+
function composeOutputDetachLocation(outputDetachId1, count, detachLocation, change2, composedTable) {
|
|
2325
|
+
let countToProcess = count;
|
|
2326
|
+
const renameEntry = firstAttachIdFromDetachId(change2.rootNodes, outputDetachId1, countToProcess);
|
|
2327
|
+
countToProcess = renameEntry.length;
|
|
2328
|
+
const attachEntry = getFirstAttachField(change2.crossFieldKeys, renameEntry.value, countToProcess);
|
|
2329
|
+
countToProcess = attachEntry.length;
|
|
2330
|
+
composedTable.outputDetachLocations.delete(outputDetachId1, countToProcess);
|
|
2331
|
+
if (attachEntry.value === undefined) {
|
|
2332
|
+
// We update the key for the detach location to the renamed ID of the root in the composed output context.
|
|
2333
|
+
composedTable.outputDetachLocations.set(renameEntry.value, countToProcess, detachLocation);
|
|
2334
|
+
}
|
|
2335
|
+
else {
|
|
2336
|
+
// These nodes are attached by `change2` and thus attached in the composed output context,
|
|
2337
|
+
// so there should be no output detach location.
|
|
2338
|
+
}
|
|
2339
|
+
const countRemaining = count - countToProcess;
|
|
2340
|
+
if (countRemaining > 0) {
|
|
2341
|
+
composeOutputDetachLocation((0, index_js_2.offsetChangeAtomId)(outputDetachId1, countToProcess), countRemaining, detachLocation, change2, composedTable);
|
|
2342
|
+
}
|
|
2343
|
+
}
|
|
2344
|
+
function composeRename(change1, change2, mergedTable, oldId, newId, count, movedCrossFieldKeys, removedCrossFieldKeys, pendingCompositions) {
|
|
2345
|
+
let countToProcess = count;
|
|
2346
|
+
const detachEntry = getFirstDetachField(change1.crossFieldKeys, oldId, countToProcess);
|
|
2347
|
+
countToProcess = detachEntry.length;
|
|
2348
|
+
if (detachEntry.value === undefined) {
|
|
2349
|
+
// `change1` may also have a rename to `renameEntry.value`, in which case it must refer to a different node.
|
|
2350
|
+
// That node must have been attached by `change1` and detached by `change2`.
|
|
2351
|
+
// The final rename for that node will be created in `composeAttachDetach`.
|
|
2352
|
+
// We delete any such rename for now to avoid colliding with the rename currently being processed.
|
|
2353
|
+
deleteNodeRenameTo(mergedTable, newId, countToProcess);
|
|
2354
|
+
// The nodes were detached before `change`, so we append this rename.
|
|
2355
|
+
appendNodeRename(mergedTable, oldId, newId, countToProcess, change1.rootNodes, change2.rootNodes.detachLocations.getFirst(oldId, countToProcess).value);
|
|
2356
|
+
}
|
|
2357
|
+
else {
|
|
2358
|
+
// `change1` detached these nodes,
|
|
2359
|
+
// so we invalidate the detach location so that the detach's ID can be replaced with the new ID.
|
|
2360
|
+
pendingCompositions.affectedBaseFields.set(fieldIdKeyFromFieldId(detachEntry.value), true);
|
|
2361
|
+
if (!(0, index_js_2.areEqualChangeAtomIds)(oldId, newId)) {
|
|
2362
|
+
// `change1`'s detach will be replaced by `change2`'s detach, so we update the cross-field keys.
|
|
2363
|
+
removedCrossFieldKeys.set({ ...oldId, target: crossFieldQueries_js_1.NodeMoveType.Detach }, countToProcess, true);
|
|
2364
|
+
}
|
|
2365
|
+
movedCrossFieldKeys.set({ ...newId, target: crossFieldQueries_js_1.NodeMoveType.Detach }, countToProcess, detachEntry.value);
|
|
2366
|
+
}
|
|
2367
|
+
if (countToProcess < count) {
|
|
2368
|
+
composeRename(change1, change2, mergedTable, (0, index_js_2.offsetChangeAtomId)(oldId, countToProcess), (0, index_js_2.offsetChangeAtomId)(newId, countToProcess), count - countToProcess, movedCrossFieldKeys, removedCrossFieldKeys, pendingCompositions);
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
function cloneRootTable(table) {
|
|
2372
|
+
return {
|
|
2373
|
+
oldToNewId: table.oldToNewId.clone(),
|
|
2374
|
+
newToOldId: table.newToOldId.clone(),
|
|
2375
|
+
nodeChanges: (0, index_js_3.brand)(table.nodeChanges.clone()),
|
|
2376
|
+
detachLocations: table.detachLocations.clone(),
|
|
2377
|
+
outputDetachLocations: table.outputDetachLocations.clone(),
|
|
2378
|
+
};
|
|
2379
|
+
}
|
|
2380
|
+
exports.cloneRootTable = cloneRootTable;
|
|
2381
|
+
function invertRootTable(change, invertedNodeToParent, isRollback) {
|
|
2382
|
+
const invertedRoots = newRootTable();
|
|
2383
|
+
if (isRollback) {
|
|
2384
|
+
// We only invert renames of nodes which are not attached or detached by this changeset.
|
|
2385
|
+
// When we invert an attach we will create a detach which incorporates the rename.
|
|
2386
|
+
for (const { start: oldId, value: newId, length, } of change.rootNodes.oldToNewId.entries()) {
|
|
2387
|
+
invertRename(change, invertedRoots, oldId, newId, length);
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
for (const [[revision, localId], nodeId] of change.rootNodes.nodeChanges.entries()) {
|
|
2391
|
+
const detachId = { revision, localId };
|
|
2392
|
+
const renamedId = firstAttachIdFromDetachId(change.rootNodes, detachId, 1).value;
|
|
2393
|
+
// This checks whether `change` attaches this node.
|
|
2394
|
+
// If it does, the node is not detached in the input context of the inverse, and so should not be included in the root table.
|
|
2395
|
+
if (change.crossFieldKeys.getFirst({ ...renamedId, target: crossFieldQueries_js_1.NodeMoveType.Attach }, 1)
|
|
2396
|
+
.value === undefined) {
|
|
2397
|
+
assignRootChange(invertedRoots, invertedNodeToParent, renamedId, nodeId, change.rootNodes.detachLocations.getFirst(detachId, 1).value, change.rebaseVersion);
|
|
2398
|
+
}
|
|
2399
|
+
}
|
|
2400
|
+
return invertedRoots;
|
|
2401
|
+
}
|
|
2402
|
+
function invertRename(change, invertedRoots, oldId, newId, length) {
|
|
2403
|
+
for (const detachEntry of doesChangeDetachNodes(change.crossFieldKeys, newId, length)) {
|
|
2404
|
+
(0, internal_1.assert)(!detachEntry.value, "A changeset should not have a rename and detach for the same node.");
|
|
2405
|
+
}
|
|
2406
|
+
let countProcessed = length;
|
|
2407
|
+
const outputDetachEntry = change.rootNodes.outputDetachLocations.getFirst(newId, countProcessed);
|
|
2408
|
+
countProcessed = outputDetachEntry.length;
|
|
2409
|
+
const inputDetachEntry = change.rootNodes.detachLocations.getFirst(oldId, countProcessed);
|
|
2410
|
+
countProcessed = inputDetachEntry.length;
|
|
2411
|
+
const attachEntry = getFirstAttachField(change.crossFieldKeys, newId, countProcessed);
|
|
2412
|
+
countProcessed = attachEntry.length;
|
|
2413
|
+
if (attachEntry.value === undefined) {
|
|
2414
|
+
addNodeRename(invertedRoots, newId, oldId, countProcessed, outputDetachEntry.value ?? inputDetachEntry.value);
|
|
2415
|
+
// The original change moves the detached node, so the inverse should also record a move back to the original location.
|
|
2416
|
+
if (outputDetachEntry.value !== undefined && inputDetachEntry.value !== undefined) {
|
|
2417
|
+
invertedRoots.outputDetachLocations.set(oldId, countProcessed, inputDetachEntry.value);
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
if (countProcessed < length) {
|
|
2421
|
+
invertRename(change, invertedRoots, (0, index_js_2.offsetChangeAtomId)(oldId, countProcessed), (0, index_js_2.offsetChangeAtomId)(newId, countProcessed), length - countProcessed);
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
function doesChangeAttachNodes(table, id, count) {
|
|
2425
|
+
return table
|
|
2426
|
+
.getAll2({ ...id, target: crossFieldQueries_js_1.NodeMoveType.Attach }, count)
|
|
2427
|
+
.map((entry) => ({ ...entry, value: entry.value !== undefined }));
|
|
2428
|
+
}
|
|
2429
|
+
function doesChangeDetachNodes(table, id, count) {
|
|
2430
|
+
return table
|
|
2431
|
+
.getAll2({ ...id, target: crossFieldQueries_js_1.NodeMoveType.Detach }, count)
|
|
2432
|
+
.map((entry) => ({ ...entry, value: entry.value !== undefined }));
|
|
2433
|
+
}
|
|
2434
|
+
function getFirstDetachField(table, id, count) {
|
|
2435
|
+
return table.getFirst({ target: crossFieldQueries_js_1.NodeMoveType.Detach, ...id }, count);
|
|
2436
|
+
}
|
|
2437
|
+
exports.getFirstDetachField = getFirstDetachField;
|
|
2438
|
+
function getFirstAttachField(table, id, count) {
|
|
2439
|
+
return table.getFirst({ target: crossFieldQueries_js_1.NodeMoveType.Attach, ...id }, count);
|
|
2440
|
+
}
|
|
2441
|
+
exports.getFirstAttachField = getFirstAttachField;
|
|
2442
|
+
function addNodeRename(table, oldId, newId, count, detachLocation) {
|
|
2443
|
+
if ((0, index_js_2.areEqualChangeAtomIds)(oldId, newId)) {
|
|
2444
|
+
return;
|
|
2445
|
+
}
|
|
2446
|
+
for (const entry of table.oldToNewId.getAll2(oldId, count)) {
|
|
2447
|
+
(0, internal_1.assert)(entry.value === undefined ||
|
|
2448
|
+
(0, index_js_2.areEqualChangeAtomIds)(entry.value, (0, index_js_2.offsetChangeAtomId)(newId, entry.offset)), "Rename collision detected");
|
|
2449
|
+
}
|
|
2450
|
+
for (const entry of table.newToOldId.getAll2(newId, count)) {
|
|
2451
|
+
(0, internal_1.assert)(entry.value === undefined ||
|
|
2452
|
+
(0, index_js_2.areEqualChangeAtomIds)(entry.value, (0, index_js_2.offsetChangeAtomId)(oldId, entry.offset)), "Rename collision detected");
|
|
2453
|
+
}
|
|
2454
|
+
table.oldToNewId.set(oldId, count, newId);
|
|
2455
|
+
table.newToOldId.set(newId, count, oldId);
|
|
2456
|
+
if (detachLocation !== undefined) {
|
|
2457
|
+
table.detachLocations.set(oldId, count, detachLocation);
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
exports.addNodeRename = addNodeRename;
|
|
2461
|
+
/**
|
|
2462
|
+
* Deletes any renames from `id`.
|
|
2463
|
+
*/
|
|
2464
|
+
function deleteNodeRenameFrom(roots, id, count) {
|
|
2465
|
+
for (const entry of roots.oldToNewId.getAll(id, count)) {
|
|
2466
|
+
deleteNodeRenameEntry(roots, entry.start, entry.value, entry.length);
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
/**
|
|
2470
|
+
* Deletes any renames to `id`.
|
|
2471
|
+
*/
|
|
2472
|
+
function deleteNodeRenameTo(roots, id, count) {
|
|
2473
|
+
for (const entry of roots.newToOldId.getAll(id, count)) {
|
|
2474
|
+
deleteNodeRenameEntry(roots, entry.value, entry.start, entry.length);
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
function appendNodeRename(composedTable, oldId, newId, count, change1Table, detachLocation) {
|
|
2478
|
+
let countToProcess = count;
|
|
2479
|
+
const rename1Entry = change1Table.newToOldId.getFirst(oldId, countToProcess);
|
|
2480
|
+
countToProcess = rename1Entry.length;
|
|
2481
|
+
if (rename1Entry.value !== undefined) {
|
|
2482
|
+
deleteNodeRenameFrom(composedTable, rename1Entry.value, countToProcess);
|
|
2483
|
+
}
|
|
2484
|
+
addNodeRename(composedTable, rename1Entry.value ?? oldId, newId, countToProcess, detachLocation);
|
|
2485
|
+
tryRemoveDetachLocation(composedTable, newId, countToProcess);
|
|
2486
|
+
if (countToProcess < count) {
|
|
2487
|
+
const countRemaining = count - countToProcess;
|
|
2488
|
+
appendNodeRename(composedTable, (0, index_js_2.offsetChangeAtomId)(oldId, countToProcess), (0, index_js_2.offsetChangeAtomId)(newId, countToProcess), countRemaining, change1Table, detachLocation);
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
function tryRemoveDetachLocation(roots, rootId, count) {
|
|
2492
|
+
let countProcessed = count;
|
|
2493
|
+
const renameEntry = roots.oldToNewId.getFirst(rootId, countProcessed);
|
|
2494
|
+
countProcessed = renameEntry.length;
|
|
2495
|
+
const outputDetachEntry = roots.outputDetachLocations.getFirst(rootId, countProcessed);
|
|
2496
|
+
countProcessed = outputDetachEntry.length;
|
|
2497
|
+
const nodeChangeEntry = (0, changeAtomIdBTree_js_1.rangeQueryChangeAtomIdMap)(roots.nodeChanges, rootId, countProcessed);
|
|
2498
|
+
countProcessed = nodeChangeEntry.length;
|
|
2499
|
+
if (nodeChangeEntry.value === undefined &&
|
|
2500
|
+
renameEntry.value === undefined &&
|
|
2501
|
+
outputDetachEntry.value === undefined) {
|
|
2502
|
+
roots.detachLocations.delete(rootId, countProcessed);
|
|
2503
|
+
}
|
|
2504
|
+
const countRemaining = count - countProcessed;
|
|
2505
|
+
if (countRemaining > 0) {
|
|
2506
|
+
tryRemoveDetachLocation(roots, (0, index_js_2.offsetChangeAtomId)(rootId, countProcessed), countRemaining);
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
/**
|
|
2510
|
+
* Deletes the entry renaming the ID range of length `count` from `oldId` to `newId`.
|
|
2511
|
+
* This function assumes that such an entry exists.
|
|
2512
|
+
*/
|
|
2513
|
+
function deleteNodeRenameEntry(roots, oldId, newId, count) {
|
|
2514
|
+
roots.oldToNewId.delete(oldId, count);
|
|
2515
|
+
roots.newToOldId.delete(newId, count);
|
|
2516
|
+
}
|
|
2517
|
+
function replaceRootTableRevision(table, replacer, nodeAliases) {
|
|
2518
|
+
const oldToNewId = table.oldToNewId.mapEntries((id) => replacer.getUpdatedAtomId(id), (id) => replacer.getUpdatedAtomId(id));
|
|
2519
|
+
const newToOldId = table.newToOldId.mapEntries((id) => replacer.getUpdatedAtomId(id), (id) => replacer.getUpdatedAtomId(id));
|
|
2520
|
+
const nodeChanges = replaceIdMapRevisions(table.nodeChanges, replacer, (nodeId) => replacer.getUpdatedAtomId(normalizeNodeId(nodeId, nodeAliases)));
|
|
2521
|
+
const detachLocations = table.detachLocations.mapEntries((id) => replacer.getUpdatedAtomId(id), (fieldId) => replaceFieldIdRevision(normalizeFieldId(fieldId, nodeAliases), replacer));
|
|
2522
|
+
const outputDetachLocations = table.outputDetachLocations.mapEntries((id) => replacer.getUpdatedAtomId(id), (fieldId) => replaceFieldIdRevision(normalizeFieldId(fieldId, nodeAliases), replacer));
|
|
2523
|
+
return { oldToNewId, newToOldId, nodeChanges, detachLocations, outputDetachLocations };
|
|
2524
|
+
}
|
|
2525
|
+
function newDetachedEntryMap() {
|
|
2526
|
+
return new index_js_3.RangeMap(index_js_2.offsetChangeAtomId, index_js_2.subtractChangeAtomIds, offsetDetachedNodeEntry);
|
|
2527
|
+
}
|
|
2528
|
+
function offsetDetachedNodeEntry(entry, count) {
|
|
2529
|
+
(0, internal_1.assert)(count <= 1 || entry.nodeChange === undefined, "Cannot split an entry with a node change");
|
|
2530
|
+
return entry.detachId === undefined
|
|
2531
|
+
? entry
|
|
2532
|
+
: { ...entry, detachId: (0, index_js_2.offsetChangeAtomId)(entry.detachId, count) };
|
|
2533
|
+
}
|
|
2534
|
+
function getFieldsWithRootMoves(roots, nodeAliases) {
|
|
2535
|
+
const fields = newFieldIdKeyBTree();
|
|
2536
|
+
for (const { start: rootId, value: fieldId, length } of roots.detachLocations.entries()) {
|
|
2537
|
+
let isRootMoved = false;
|
|
2538
|
+
for (const renameEntry of roots.oldToNewId.getAll2(rootId, length)) {
|
|
2539
|
+
if (renameEntry.value !== undefined) {
|
|
2540
|
+
isRootMoved = true;
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
for (const outputDetachEntry of roots.outputDetachLocations.getAll2(rootId, length)) {
|
|
2544
|
+
if (outputDetachEntry.value !== undefined) {
|
|
2545
|
+
isRootMoved = true;
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
if (isRootMoved) {
|
|
2549
|
+
fields.set(fieldIdKeyFromFieldId(normalizeFieldId(fieldId, nodeAliases)), true);
|
|
2550
|
+
}
|
|
2551
|
+
}
|
|
2552
|
+
return fields;
|
|
2553
|
+
}
|
|
2554
|
+
function getFieldToRootChanges(roots, nodeAliases) {
|
|
2555
|
+
const fields = newFieldIdKeyBTree();
|
|
2556
|
+
for (const rootIdKey of roots.nodeChanges.keys()) {
|
|
2557
|
+
const rootId = { revision: rootIdKey[0], localId: rootIdKey[1] };
|
|
2558
|
+
const detachLocation = roots.detachLocations.getFirst(rootId, 1).value;
|
|
2559
|
+
if (detachLocation !== undefined) {
|
|
2560
|
+
const fieldIdKey = fieldIdKeyFromFieldId(normalizeFieldId(detachLocation, nodeAliases));
|
|
2561
|
+
let rootsInField = fields.get(fieldIdKey);
|
|
2562
|
+
if (rootsInField === undefined) {
|
|
2563
|
+
rootsInField = [];
|
|
2564
|
+
fields.set(fieldIdKey, rootsInField);
|
|
2565
|
+
}
|
|
2566
|
+
rootsInField.push(rootId);
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
return fields;
|
|
2570
|
+
}
|
|
2571
|
+
function muteRootChanges(roots) {
|
|
2572
|
+
return {
|
|
2573
|
+
oldToNewId: (0, index_js_2.newChangeAtomIdTransform)(),
|
|
2574
|
+
newToOldId: (0, index_js_2.newChangeAtomIdTransform)(),
|
|
2575
|
+
nodeChanges: (0, index_js_3.brand)(roots.nodeChanges.clone()),
|
|
2576
|
+
detachLocations: roots.detachLocations.clone(),
|
|
2577
|
+
outputDetachLocations: (0, index_js_2.newChangeAtomIdRangeMap)(),
|
|
2578
|
+
};
|
|
2579
|
+
}
|
|
2580
|
+
function validateChangeset(change, fieldKinds) {
|
|
2581
|
+
const unreachableNodes = (0, index_js_3.brand)(change.nodeToParent.clone());
|
|
2582
|
+
const unreachableCFKs = change.crossFieldKeys.clone();
|
|
2583
|
+
validateFieldChanges(fieldKinds, change, change.fieldChanges, undefined, unreachableNodes, unreachableCFKs);
|
|
2584
|
+
for (const [[revision, localId], node] of change.nodeChanges.entries()) {
|
|
2585
|
+
if (node.fieldChanges === undefined) {
|
|
2586
|
+
continue;
|
|
2587
|
+
}
|
|
2588
|
+
const nodeId = normalizeNodeId({ revision, localId }, change.nodeAliases);
|
|
2589
|
+
validateFieldChanges(fieldKinds, change, node.fieldChanges, nodeId, unreachableNodes, unreachableCFKs);
|
|
2590
|
+
}
|
|
2591
|
+
for (const [detachIdKey, nodeId] of change.rootNodes.nodeChanges.entries()) {
|
|
2592
|
+
const detachId = { revision: detachIdKey[0], localId: detachIdKey[1] };
|
|
2593
|
+
const location = getNodeParent(change, nodeId);
|
|
2594
|
+
(0, internal_1.assert)((0, index_js_2.areEqualChangeAtomIdOpts)(location.root, detachId), "Inconsistent node location");
|
|
2595
|
+
const normalizedNodeId = normalizeNodeId(nodeId, change.nodeAliases);
|
|
2596
|
+
unreachableNodes.delete([normalizedNodeId.revision, normalizedNodeId.localId]);
|
|
2597
|
+
const fieldChanges = nodeChangeFromId(change.nodeChanges, change.nodeAliases, nodeId).fieldChanges;
|
|
2598
|
+
if (fieldChanges !== undefined) {
|
|
2599
|
+
validateFieldChanges(fieldKinds, change, fieldChanges, normalizedNodeId, unreachableNodes, unreachableCFKs);
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
if (!containsRollbacks(change)) {
|
|
2603
|
+
for (const entry of change.crossFieldKeys.entries()) {
|
|
2604
|
+
if (entry.start.target !== crossFieldQueries_js_1.NodeMoveType.Attach) {
|
|
2605
|
+
continue;
|
|
2606
|
+
}
|
|
2607
|
+
validateAttach(change, entry.start, entry.length);
|
|
2608
|
+
}
|
|
2609
|
+
}
|
|
2610
|
+
(0, internal_1.assert)(unreachableNodes.size === 0, "Unreachable nodes found");
|
|
2611
|
+
(0, internal_1.assert)(unreachableCFKs.entries().length === 0, "Unreachable cross-field keys found");
|
|
2612
|
+
}
|
|
2613
|
+
exports.validateChangeset = validateChangeset;
|
|
2614
|
+
function containsRollbacks(change) {
|
|
2615
|
+
if (change.revisions === undefined) {
|
|
2616
|
+
return false;
|
|
2617
|
+
}
|
|
2618
|
+
for (const revInfo of change.revisions) {
|
|
2619
|
+
if (revInfo.rollbackOf !== undefined) {
|
|
2620
|
+
return true;
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
return false;
|
|
2624
|
+
}
|
|
2625
|
+
function validateAttach(changeset, attachId, count) {
|
|
2626
|
+
let countProcessed = count;
|
|
2627
|
+
const buildEntry = hasBuildForIdRange(changeset.builds, attachId, count);
|
|
2628
|
+
countProcessed = buildEntry.length;
|
|
2629
|
+
const detachEntry = changeset.crossFieldKeys.getFirst({ ...attachId, target: crossFieldQueries_js_1.NodeMoveType.Detach }, countProcessed);
|
|
2630
|
+
countProcessed = detachEntry.length;
|
|
2631
|
+
const renameEntry = changeset.rootNodes.newToOldId.getFirst(attachId, countProcessed);
|
|
2632
|
+
countProcessed = renameEntry.length;
|
|
2633
|
+
// assert(
|
|
2634
|
+
// buildEntry.value || detachEntry.value !== undefined || renameEntry.value !== undefined,
|
|
2635
|
+
// "No build, detach, or rename found for attach",
|
|
2636
|
+
// );
|
|
2637
|
+
if (countProcessed < count) {
|
|
2638
|
+
validateAttach(changeset, (0, index_js_2.offsetChangeAtomId)(attachId, countProcessed), count - countProcessed);
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
function hasBuildForIdRange(builds, id, count) {
|
|
2642
|
+
if (builds === undefined) {
|
|
2643
|
+
return { value: false, length: count };
|
|
2644
|
+
}
|
|
2645
|
+
const prevBuildEntry = builds.nextLowerPair([id.revision, id.localId]);
|
|
2646
|
+
if (prevBuildEntry !== undefined) {
|
|
2647
|
+
const prevBuildKey = {
|
|
2648
|
+
revision: prevBuildEntry[0][0],
|
|
2649
|
+
localId: prevBuildEntry[0][1],
|
|
2650
|
+
};
|
|
2651
|
+
const prevBuildLength = prevBuildEntry[1].topLevelLength;
|
|
2652
|
+
const lastLocalId = prevBuildKey.localId + prevBuildLength - 1;
|
|
2653
|
+
if (prevBuildKey.revision === id.revision && lastLocalId >= id.localId) {
|
|
2654
|
+
return { value: true, length: Math.min(count, lastLocalId - id.localId + 1) };
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
const buildEntry = (0, changeAtomIdBTree_js_1.rangeQueryChangeAtomIdMap)(builds, id, count);
|
|
2658
|
+
const length = buildEntry.value === undefined ? buildEntry.length : buildEntry.value.topLevelLength;
|
|
2659
|
+
const hasBuild = buildEntry.value !== undefined;
|
|
2660
|
+
return { value: hasBuild, length };
|
|
2661
|
+
}
|
|
2662
|
+
/**
|
|
2663
|
+
* Asserts that each node has a correct entry in `change.nodeToParent`,
|
|
2664
|
+
* and each cross field key has a correct entry in `change.crossFieldKeys`.
|
|
2665
|
+
* @returns the number of children found.
|
|
2666
|
+
*/
|
|
2667
|
+
function validateFieldChanges(fieldKinds, change, fieldChanges, nodeParent, unreachableNodes, unreachableCFKs) {
|
|
2668
|
+
for (const [field, fieldChange] of fieldChanges.entries()) {
|
|
2669
|
+
const fieldId = { nodeId: nodeParent, field };
|
|
2670
|
+
const handler = getChangeHandler(fieldKinds, fieldChange.fieldKind);
|
|
2671
|
+
for (const [child, _index] of handler.getNestedChanges(fieldChange.change)) {
|
|
2672
|
+
const parentFieldId = getNodeParent(change, child);
|
|
2673
|
+
(0, internal_1.assert)(parentFieldId.field !== undefined && areEqualFieldIds(parentFieldId.field, fieldId), 0xa4e /* Inconsistent node parentage */);
|
|
2674
|
+
unreachableNodes.delete([child.revision, child.localId]);
|
|
2675
|
+
}
|
|
2676
|
+
for (const keyRange of handler.getCrossFieldKeys(fieldChange.change)) {
|
|
2677
|
+
const fields = getFieldsForCrossFieldKey(change, keyRange.key, keyRange.count);
|
|
2678
|
+
(0, internal_1.assert)(fields.length > 0, "Unregistered cross-field key");
|
|
2679
|
+
for (const fieldFromLookup of fields) {
|
|
2680
|
+
(0, internal_1.assert)(areEqualFieldIds(fieldFromLookup, fieldId), 0xa4f /* Inconsistent cross field keys */);
|
|
2681
|
+
}
|
|
2682
|
+
unreachableCFKs.delete(keyRange.key, keyRange.count);
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
1758
2685
|
}
|
|
1759
2686
|
function newFieldIdKeyBTree() {
|
|
1760
2687
|
return (0, index_js_3.newTupleBTree)(compareFieldIdKeys);
|
|
1761
2688
|
}
|
|
2689
|
+
exports.newFieldIdKeyBTree = newFieldIdKeyBTree;
|
|
1762
2690
|
const compareFieldIdKeys = (0, index_js_3.createTupleComparator)([
|
|
1763
2691
|
index_js_2.comparePartialRevisions,
|
|
1764
2692
|
index_js_2.comparePartialChangesetLocalIds,
|