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