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