@fluidframework/tree 2.74.0-365691 → 2.74.0-368706
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 +2 -2
- package/api-report/tree.alpha.api.md +119 -85
- package/api-report/tree.beta.api.md +0 -1
- package/api-report/tree.legacy.beta.api.md +0 -1
- package/api-report/tree.legacy.public.api.md +0 -1
- package/api-report/tree.public.api.md +0 -1
- package/dist/alpha.d.ts +3 -2
- package/dist/codec/codec.d.ts +14 -1
- package/dist/codec/codec.d.ts.map +1 -1
- package/dist/codec/codec.js +11 -0
- package/dist/codec/codec.js.map +1 -1
- package/dist/codec/versioned/codec.d.ts +1 -1
- package/dist/codec/versioned/codec.d.ts.map +1 -1
- package/dist/codec/versioned/codec.js.map +1 -1
- package/dist/codec/versioned/format.d.ts +4 -1
- package/dist/codec/versioned/format.d.ts.map +1 -1
- package/dist/codec/versioned/format.js +4 -1
- package/dist/codec/versioned/format.js.map +1 -1
- package/dist/core/change-family/changeFamily.d.ts +4 -1
- package/dist/core/change-family/changeFamily.d.ts.map +1 -1
- package/dist/core/change-family/changeFamily.js.map +1 -1
- package/dist/core/change-family/index.d.ts +1 -1
- package/dist/core/change-family/index.d.ts.map +1 -1
- package/dist/core/change-family/index.js.map +1 -1
- package/dist/core/index.d.ts +3 -3
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +7 -4
- package/dist/core/index.js.map +1 -1
- package/dist/core/rebase/changeRebaser.d.ts +6 -1
- package/dist/core/rebase/changeRebaser.d.ts.map +1 -1
- package/dist/core/rebase/changeRebaser.js.map +1 -1
- package/dist/core/rebase/index.d.ts +1 -1
- package/dist/core/rebase/index.d.ts.map +1 -1
- package/dist/core/rebase/index.js +2 -1
- package/dist/core/rebase/index.js.map +1 -1
- package/dist/core/rebase/types.d.ts +2 -1
- package/dist/core/rebase/types.d.ts.map +1 -1
- package/dist/core/rebase/types.js +5 -1
- package/dist/core/rebase/types.js.map +1 -1
- package/dist/core/rebase/utils.d.ts.map +1 -1
- package/dist/core/rebase/utils.js +25 -7
- package/dist/core/rebase/utils.js.map +1 -1
- package/dist/core/tree/detachedFieldIndex.d.ts +40 -13
- package/dist/core/tree/detachedFieldIndex.d.ts.map +1 -1
- package/dist/core/tree/detachedFieldIndex.js +21 -12
- package/dist/core/tree/detachedFieldIndex.js.map +1 -1
- package/dist/core/tree/index.d.ts +4 -3
- package/dist/core/tree/index.d.ts.map +1 -1
- package/dist/core/tree/index.js +6 -2
- package/dist/core/tree/index.js.map +1 -1
- package/dist/core/tree/pathTree.d.ts +11 -3
- package/dist/core/tree/pathTree.d.ts.map +1 -1
- package/dist/core/tree/pathTree.js +14 -2
- package/dist/core/tree/pathTree.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/basicChunk.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/basicChunk.js +7 -0
- package/dist/feature-libraries/chunked-forest/basicChunk.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/chunkTree.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/chunkTree.js +4 -1
- package/dist/feature-libraries/chunked-forest/chunkTree.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/incrementalEncodingPolicy.d.ts +14 -6
- package/dist/feature-libraries/chunked-forest/codec/incrementalEncodingPolicy.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/incrementalEncodingPolicy.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/schemaBasedEncode.js +7 -2
- package/dist/feature-libraries/chunked-forest/codec/schemaBasedEncode.js.map +1 -1
- package/dist/feature-libraries/default-schema/defaultEditBuilder.d.ts +90 -42
- package/dist/feature-libraries/default-schema/defaultEditBuilder.d.ts.map +1 -1
- package/dist/feature-libraries/default-schema/defaultEditBuilder.js +234 -69
- package/dist/feature-libraries/default-schema/defaultEditBuilder.js.map +1 -1
- package/dist/feature-libraries/default-schema/defaultFieldKinds.d.ts +4 -4
- package/dist/feature-libraries/default-schema/defaultFieldKinds.d.ts.map +1 -1
- package/dist/feature-libraries/default-schema/defaultFieldKinds.js +33 -28
- package/dist/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
- package/dist/feature-libraries/default-schema/index.d.ts +2 -1
- package/dist/feature-libraries/default-schema/index.d.ts.map +1 -1
- package/dist/feature-libraries/default-schema/index.js +4 -2
- package/dist/feature-libraries/default-schema/index.js.map +1 -1
- package/dist/feature-libraries/default-schema/locationBasedEditBuilder.d.ts +36 -0
- package/dist/feature-libraries/default-schema/locationBasedEditBuilder.d.ts.map +1 -0
- package/dist/feature-libraries/default-schema/locationBasedEditBuilder.js +126 -0
- package/dist/feature-libraries/default-schema/locationBasedEditBuilder.js.map +1 -0
- package/dist/feature-libraries/default-schema/mappedEditBuilder.d.ts +7 -6
- package/dist/feature-libraries/default-schema/mappedEditBuilder.d.ts.map +1 -1
- package/dist/feature-libraries/default-schema/mappedEditBuilder.js +15 -0
- package/dist/feature-libraries/default-schema/mappedEditBuilder.js.map +1 -1
- package/dist/feature-libraries/deltaUtils.d.ts +1 -0
- package/dist/feature-libraries/deltaUtils.d.ts.map +1 -1
- package/dist/feature-libraries/deltaUtils.js +6 -1
- package/dist/feature-libraries/deltaUtils.js.map +1 -1
- package/dist/feature-libraries/detachedFieldIndexSummarizer.d.ts +30 -8
- package/dist/feature-libraries/detachedFieldIndexSummarizer.d.ts.map +1 -1
- package/dist/feature-libraries/detachedFieldIndexSummarizer.js +41 -11
- package/dist/feature-libraries/detachedFieldIndexSummarizer.js.map +1 -1
- package/dist/feature-libraries/flex-tree/context.d.ts +9 -0
- package/dist/feature-libraries/flex-tree/context.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/context.js +6 -0
- package/dist/feature-libraries/flex-tree/context.js.map +1 -1
- package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts +6 -6
- package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.d.ts +8 -7
- package/dist/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.js +37 -8
- package/dist/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/dist/feature-libraries/forest-summary/codec.d.ts +2 -2
- package/dist/feature-libraries/forest-summary/codec.d.ts.map +1 -1
- package/dist/feature-libraries/forest-summary/codec.js +4 -4
- package/dist/feature-libraries/forest-summary/codec.js.map +1 -1
- package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts +9 -13
- package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
- package/dist/feature-libraries/forest-summary/forestSummarizer.js +21 -26
- package/dist/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
- package/dist/feature-libraries/forest-summary/format.d.ts +41 -5
- package/dist/feature-libraries/forest-summary/format.d.ts.map +1 -1
- package/dist/feature-libraries/forest-summary/format.js +7 -7
- package/dist/feature-libraries/forest-summary/format.js.map +1 -1
- package/dist/feature-libraries/forest-summary/incrementalSummaryBuilder.d.ts +11 -9
- package/dist/feature-libraries/forest-summary/incrementalSummaryBuilder.d.ts.map +1 -1
- package/dist/feature-libraries/forest-summary/incrementalSummaryBuilder.js +16 -29
- package/dist/feature-libraries/forest-summary/incrementalSummaryBuilder.js.map +1 -1
- package/dist/feature-libraries/forest-summary/index.d.ts +2 -1
- package/dist/feature-libraries/forest-summary/index.d.ts.map +1 -1
- package/dist/feature-libraries/forest-summary/index.js +3 -2
- package/dist/feature-libraries/forest-summary/index.js.map +1 -1
- package/dist/feature-libraries/forest-summary/summaryTypes.d.ts +47 -0
- package/dist/feature-libraries/forest-summary/summaryTypes.d.ts.map +1 -0
- package/dist/feature-libraries/forest-summary/summaryTypes.js +57 -0
- package/dist/feature-libraries/forest-summary/summaryTypes.js.map +1 -0
- package/dist/feature-libraries/index.d.ts +4 -4
- package/dist/feature-libraries/index.d.ts.map +1 -1
- package/dist/feature-libraries/index.js +7 -3
- package/dist/feature-libraries/index.js.map +1 -1
- package/dist/feature-libraries/mapTreeCursor.d.ts.map +1 -1
- package/dist/feature-libraries/mapTreeCursor.js +1 -0
- package/dist/feature-libraries/mapTreeCursor.js.map +1 -1
- package/dist/feature-libraries/mitigatedChangeFamily.d.ts.map +1 -1
- package/dist/feature-libraries/mitigatedChangeFamily.js +2 -2
- package/dist/feature-libraries/mitigatedChangeFamily.js.map +1 -1
- package/dist/feature-libraries/modular-schema/comparison.d.ts +18 -2
- package/dist/feature-libraries/modular-schema/comparison.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/comparison.js +54 -3
- package/dist/feature-libraries/modular-schema/comparison.js.map +1 -1
- package/dist/feature-libraries/modular-schema/crossFieldQueries.d.ts +97 -21
- package/dist/feature-libraries/modular-schema/crossFieldQueries.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/crossFieldQueries.js +4 -7
- package/dist/feature-libraries/modular-schema/crossFieldQueries.js.map +1 -1
- package/dist/feature-libraries/modular-schema/fieldChangeHandler.d.ts +20 -52
- 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/fieldKind.d.ts +25 -13
- package/dist/feature-libraries/modular-schema/fieldKind.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/fieldKind.js +0 -21
- package/dist/feature-libraries/modular-schema/fieldKind.js.map +1 -1
- package/dist/feature-libraries/modular-schema/genericFieldKind.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/genericFieldKind.js +7 -10
- package/dist/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
- package/dist/feature-libraries/modular-schema/genericFieldKindCodecs.js +2 -2
- package/dist/feature-libraries/modular-schema/genericFieldKindCodecs.js.map +1 -1
- package/dist/feature-libraries/modular-schema/index.d.ts +5 -5
- package/dist/feature-libraries/modular-schema/index.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/index.js +12 -8
- package/dist/feature-libraries/modular-schema/index.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecV1.d.ts +17 -0
- package/dist/feature-libraries/modular-schema/modularChangeCodecV1.d.ts.map +1 -0
- package/dist/feature-libraries/modular-schema/modularChangeCodecV1.js +388 -0
- package/dist/feature-libraries/modular-schema/modularChangeCodecV1.js.map +1 -0
- package/dist/feature-libraries/modular-schema/modularChangeCodecV2.d.ts +17 -0
- package/dist/feature-libraries/modular-schema/modularChangeCodecV2.d.ts.map +1 -0
- package/dist/feature-libraries/modular-schema/modularChangeCodecV2.js +413 -0
- package/dist/feature-libraries/modular-schema/modularChangeCodecV2.js.map +1 -0
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.d.ts +2 -2
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.js +8 -284
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts +48 -15
- package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.js +1298 -465
- package/dist/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
- package/dist/feature-libraries/modular-schema/{modularChangeFormat.d.ts → modularChangeFormatV1.d.ts} +2 -2
- package/dist/feature-libraries/modular-schema/modularChangeFormatV1.d.ts.map +1 -0
- package/dist/feature-libraries/modular-schema/{modularChangeFormat.js → modularChangeFormatV1.js} +5 -5
- package/dist/feature-libraries/modular-schema/modularChangeFormatV1.js.map +1 -0
- package/dist/feature-libraries/modular-schema/modularChangeFormatV2.d.ts +146 -0
- package/dist/feature-libraries/modular-schema/modularChangeFormatV2.d.ts.map +1 -0
- package/dist/feature-libraries/modular-schema/modularChangeFormatV2.js +32 -0
- package/dist/feature-libraries/modular-schema/modularChangeFormatV2.js.map +1 -0
- package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts +50 -10
- package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeTypes.js +24 -3
- package/dist/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
- package/dist/feature-libraries/optional-field/index.d.ts +2 -2
- package/dist/feature-libraries/optional-field/index.d.ts.map +1 -1
- package/dist/feature-libraries/optional-field/index.js +1 -2
- package/dist/feature-libraries/optional-field/index.js.map +1 -1
- package/dist/feature-libraries/optional-field/optionalField.d.ts +5 -26
- package/dist/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
- package/dist/feature-libraries/optional-field/optionalField.js +217 -451
- package/dist/feature-libraries/optional-field/optionalField.js.map +1 -1
- package/dist/feature-libraries/optional-field/optionalFieldChangeTypes.d.ts +24 -33
- package/dist/feature-libraries/optional-field/optionalFieldChangeTypes.d.ts.map +1 -1
- package/dist/feature-libraries/optional-field/optionalFieldChangeTypes.js.map +1 -1
- package/dist/feature-libraries/optional-field/optionalFieldCodecV2.d.ts +1 -1
- package/dist/feature-libraries/optional-field/optionalFieldCodecV2.d.ts.map +1 -1
- package/dist/feature-libraries/optional-field/optionalFieldCodecV2.js +57 -28
- package/dist/feature-libraries/optional-field/optionalFieldCodecV2.js.map +1 -1
- package/dist/feature-libraries/schema-index/schemaSummarizer.d.ts +27 -8
- package/dist/feature-libraries/schema-index/schemaSummarizer.d.ts.map +1 -1
- package/dist/feature-libraries/schema-index/schemaSummarizer.js +42 -16
- package/dist/feature-libraries/schema-index/schemaSummarizer.js.map +1 -1
- package/dist/feature-libraries/sequence-field/compose.d.ts +6 -7
- package/dist/feature-libraries/sequence-field/compose.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/compose.js +80 -256
- package/dist/feature-libraries/sequence-field/compose.js.map +1 -1
- package/dist/feature-libraries/sequence-field/helperTypes.d.ts +14 -10
- package/dist/feature-libraries/sequence-field/helperTypes.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/helperTypes.js.map +1 -1
- package/dist/feature-libraries/sequence-field/index.d.ts +2 -3
- package/dist/feature-libraries/sequence-field/index.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/index.js +1 -3
- package/dist/feature-libraries/sequence-field/index.js.map +1 -1
- package/dist/feature-libraries/sequence-field/invert.d.ts +3 -3
- package/dist/feature-libraries/sequence-field/invert.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/invert.js +65 -167
- package/dist/feature-libraries/sequence-field/invert.js.map +1 -1
- package/dist/feature-libraries/sequence-field/markQueue.d.ts +2 -2
- package/dist/feature-libraries/sequence-field/markQueue.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/markQueue.js.map +1 -1
- package/dist/feature-libraries/sequence-field/moveEffectTable.d.ts +4 -56
- package/dist/feature-libraries/sequence-field/moveEffectTable.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/moveEffectTable.js +7 -86
- 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 +106 -112
- package/dist/feature-libraries/sequence-field/rebase.js.map +1 -1
- package/dist/feature-libraries/sequence-field/replaceRevisions.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/replaceRevisions.js +16 -33
- package/dist/feature-libraries/sequence-field/replaceRevisions.js.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldChangeHandler.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldChangeHandler.js +0 -2
- package/dist/feature-libraries/sequence-field/sequenceFieldChangeHandler.js.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV2.d.ts +22 -4
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV2.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV2.js +358 -179
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV2.js.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV3.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV3.js +20 -60
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV3.js.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldEditor.d.ts +2 -2
- package/dist/feature-libraries/sequence-field/sequenceFieldEditor.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldEditor.js +10 -10
- package/dist/feature-libraries/sequence-field/sequenceFieldEditor.js.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts +3 -2
- package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.js +14 -109
- package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.js.map +1 -1
- package/dist/feature-libraries/sequence-field/types.d.ts +30 -59
- package/dist/feature-libraries/sequence-field/types.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/types.js.map +1 -1
- package/dist/feature-libraries/sequence-field/utils.d.ts +15 -24
- package/dist/feature-libraries/sequence-field/utils.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/utils.js +111 -299
- package/dist/feature-libraries/sequence-field/utils.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/shared-tree/independentView.d.ts +1 -1
- package/dist/shared-tree/independentView.d.ts.map +1 -1
- package/dist/shared-tree/independentView.js.map +1 -1
- package/dist/shared-tree/index.d.ts +1 -1
- package/dist/shared-tree/index.d.ts.map +1 -1
- package/dist/shared-tree/index.js.map +1 -1
- package/dist/shared-tree/schematizeTree.d.ts +4 -4
- package/dist/shared-tree/schematizeTree.d.ts.map +1 -1
- package/dist/shared-tree/schematizeTree.js +2 -1
- package/dist/shared-tree/schematizeTree.js.map +1 -1
- package/dist/shared-tree/schematizingTreeView.d.ts +1 -5
- package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/dist/shared-tree/schematizingTreeView.js +32 -33
- package/dist/shared-tree/schematizingTreeView.js.map +1 -1
- package/dist/shared-tree/sharedTree.d.ts +11 -5
- package/dist/shared-tree/sharedTree.d.ts.map +1 -1
- package/dist/shared-tree/sharedTree.js +14 -4
- package/dist/shared-tree/sharedTree.js.map +1 -1
- package/dist/shared-tree/sharedTreeChangeCodecs.d.ts +1 -1
- package/dist/shared-tree/sharedTreeChangeCodecs.d.ts.map +1 -1
- package/dist/shared-tree/sharedTreeChangeCodecs.js +1 -0
- package/dist/shared-tree/sharedTreeChangeCodecs.js.map +1 -1
- package/dist/shared-tree/sharedTreeChangeEnricher.d.ts +20 -8
- package/dist/shared-tree/sharedTreeChangeEnricher.d.ts.map +1 -1
- package/dist/shared-tree/sharedTreeChangeEnricher.js +25 -11
- package/dist/shared-tree/sharedTreeChangeEnricher.js.map +1 -1
- package/dist/shared-tree/sharedTreeChangeFamily.d.ts +4 -4
- package/dist/shared-tree/sharedTreeChangeFamily.d.ts.map +1 -1
- package/dist/shared-tree/sharedTreeChangeFamily.js +2 -2
- package/dist/shared-tree/sharedTreeChangeFamily.js.map +1 -1
- package/dist/shared-tree/sharedTreeEditBuilder.d.ts +16 -6
- package/dist/shared-tree/sharedTreeEditBuilder.d.ts.map +1 -1
- package/dist/shared-tree/sharedTreeEditBuilder.js +13 -6
- package/dist/shared-tree/sharedTreeEditBuilder.js.map +1 -1
- package/dist/shared-tree/treeAlpha.d.ts.map +1 -1
- package/dist/shared-tree/treeAlpha.js +1 -1
- package/dist/shared-tree/treeAlpha.js.map +1 -1
- package/dist/shared-tree/treeCheckout.d.ts +12 -10
- package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
- package/dist/shared-tree/treeCheckout.js +66 -17
- package/dist/shared-tree/treeCheckout.js.map +1 -1
- package/dist/shared-tree-core/branch.d.ts +3 -2
- package/dist/shared-tree-core/branch.d.ts.map +1 -1
- package/dist/shared-tree-core/branch.js +4 -3
- package/dist/shared-tree-core/branch.js.map +1 -1
- package/dist/shared-tree-core/editManager.d.ts +2 -2
- package/dist/shared-tree-core/editManager.d.ts.map +1 -1
- package/dist/shared-tree-core/editManager.js +9 -9
- package/dist/shared-tree-core/editManager.js.map +1 -1
- package/dist/shared-tree-core/editManagerCodecs.d.ts +4 -0
- package/dist/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerCodecs.js +16 -6
- package/dist/shared-tree-core/editManagerCodecs.js.map +1 -1
- package/{lib/shared-tree-core/editManagerCodecsV5.d.ts → dist/shared-tree-core/editManagerCodecsVSharedBranches.d.ts} +3 -3
- package/dist/shared-tree-core/editManagerCodecsVSharedBranches.d.ts.map +1 -0
- package/dist/shared-tree-core/{editManagerCodecsV5.js → editManagerCodecsVSharedBranches.js} +7 -7
- package/dist/shared-tree-core/editManagerCodecsVSharedBranches.js.map +1 -0
- package/dist/shared-tree-core/editManagerFormatCommons.d.ts +20 -6
- package/dist/shared-tree-core/editManagerFormatCommons.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerFormatCommons.js +22 -7
- package/dist/shared-tree-core/editManagerFormatCommons.js.map +1 -1
- package/dist/shared-tree-core/editManagerFormatV1toV4.d.ts +2 -2
- package/dist/shared-tree-core/editManagerFormatV1toV4.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerFormatV1toV4.js +1 -0
- package/dist/shared-tree-core/editManagerFormatV1toV4.js.map +1 -1
- package/dist/shared-tree-core/{editManagerFormatV5.d.ts → editManagerFormatVSharedBranches.d.ts} +3 -3
- package/dist/shared-tree-core/editManagerFormatVSharedBranches.d.ts.map +1 -0
- package/dist/shared-tree-core/{editManagerFormatV5.js → editManagerFormatVSharedBranches.js} +2 -2
- package/dist/shared-tree-core/editManagerFormatVSharedBranches.js.map +1 -0
- package/dist/shared-tree-core/editManagerSummarizer.d.ts +29 -9
- package/dist/shared-tree-core/editManagerSummarizer.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerSummarizer.js +41 -13
- package/dist/shared-tree-core/editManagerSummarizer.js.map +1 -1
- package/dist/shared-tree-core/index.d.ts +5 -3
- package/dist/shared-tree-core/index.d.ts.map +1 -1
- package/dist/shared-tree-core/index.js +8 -1
- package/dist/shared-tree-core/index.js.map +1 -1
- package/dist/shared-tree-core/messageCodecV1ToV4.d.ts +1 -1
- package/dist/shared-tree-core/messageCodecV1ToV4.d.ts.map +1 -1
- package/dist/shared-tree-core/messageCodecV1ToV4.js.map +1 -1
- package/{lib/shared-tree-core/messageCodecV5.d.ts → dist/shared-tree-core/messageCodecVSharedBranches.d.ts} +2 -2
- package/dist/shared-tree-core/messageCodecVSharedBranches.d.ts.map +1 -0
- package/dist/shared-tree-core/{messageCodecV5.js → messageCodecVSharedBranches.js} +6 -6
- package/dist/shared-tree-core/messageCodecVSharedBranches.js.map +1 -0
- package/dist/shared-tree-core/messageCodecs.d.ts +4 -0
- package/dist/shared-tree-core/messageCodecs.d.ts.map +1 -1
- package/dist/shared-tree-core/messageCodecs.js +16 -6
- package/dist/shared-tree-core/messageCodecs.js.map +1 -1
- package/dist/shared-tree-core/messageFormat.d.ts +20 -6
- package/dist/shared-tree-core/messageFormat.d.ts.map +1 -1
- package/dist/shared-tree-core/messageFormat.js +22 -7
- package/dist/shared-tree-core/messageFormat.js.map +1 -1
- package/dist/shared-tree-core/messageFormatV1ToV4.d.ts +3 -2
- package/dist/shared-tree-core/messageFormatV1ToV4.d.ts.map +1 -1
- package/dist/shared-tree-core/messageFormatV1ToV4.js +8 -1
- package/dist/shared-tree-core/messageFormatV1ToV4.js.map +1 -1
- package/dist/shared-tree-core/{messageFormatV5.d.ts → messageFormatVSharedBranches.d.ts} +5 -7
- package/dist/shared-tree-core/messageFormatVSharedBranches.d.ts.map +1 -0
- package/dist/shared-tree-core/{messageFormatV5.js → messageFormatVSharedBranches.js} +3 -2
- package/dist/shared-tree-core/messageFormatVSharedBranches.js.map +1 -0
- package/dist/shared-tree-core/sharedTreeCore.d.ts +14 -47
- package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.js +30 -18
- package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/dist/shared-tree-core/summaryTypes.d.ts +94 -0
- package/dist/shared-tree-core/summaryTypes.d.ts.map +1 -0
- package/dist/shared-tree-core/summaryTypes.js +47 -0
- package/dist/shared-tree-core/summaryTypes.js.map +1 -0
- package/dist/shared-tree-core/versionedSummarizer.d.ts +67 -0
- package/dist/shared-tree-core/versionedSummarizer.d.ts.map +1 -0
- package/dist/shared-tree-core/versionedSummarizer.js +63 -0
- package/dist/shared-tree-core/versionedSummarizer.js.map +1 -0
- package/dist/simple-tree/api/configuration.d.ts +3 -26
- package/dist/simple-tree/api/configuration.d.ts.map +1 -1
- package/dist/simple-tree/api/configuration.js +10 -21
- package/dist/simple-tree/api/configuration.js.map +1 -1
- package/dist/simple-tree/api/dirtyIndex.d.ts +11 -0
- package/dist/simple-tree/api/dirtyIndex.d.ts.map +1 -1
- package/dist/simple-tree/api/dirtyIndex.js +7 -0
- package/dist/simple-tree/api/dirtyIndex.js.map +1 -1
- package/dist/simple-tree/api/discrepancies.d.ts +1 -1
- package/dist/simple-tree/api/discrepancies.d.ts.map +1 -1
- package/dist/simple-tree/api/discrepancies.js.map +1 -1
- package/dist/simple-tree/api/getSimpleSchema.d.ts +3 -3
- package/dist/simple-tree/api/getSimpleSchema.d.ts.map +1 -1
- package/dist/simple-tree/api/getSimpleSchema.js +9 -3
- package/dist/simple-tree/api/getSimpleSchema.js.map +1 -1
- package/dist/simple-tree/api/incrementalAllowedTypes.d.ts +1 -1
- package/dist/simple-tree/api/incrementalAllowedTypes.d.ts.map +1 -1
- package/dist/simple-tree/api/incrementalAllowedTypes.js +7 -0
- package/dist/simple-tree/api/incrementalAllowedTypes.js.map +1 -1
- package/dist/simple-tree/api/index.d.ts +3 -4
- package/dist/simple-tree/api/index.d.ts.map +1 -1
- package/dist/simple-tree/api/index.js +4 -5
- package/dist/simple-tree/api/index.js.map +1 -1
- package/dist/simple-tree/api/schemaCompatibilityTester.d.ts +1 -1
- package/dist/simple-tree/api/schemaCompatibilityTester.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaCompatibilityTester.js.map +1 -1
- package/dist/simple-tree/api/schemaFactoryAlpha.d.ts +5 -5
- package/dist/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaFactoryAlpha.js.map +1 -1
- package/dist/simple-tree/api/schemaFactoryRecursive.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaFactoryRecursive.js +0 -1
- package/dist/simple-tree/api/schemaFactoryRecursive.js.map +1 -1
- package/dist/simple-tree/api/schemaFromSimple.d.ts +6 -1
- package/dist/simple-tree/api/schemaFromSimple.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaFromSimple.js +5 -0
- package/dist/simple-tree/api/schemaFromSimple.js.map +1 -1
- package/dist/simple-tree/api/schemaStatics.d.ts +12 -12
- package/dist/simple-tree/api/simpleSchemaCodec.d.ts +15 -3
- package/dist/simple-tree/api/simpleSchemaCodec.d.ts.map +1 -1
- package/dist/simple-tree/api/simpleSchemaCodec.js +18 -6
- package/dist/simple-tree/api/simpleSchemaCodec.js.map +1 -1
- package/dist/simple-tree/api/simpleSchemaToJsonSchema.d.ts +1 -1
- package/dist/simple-tree/api/simpleSchemaToJsonSchema.d.ts.map +1 -1
- package/dist/simple-tree/api/simpleSchemaToJsonSchema.js.map +1 -1
- package/dist/simple-tree/api/snapshotCompatibilityChecker.d.ts +8 -1
- package/dist/simple-tree/api/snapshotCompatibilityChecker.d.ts.map +1 -1
- package/dist/simple-tree/api/snapshotCompatibilityChecker.js +13 -8
- package/dist/simple-tree/api/snapshotCompatibilityChecker.js.map +1 -1
- package/dist/simple-tree/api/typesUnsafe.d.ts +3 -3
- package/dist/simple-tree/api/typesUnsafe.d.ts.map +1 -1
- package/dist/simple-tree/api/typesUnsafe.js.map +1 -1
- package/dist/simple-tree/core/allowedTypes.d.ts +2 -2
- package/dist/simple-tree/core/allowedTypes.d.ts.map +1 -1
- package/dist/simple-tree/core/allowedTypes.js.map +1 -1
- package/dist/simple-tree/core/index.d.ts +1 -1
- package/dist/simple-tree/core/index.d.ts.map +1 -1
- package/dist/simple-tree/core/index.js +2 -3
- package/dist/simple-tree/core/index.js.map +1 -1
- package/dist/simple-tree/core/toStored.d.ts +17 -15
- package/dist/simple-tree/core/toStored.d.ts.map +1 -1
- package/dist/simple-tree/core/toStored.js +5 -40
- package/dist/simple-tree/core/toStored.js.map +1 -1
- package/dist/simple-tree/core/unhydratedFlexTree.d.ts +15 -15
- package/dist/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
- package/dist/simple-tree/core/unhydratedFlexTree.js +59 -8
- package/dist/simple-tree/core/unhydratedFlexTree.js.map +1 -1
- package/dist/simple-tree/core/walkSchema.d.ts.map +1 -1
- package/dist/simple-tree/core/walkSchema.js +4 -0
- package/dist/simple-tree/core/walkSchema.js.map +1 -1
- package/dist/simple-tree/createContext.d.ts.map +1 -1
- package/dist/simple-tree/createContext.js +20 -5
- package/dist/simple-tree/createContext.js.map +1 -1
- package/dist/simple-tree/fieldSchema.d.ts +7 -7
- 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 +8 -7
- package/dist/simple-tree/index.d.ts.map +1 -1
- package/dist/simple-tree/index.js +15 -12
- package/dist/simple-tree/index.js.map +1 -1
- package/dist/simple-tree/leafNodeSchema.d.ts +5 -5
- package/dist/simple-tree/leafNodeSchema.d.ts.map +1 -1
- package/dist/simple-tree/node-kinds/array/arrayNode.d.ts.map +1 -1
- package/dist/simple-tree/node-kinds/array/arrayNode.js +5 -3
- package/dist/simple-tree/node-kinds/array/arrayNode.js.map +1 -1
- package/dist/simple-tree/node-kinds/array/arrayNodeTypes.d.ts +3 -3
- package/dist/simple-tree/node-kinds/array/arrayNodeTypes.d.ts.map +1 -1
- package/dist/simple-tree/node-kinds/array/arrayNodeTypes.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.d.ts.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/map/mapNodeTypes.d.ts +3 -3
- package/dist/simple-tree/node-kinds/map/mapNodeTypes.d.ts.map +1 -1
- package/dist/simple-tree/node-kinds/map/mapNodeTypes.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 +18 -18
- package/dist/simple-tree/node-kinds/object/objectNode.js.map +1 -1
- package/dist/simple-tree/node-kinds/object/objectNodeTypes.d.ts +2 -2
- package/dist/simple-tree/node-kinds/object/objectNodeTypes.d.ts.map +1 -1
- package/dist/simple-tree/node-kinds/object/objectNodeTypes.js.map +1 -1
- package/dist/simple-tree/node-kinds/record/recordNode.d.ts.map +1 -1
- package/dist/simple-tree/node-kinds/record/recordNode.js +4 -2
- package/dist/simple-tree/node-kinds/record/recordNode.js.map +1 -1
- package/dist/simple-tree/node-kinds/record/recordNodeTypes.d.ts +3 -3
- package/dist/simple-tree/node-kinds/record/recordNodeTypes.d.ts.map +1 -1
- package/dist/simple-tree/node-kinds/record/recordNodeTypes.js.map +1 -1
- package/dist/simple-tree/prepareForInsertion.d.ts +54 -47
- package/dist/simple-tree/prepareForInsertion.d.ts.map +1 -1
- package/dist/simple-tree/prepareForInsertion.js +183 -125
- package/dist/simple-tree/prepareForInsertion.js.map +1 -1
- package/dist/simple-tree/simpleSchema.d.ts +55 -23
- package/dist/simple-tree/simpleSchema.d.ts.map +1 -1
- package/dist/simple-tree/simpleSchema.js +17 -0
- package/dist/simple-tree/simpleSchema.js.map +1 -1
- package/dist/simple-tree/simpleSchemaFormatV1.d.ts +1 -1
- package/dist/simple-tree/simpleSchemaFormatV1.d.ts.map +1 -1
- package/dist/simple-tree/simpleSchemaFormatV1.js +8 -1
- package/dist/simple-tree/simpleSchemaFormatV1.js.map +1 -1
- package/dist/simple-tree/toStoredSchema.d.ts +58 -11
- package/dist/simple-tree/toStoredSchema.d.ts.map +1 -1
- package/dist/simple-tree/toStoredSchema.js +205 -30
- package/dist/simple-tree/toStoredSchema.js.map +1 -1
- package/dist/simple-tree/treeSchema.d.ts +23 -0
- package/dist/simple-tree/treeSchema.d.ts.map +1 -0
- package/dist/simple-tree/treeSchema.js +25 -0
- package/dist/simple-tree/treeSchema.js.map +1 -0
- package/dist/simple-tree/unhydratedFlexTreeFromInsertable.d.ts +13 -4
- package/dist/simple-tree/unhydratedFlexTreeFromInsertable.d.ts.map +1 -1
- package/dist/simple-tree/unhydratedFlexTreeFromInsertable.js +29 -11
- package/dist/simple-tree/unhydratedFlexTreeFromInsertable.js.map +1 -1
- package/dist/tableSchema.d.ts +117 -63
- package/dist/tableSchema.d.ts.map +1 -1
- package/dist/tableSchema.js +159 -58
- package/dist/tableSchema.js.map +1 -1
- package/dist/treeFactory.d.ts.map +1 -1
- package/dist/treeFactory.js +17 -3
- package/dist/treeFactory.js.map +1 -1
- package/dist/util/index.d.ts +2 -1
- package/dist/util/index.d.ts.map +1 -1
- package/dist/util/index.js +4 -1
- package/dist/util/index.js.map +1 -1
- package/dist/util/rangeMap.d.ts +24 -12
- package/dist/util/rangeMap.d.ts.map +1 -1
- package/dist/util/rangeMap.js +46 -6
- package/dist/util/rangeMap.js.map +1 -1
- package/dist/util/readSnapshotBlob.d.ts +13 -0
- package/dist/util/readSnapshotBlob.d.ts.map +1 -0
- package/dist/util/readSnapshotBlob.js +18 -0
- package/dist/util/readSnapshotBlob.js.map +1 -0
- package/lib/alpha.d.ts +3 -2
- package/lib/codec/codec.d.ts +14 -1
- package/lib/codec/codec.d.ts.map +1 -1
- package/lib/codec/codec.js +11 -0
- package/lib/codec/codec.js.map +1 -1
- package/lib/codec/versioned/codec.d.ts +1 -1
- package/lib/codec/versioned/codec.d.ts.map +1 -1
- package/lib/codec/versioned/codec.js.map +1 -1
- package/lib/codec/versioned/format.d.ts +4 -1
- package/lib/codec/versioned/format.d.ts.map +1 -1
- package/lib/codec/versioned/format.js +4 -1
- package/lib/codec/versioned/format.js.map +1 -1
- package/lib/core/change-family/changeFamily.d.ts +4 -1
- package/lib/core/change-family/changeFamily.d.ts.map +1 -1
- package/lib/core/change-family/changeFamily.js.map +1 -1
- package/lib/core/change-family/index.d.ts +1 -1
- package/lib/core/change-family/index.d.ts.map +1 -1
- package/lib/core/change-family/index.js.map +1 -1
- package/lib/core/index.d.ts +3 -3
- package/lib/core/index.d.ts.map +1 -1
- package/lib/core/index.js +2 -2
- package/lib/core/index.js.map +1 -1
- package/lib/core/rebase/changeRebaser.d.ts +6 -1
- package/lib/core/rebase/changeRebaser.d.ts.map +1 -1
- package/lib/core/rebase/changeRebaser.js.map +1 -1
- package/lib/core/rebase/index.d.ts +1 -1
- package/lib/core/rebase/index.d.ts.map +1 -1
- package/lib/core/rebase/index.js +1 -1
- package/lib/core/rebase/index.js.map +1 -1
- package/lib/core/rebase/types.d.ts +2 -1
- package/lib/core/rebase/types.d.ts.map +1 -1
- package/lib/core/rebase/types.js +3 -0
- package/lib/core/rebase/types.js.map +1 -1
- package/lib/core/rebase/utils.d.ts.map +1 -1
- package/lib/core/rebase/utils.js +25 -7
- package/lib/core/rebase/utils.js.map +1 -1
- package/lib/core/tree/detachedFieldIndex.d.ts +40 -13
- package/lib/core/tree/detachedFieldIndex.d.ts.map +1 -1
- package/lib/core/tree/detachedFieldIndex.js +22 -13
- package/lib/core/tree/detachedFieldIndex.js.map +1 -1
- package/lib/core/tree/index.d.ts +4 -3
- package/lib/core/tree/index.d.ts.map +1 -1
- package/lib/core/tree/index.js +3 -2
- package/lib/core/tree/index.js.map +1 -1
- package/lib/core/tree/pathTree.d.ts +11 -3
- package/lib/core/tree/pathTree.d.ts.map +1 -1
- package/lib/core/tree/pathTree.js +12 -1
- package/lib/core/tree/pathTree.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/basicChunk.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/basicChunk.js +8 -1
- package/lib/feature-libraries/chunked-forest/basicChunk.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/chunkTree.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/chunkTree.js +4 -1
- package/lib/feature-libraries/chunked-forest/chunkTree.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/incrementalEncodingPolicy.d.ts +14 -6
- package/lib/feature-libraries/chunked-forest/codec/incrementalEncodingPolicy.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/incrementalEncodingPolicy.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/schemaBasedEncode.js +7 -2
- package/lib/feature-libraries/chunked-forest/codec/schemaBasedEncode.js.map +1 -1
- package/lib/feature-libraries/default-schema/defaultEditBuilder.d.ts +90 -42
- package/lib/feature-libraries/default-schema/defaultEditBuilder.d.ts.map +1 -1
- package/lib/feature-libraries/default-schema/defaultEditBuilder.js +232 -69
- package/lib/feature-libraries/default-schema/defaultEditBuilder.js.map +1 -1
- package/lib/feature-libraries/default-schema/defaultFieldKinds.d.ts +4 -4
- package/lib/feature-libraries/default-schema/defaultFieldKinds.d.ts.map +1 -1
- package/lib/feature-libraries/default-schema/defaultFieldKinds.js +34 -29
- package/lib/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
- package/lib/feature-libraries/default-schema/index.d.ts +2 -1
- package/lib/feature-libraries/default-schema/index.d.ts.map +1 -1
- package/lib/feature-libraries/default-schema/index.js +2 -1
- package/lib/feature-libraries/default-schema/index.js.map +1 -1
- package/lib/feature-libraries/default-schema/locationBasedEditBuilder.d.ts +36 -0
- package/lib/feature-libraries/default-schema/locationBasedEditBuilder.d.ts.map +1 -0
- package/lib/feature-libraries/default-schema/locationBasedEditBuilder.js +122 -0
- package/lib/feature-libraries/default-schema/locationBasedEditBuilder.js.map +1 -0
- package/lib/feature-libraries/default-schema/mappedEditBuilder.d.ts +7 -6
- package/lib/feature-libraries/default-schema/mappedEditBuilder.d.ts.map +1 -1
- package/lib/feature-libraries/default-schema/mappedEditBuilder.js +15 -0
- package/lib/feature-libraries/default-schema/mappedEditBuilder.js.map +1 -1
- package/lib/feature-libraries/deltaUtils.d.ts +1 -0
- package/lib/feature-libraries/deltaUtils.d.ts.map +1 -1
- package/lib/feature-libraries/deltaUtils.js +5 -1
- package/lib/feature-libraries/deltaUtils.js.map +1 -1
- package/lib/feature-libraries/detachedFieldIndexSummarizer.d.ts +30 -8
- package/lib/feature-libraries/detachedFieldIndexSummarizer.d.ts.map +1 -1
- package/lib/feature-libraries/detachedFieldIndexSummarizer.js +38 -8
- package/lib/feature-libraries/detachedFieldIndexSummarizer.js.map +1 -1
- package/lib/feature-libraries/flex-tree/context.d.ts +9 -0
- package/lib/feature-libraries/flex-tree/context.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/context.js +6 -0
- package/lib/feature-libraries/flex-tree/context.js.map +1 -1
- package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts +6 -6
- package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.d.ts +8 -7
- package/lib/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.js +38 -9
- package/lib/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/lib/feature-libraries/forest-summary/codec.d.ts +2 -2
- package/lib/feature-libraries/forest-summary/codec.d.ts.map +1 -1
- package/lib/feature-libraries/forest-summary/codec.js +5 -5
- package/lib/feature-libraries/forest-summary/codec.js.map +1 -1
- package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts +9 -13
- package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
- package/lib/feature-libraries/forest-summary/forestSummarizer.js +17 -22
- package/lib/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
- package/lib/feature-libraries/forest-summary/format.d.ts +41 -5
- package/lib/feature-libraries/forest-summary/format.d.ts.map +1 -1
- package/lib/feature-libraries/forest-summary/format.js +3 -3
- package/lib/feature-libraries/forest-summary/format.js.map +1 -1
- package/lib/feature-libraries/forest-summary/incrementalSummaryBuilder.d.ts +11 -9
- package/lib/feature-libraries/forest-summary/incrementalSummaryBuilder.d.ts.map +1 -1
- package/lib/feature-libraries/forest-summary/incrementalSummaryBuilder.js +13 -26
- package/lib/feature-libraries/forest-summary/incrementalSummaryBuilder.js.map +1 -1
- package/lib/feature-libraries/forest-summary/index.d.ts +2 -1
- package/lib/feature-libraries/forest-summary/index.d.ts.map +1 -1
- package/lib/feature-libraries/forest-summary/index.js +2 -1
- package/lib/feature-libraries/forest-summary/index.js.map +1 -1
- package/lib/feature-libraries/forest-summary/summaryTypes.d.ts +47 -0
- package/lib/feature-libraries/forest-summary/summaryTypes.d.ts.map +1 -0
- package/lib/feature-libraries/forest-summary/summaryTypes.js +53 -0
- package/lib/feature-libraries/forest-summary/summaryTypes.js.map +1 -0
- package/lib/feature-libraries/index.d.ts +4 -4
- package/lib/feature-libraries/index.d.ts.map +1 -1
- package/lib/feature-libraries/index.js +3 -3
- package/lib/feature-libraries/index.js.map +1 -1
- package/lib/feature-libraries/mapTreeCursor.d.ts.map +1 -1
- package/lib/feature-libraries/mapTreeCursor.js +2 -1
- package/lib/feature-libraries/mapTreeCursor.js.map +1 -1
- package/lib/feature-libraries/mitigatedChangeFamily.d.ts.map +1 -1
- package/lib/feature-libraries/mitigatedChangeFamily.js +2 -2
- package/lib/feature-libraries/mitigatedChangeFamily.js.map +1 -1
- package/lib/feature-libraries/modular-schema/comparison.d.ts +18 -2
- package/lib/feature-libraries/modular-schema/comparison.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/comparison.js +55 -5
- package/lib/feature-libraries/modular-schema/comparison.js.map +1 -1
- package/lib/feature-libraries/modular-schema/crossFieldQueries.d.ts +97 -21
- package/lib/feature-libraries/modular-schema/crossFieldQueries.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/crossFieldQueries.js +3 -5
- package/lib/feature-libraries/modular-schema/crossFieldQueries.js.map +1 -1
- package/lib/feature-libraries/modular-schema/fieldChangeHandler.d.ts +20 -52
- 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/fieldKind.d.ts +25 -13
- package/lib/feature-libraries/modular-schema/fieldKind.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/fieldKind.js +0 -21
- package/lib/feature-libraries/modular-schema/fieldKind.js.map +1 -1
- package/lib/feature-libraries/modular-schema/genericFieldKind.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/genericFieldKind.js +7 -10
- package/lib/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
- package/lib/feature-libraries/modular-schema/genericFieldKindCodecs.js +1 -1
- package/lib/feature-libraries/modular-schema/genericFieldKindCodecs.js.map +1 -1
- package/lib/feature-libraries/modular-schema/index.d.ts +5 -5
- package/lib/feature-libraries/modular-schema/index.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/index.js +4 -3
- package/lib/feature-libraries/modular-schema/index.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecV1.d.ts +17 -0
- package/lib/feature-libraries/modular-schema/modularChangeCodecV1.d.ts.map +1 -0
- package/lib/feature-libraries/modular-schema/modularChangeCodecV1.js +384 -0
- package/lib/feature-libraries/modular-schema/modularChangeCodecV1.js.map +1 -0
- package/lib/feature-libraries/modular-schema/modularChangeCodecV2.d.ts +17 -0
- package/lib/feature-libraries/modular-schema/modularChangeCodecV2.d.ts.map +1 -0
- package/lib/feature-libraries/modular-schema/modularChangeCodecV2.js +409 -0
- package/lib/feature-libraries/modular-schema/modularChangeCodecV2.js.map +1 -0
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.d.ts +2 -2
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.js +9 -285
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts +48 -15
- package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFamily.js +1284 -458
- package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
- package/lib/feature-libraries/modular-schema/{modularChangeFormat.d.ts → modularChangeFormatV1.d.ts} +2 -2
- package/lib/feature-libraries/modular-schema/modularChangeFormatV1.d.ts.map +1 -0
- package/lib/feature-libraries/modular-schema/{modularChangeFormat.js → modularChangeFormatV1.js} +2 -2
- package/lib/feature-libraries/modular-schema/modularChangeFormatV1.js.map +1 -0
- package/lib/feature-libraries/modular-schema/modularChangeFormatV2.d.ts +146 -0
- package/lib/feature-libraries/modular-schema/modularChangeFormatV2.d.ts.map +1 -0
- package/lib/feature-libraries/modular-schema/modularChangeFormatV2.js +29 -0
- package/lib/feature-libraries/modular-schema/modularChangeFormatV2.js.map +1 -0
- package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts +50 -10
- package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeTypes.js +20 -2
- package/lib/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
- package/lib/feature-libraries/optional-field/index.d.ts +2 -2
- package/lib/feature-libraries/optional-field/index.d.ts.map +1 -1
- package/lib/feature-libraries/optional-field/index.js +1 -1
- package/lib/feature-libraries/optional-field/index.js.map +1 -1
- package/lib/feature-libraries/optional-field/optionalField.d.ts +5 -26
- package/lib/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
- package/lib/feature-libraries/optional-field/optionalField.js +217 -449
- package/lib/feature-libraries/optional-field/optionalField.js.map +1 -1
- package/lib/feature-libraries/optional-field/optionalFieldChangeTypes.d.ts +24 -33
- package/lib/feature-libraries/optional-field/optionalFieldChangeTypes.d.ts.map +1 -1
- package/lib/feature-libraries/optional-field/optionalFieldChangeTypes.js.map +1 -1
- package/lib/feature-libraries/optional-field/optionalFieldCodecV2.d.ts +1 -1
- package/lib/feature-libraries/optional-field/optionalFieldCodecV2.d.ts.map +1 -1
- package/lib/feature-libraries/optional-field/optionalFieldCodecV2.js +55 -26
- package/lib/feature-libraries/optional-field/optionalFieldCodecV2.js.map +1 -1
- package/lib/feature-libraries/schema-index/schemaSummarizer.d.ts +27 -8
- package/lib/feature-libraries/schema-index/schemaSummarizer.d.ts.map +1 -1
- package/lib/feature-libraries/schema-index/schemaSummarizer.js +38 -12
- package/lib/feature-libraries/schema-index/schemaSummarizer.js.map +1 -1
- package/lib/feature-libraries/sequence-field/compose.d.ts +6 -7
- package/lib/feature-libraries/sequence-field/compose.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/compose.js +82 -258
- package/lib/feature-libraries/sequence-field/compose.js.map +1 -1
- package/lib/feature-libraries/sequence-field/helperTypes.d.ts +14 -10
- package/lib/feature-libraries/sequence-field/helperTypes.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/helperTypes.js.map +1 -1
- package/lib/feature-libraries/sequence-field/index.d.ts +2 -3
- package/lib/feature-libraries/sequence-field/index.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/index.js +0 -1
- package/lib/feature-libraries/sequence-field/index.js.map +1 -1
- package/lib/feature-libraries/sequence-field/invert.d.ts +3 -3
- package/lib/feature-libraries/sequence-field/invert.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/invert.js +67 -169
- package/lib/feature-libraries/sequence-field/invert.js.map +1 -1
- package/lib/feature-libraries/sequence-field/markQueue.d.ts +2 -2
- package/lib/feature-libraries/sequence-field/markQueue.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/markQueue.js.map +1 -1
- package/lib/feature-libraries/sequence-field/moveEffectTable.d.ts +4 -56
- package/lib/feature-libraries/sequence-field/moveEffectTable.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/moveEffectTable.js +6 -80
- 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 +108 -114
- package/lib/feature-libraries/sequence-field/rebase.js.map +1 -1
- package/lib/feature-libraries/sequence-field/replaceRevisions.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/replaceRevisions.js +16 -33
- package/lib/feature-libraries/sequence-field/replaceRevisions.js.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldChangeHandler.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldChangeHandler.js +0 -2
- package/lib/feature-libraries/sequence-field/sequenceFieldChangeHandler.js.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV2.d.ts +22 -4
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV2.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV2.js +350 -175
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV2.js.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV3.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV3.js +21 -61
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV3.js.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldEditor.d.ts +2 -2
- package/lib/feature-libraries/sequence-field/sequenceFieldEditor.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldEditor.js +10 -10
- package/lib/feature-libraries/sequence-field/sequenceFieldEditor.js.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts +3 -2
- package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.js +14 -109
- package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.js.map +1 -1
- package/lib/feature-libraries/sequence-field/types.d.ts +30 -59
- package/lib/feature-libraries/sequence-field/types.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/types.js.map +1 -1
- package/lib/feature-libraries/sequence-field/utils.d.ts +15 -24
- package/lib/feature-libraries/sequence-field/utils.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/utils.js +107 -292
- package/lib/feature-libraries/sequence-field/utils.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/shared-tree/independentView.d.ts +1 -1
- package/lib/shared-tree/independentView.d.ts.map +1 -1
- package/lib/shared-tree/independentView.js.map +1 -1
- package/lib/shared-tree/index.d.ts +1 -1
- package/lib/shared-tree/index.d.ts.map +1 -1
- package/lib/shared-tree/index.js.map +1 -1
- package/lib/shared-tree/schematizeTree.d.ts +4 -4
- package/lib/shared-tree/schematizeTree.d.ts.map +1 -1
- package/lib/shared-tree/schematizeTree.js +3 -2
- package/lib/shared-tree/schematizeTree.js.map +1 -1
- package/lib/shared-tree/schematizingTreeView.d.ts +1 -5
- package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/lib/shared-tree/schematizingTreeView.js +35 -36
- package/lib/shared-tree/schematizingTreeView.js.map +1 -1
- package/lib/shared-tree/sharedTree.d.ts +11 -5
- package/lib/shared-tree/sharedTree.d.ts.map +1 -1
- package/lib/shared-tree/sharedTree.js +14 -4
- package/lib/shared-tree/sharedTree.js.map +1 -1
- package/lib/shared-tree/sharedTreeChangeCodecs.d.ts +1 -1
- package/lib/shared-tree/sharedTreeChangeCodecs.d.ts.map +1 -1
- package/lib/shared-tree/sharedTreeChangeCodecs.js +1 -0
- package/lib/shared-tree/sharedTreeChangeCodecs.js.map +1 -1
- package/lib/shared-tree/sharedTreeChangeEnricher.d.ts +20 -8
- package/lib/shared-tree/sharedTreeChangeEnricher.d.ts.map +1 -1
- package/lib/shared-tree/sharedTreeChangeEnricher.js +25 -11
- package/lib/shared-tree/sharedTreeChangeEnricher.js.map +1 -1
- package/lib/shared-tree/sharedTreeChangeFamily.d.ts +4 -4
- package/lib/shared-tree/sharedTreeChangeFamily.d.ts.map +1 -1
- package/lib/shared-tree/sharedTreeChangeFamily.js +3 -3
- package/lib/shared-tree/sharedTreeChangeFamily.js.map +1 -1
- package/lib/shared-tree/sharedTreeEditBuilder.d.ts +16 -6
- package/lib/shared-tree/sharedTreeEditBuilder.d.ts.map +1 -1
- package/lib/shared-tree/sharedTreeEditBuilder.js +11 -5
- package/lib/shared-tree/sharedTreeEditBuilder.js.map +1 -1
- package/lib/shared-tree/treeAlpha.d.ts.map +1 -1
- package/lib/shared-tree/treeAlpha.js +2 -2
- package/lib/shared-tree/treeAlpha.js.map +1 -1
- package/lib/shared-tree/treeCheckout.d.ts +12 -10
- package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
- package/lib/shared-tree/treeCheckout.js +69 -20
- package/lib/shared-tree/treeCheckout.js.map +1 -1
- package/lib/shared-tree-core/branch.d.ts +3 -2
- package/lib/shared-tree-core/branch.d.ts.map +1 -1
- package/lib/shared-tree-core/branch.js +4 -3
- package/lib/shared-tree-core/branch.js.map +1 -1
- package/lib/shared-tree-core/editManager.d.ts +2 -2
- package/lib/shared-tree-core/editManager.d.ts.map +1 -1
- package/lib/shared-tree-core/editManager.js +9 -9
- package/lib/shared-tree-core/editManager.js.map +1 -1
- package/lib/shared-tree-core/editManagerCodecs.d.ts +4 -0
- package/lib/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerCodecs.js +14 -5
- package/lib/shared-tree-core/editManagerCodecs.js.map +1 -1
- package/{dist/shared-tree-core/editManagerCodecsV5.d.ts → lib/shared-tree-core/editManagerCodecsVSharedBranches.d.ts} +3 -3
- package/lib/shared-tree-core/editManagerCodecsVSharedBranches.d.ts.map +1 -0
- package/lib/shared-tree-core/{editManagerCodecsV5.js → editManagerCodecsVSharedBranches.js} +4 -4
- package/lib/shared-tree-core/editManagerCodecsVSharedBranches.js.map +1 -0
- package/lib/shared-tree-core/editManagerFormatCommons.d.ts +20 -6
- package/lib/shared-tree-core/editManagerFormatCommons.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerFormatCommons.js +22 -7
- package/lib/shared-tree-core/editManagerFormatCommons.js.map +1 -1
- package/lib/shared-tree-core/editManagerFormatV1toV4.d.ts +2 -2
- package/lib/shared-tree-core/editManagerFormatV1toV4.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerFormatV1toV4.js +1 -0
- package/lib/shared-tree-core/editManagerFormatV1toV4.js.map +1 -1
- package/lib/shared-tree-core/{editManagerFormatV5.d.ts → editManagerFormatVSharedBranches.d.ts} +3 -3
- package/lib/shared-tree-core/editManagerFormatVSharedBranches.d.ts.map +1 -0
- package/lib/shared-tree-core/{editManagerFormatV5.js → editManagerFormatVSharedBranches.js} +2 -2
- package/lib/shared-tree-core/editManagerFormatVSharedBranches.js.map +1 -0
- package/lib/shared-tree-core/editManagerSummarizer.d.ts +29 -9
- package/lib/shared-tree-core/editManagerSummarizer.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerSummarizer.js +39 -11
- package/lib/shared-tree-core/editManagerSummarizer.js.map +1 -1
- package/lib/shared-tree-core/index.d.ts +5 -3
- package/lib/shared-tree-core/index.d.ts.map +1 -1
- package/lib/shared-tree-core/index.js +4 -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/{dist/shared-tree-core/messageCodecV5.d.ts → lib/shared-tree-core/messageCodecVSharedBranches.d.ts} +2 -2
- package/lib/shared-tree-core/messageCodecVSharedBranches.d.ts.map +1 -0
- package/lib/shared-tree-core/{messageCodecV5.js → messageCodecVSharedBranches.js} +3 -3
- package/lib/shared-tree-core/messageCodecVSharedBranches.js.map +1 -0
- package/lib/shared-tree-core/messageCodecs.d.ts +4 -0
- package/lib/shared-tree-core/messageCodecs.d.ts.map +1 -1
- package/lib/shared-tree-core/messageCodecs.js +14 -5
- package/lib/shared-tree-core/messageCodecs.js.map +1 -1
- package/lib/shared-tree-core/messageFormat.d.ts +20 -6
- package/lib/shared-tree-core/messageFormat.d.ts.map +1 -1
- package/lib/shared-tree-core/messageFormat.js +22 -7
- package/lib/shared-tree-core/messageFormat.js.map +1 -1
- package/lib/shared-tree-core/messageFormatV1ToV4.d.ts +3 -2
- package/lib/shared-tree-core/messageFormatV1ToV4.d.ts.map +1 -1
- package/lib/shared-tree-core/messageFormatV1ToV4.js +8 -1
- package/lib/shared-tree-core/messageFormatV1ToV4.js.map +1 -1
- package/lib/shared-tree-core/{messageFormatV5.d.ts → messageFormatVSharedBranches.d.ts} +5 -7
- package/lib/shared-tree-core/messageFormatVSharedBranches.d.ts.map +1 -0
- package/lib/shared-tree-core/{messageFormatV5.js → messageFormatVSharedBranches.js} +3 -2
- package/lib/shared-tree-core/messageFormatVSharedBranches.js.map +1 -0
- package/lib/shared-tree-core/sharedTreeCore.d.ts +14 -47
- package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.js +28 -16
- package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/lib/shared-tree-core/summaryTypes.d.ts +94 -0
- package/lib/shared-tree-core/summaryTypes.d.ts.map +1 -0
- package/lib/shared-tree-core/summaryTypes.js +43 -0
- package/lib/shared-tree-core/summaryTypes.js.map +1 -0
- package/lib/shared-tree-core/versionedSummarizer.d.ts +67 -0
- package/lib/shared-tree-core/versionedSummarizer.d.ts.map +1 -0
- package/lib/shared-tree-core/versionedSummarizer.js +59 -0
- package/lib/shared-tree-core/versionedSummarizer.js.map +1 -0
- package/lib/simple-tree/api/configuration.d.ts +3 -26
- package/lib/simple-tree/api/configuration.d.ts.map +1 -1
- package/lib/simple-tree/api/configuration.js +14 -25
- package/lib/simple-tree/api/configuration.js.map +1 -1
- package/lib/simple-tree/api/dirtyIndex.d.ts +11 -0
- package/lib/simple-tree/api/dirtyIndex.d.ts.map +1 -1
- package/lib/simple-tree/api/dirtyIndex.js +7 -0
- package/lib/simple-tree/api/dirtyIndex.js.map +1 -1
- package/lib/simple-tree/api/discrepancies.d.ts +1 -1
- package/lib/simple-tree/api/discrepancies.d.ts.map +1 -1
- package/lib/simple-tree/api/discrepancies.js.map +1 -1
- package/lib/simple-tree/api/getSimpleSchema.d.ts +3 -3
- package/lib/simple-tree/api/getSimpleSchema.d.ts.map +1 -1
- package/lib/simple-tree/api/getSimpleSchema.js +9 -3
- package/lib/simple-tree/api/getSimpleSchema.js.map +1 -1
- package/lib/simple-tree/api/incrementalAllowedTypes.d.ts +1 -1
- package/lib/simple-tree/api/incrementalAllowedTypes.d.ts.map +1 -1
- package/lib/simple-tree/api/incrementalAllowedTypes.js +8 -1
- package/lib/simple-tree/api/incrementalAllowedTypes.js.map +1 -1
- package/lib/simple-tree/api/index.d.ts +3 -4
- package/lib/simple-tree/api/index.d.ts.map +1 -1
- package/lib/simple-tree/api/index.js +2 -3
- package/lib/simple-tree/api/index.js.map +1 -1
- package/lib/simple-tree/api/schemaCompatibilityTester.d.ts +1 -1
- package/lib/simple-tree/api/schemaCompatibilityTester.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaCompatibilityTester.js.map +1 -1
- package/lib/simple-tree/api/schemaFactoryAlpha.d.ts +5 -5
- package/lib/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaFactoryAlpha.js.map +1 -1
- package/lib/simple-tree/api/schemaFactoryRecursive.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaFactoryRecursive.js +0 -1
- package/lib/simple-tree/api/schemaFactoryRecursive.js.map +1 -1
- package/lib/simple-tree/api/schemaFromSimple.d.ts +6 -1
- package/lib/simple-tree/api/schemaFromSimple.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaFromSimple.js +5 -0
- package/lib/simple-tree/api/schemaFromSimple.js.map +1 -1
- package/lib/simple-tree/api/schemaStatics.d.ts +12 -12
- package/lib/simple-tree/api/simpleSchemaCodec.d.ts +15 -3
- package/lib/simple-tree/api/simpleSchemaCodec.d.ts.map +1 -1
- package/lib/simple-tree/api/simpleSchemaCodec.js +15 -3
- package/lib/simple-tree/api/simpleSchemaCodec.js.map +1 -1
- package/lib/simple-tree/api/simpleSchemaToJsonSchema.d.ts +1 -1
- package/lib/simple-tree/api/simpleSchemaToJsonSchema.d.ts.map +1 -1
- package/lib/simple-tree/api/simpleSchemaToJsonSchema.js.map +1 -1
- package/lib/simple-tree/api/snapshotCompatibilityChecker.d.ts +8 -1
- package/lib/simple-tree/api/snapshotCompatibilityChecker.d.ts.map +1 -1
- package/lib/simple-tree/api/snapshotCompatibilityChecker.js +15 -10
- package/lib/simple-tree/api/snapshotCompatibilityChecker.js.map +1 -1
- package/lib/simple-tree/api/typesUnsafe.d.ts +3 -3
- package/lib/simple-tree/api/typesUnsafe.d.ts.map +1 -1
- package/lib/simple-tree/api/typesUnsafe.js.map +1 -1
- package/lib/simple-tree/core/allowedTypes.d.ts +2 -2
- package/lib/simple-tree/core/allowedTypes.d.ts.map +1 -1
- package/lib/simple-tree/core/allowedTypes.js.map +1 -1
- package/lib/simple-tree/core/index.d.ts +1 -1
- package/lib/simple-tree/core/index.d.ts.map +1 -1
- package/lib/simple-tree/core/index.js +1 -1
- package/lib/simple-tree/core/index.js.map +1 -1
- package/lib/simple-tree/core/toStored.d.ts +17 -15
- package/lib/simple-tree/core/toStored.d.ts.map +1 -1
- package/lib/simple-tree/core/toStored.js +4 -37
- package/lib/simple-tree/core/toStored.js.map +1 -1
- package/lib/simple-tree/core/unhydratedFlexTree.d.ts +15 -15
- package/lib/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
- package/lib/simple-tree/core/unhydratedFlexTree.js +58 -8
- package/lib/simple-tree/core/unhydratedFlexTree.js.map +1 -1
- package/lib/simple-tree/core/walkSchema.d.ts.map +1 -1
- package/lib/simple-tree/core/walkSchema.js +5 -1
- package/lib/simple-tree/core/walkSchema.js.map +1 -1
- package/lib/simple-tree/createContext.d.ts.map +1 -1
- package/lib/simple-tree/createContext.js +20 -5
- package/lib/simple-tree/createContext.js.map +1 -1
- package/lib/simple-tree/fieldSchema.d.ts +7 -7
- 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 +8 -7
- package/lib/simple-tree/index.d.ts.map +1 -1
- package/lib/simple-tree/index.js +6 -5
- package/lib/simple-tree/index.js.map +1 -1
- package/lib/simple-tree/leafNodeSchema.d.ts +5 -5
- package/lib/simple-tree/leafNodeSchema.d.ts.map +1 -1
- package/lib/simple-tree/node-kinds/array/arrayNode.d.ts.map +1 -1
- package/lib/simple-tree/node-kinds/array/arrayNode.js +6 -4
- package/lib/simple-tree/node-kinds/array/arrayNode.js.map +1 -1
- package/lib/simple-tree/node-kinds/array/arrayNodeTypes.d.ts +3 -3
- package/lib/simple-tree/node-kinds/array/arrayNodeTypes.d.ts.map +1 -1
- package/lib/simple-tree/node-kinds/array/arrayNodeTypes.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.d.ts.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/map/mapNodeTypes.d.ts +3 -3
- package/lib/simple-tree/node-kinds/map/mapNodeTypes.d.ts.map +1 -1
- package/lib/simple-tree/node-kinds/map/mapNodeTypes.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 +19 -19
- package/lib/simple-tree/node-kinds/object/objectNode.js.map +1 -1
- package/lib/simple-tree/node-kinds/object/objectNodeTypes.d.ts +2 -2
- package/lib/simple-tree/node-kinds/object/objectNodeTypes.d.ts.map +1 -1
- package/lib/simple-tree/node-kinds/object/objectNodeTypes.js.map +1 -1
- package/lib/simple-tree/node-kinds/record/recordNode.d.ts.map +1 -1
- package/lib/simple-tree/node-kinds/record/recordNode.js +4 -2
- package/lib/simple-tree/node-kinds/record/recordNode.js.map +1 -1
- package/lib/simple-tree/node-kinds/record/recordNodeTypes.d.ts +3 -3
- package/lib/simple-tree/node-kinds/record/recordNodeTypes.d.ts.map +1 -1
- package/lib/simple-tree/node-kinds/record/recordNodeTypes.js.map +1 -1
- package/lib/simple-tree/prepareForInsertion.d.ts +54 -47
- package/lib/simple-tree/prepareForInsertion.d.ts.map +1 -1
- package/lib/simple-tree/prepareForInsertion.js +183 -124
- package/lib/simple-tree/prepareForInsertion.js.map +1 -1
- package/lib/simple-tree/simpleSchema.d.ts +55 -23
- package/lib/simple-tree/simpleSchema.d.ts.map +1 -1
- package/lib/simple-tree/simpleSchema.js +16 -1
- package/lib/simple-tree/simpleSchema.js.map +1 -1
- package/lib/simple-tree/simpleSchemaFormatV1.d.ts +1 -1
- package/lib/simple-tree/simpleSchemaFormatV1.d.ts.map +1 -1
- package/lib/simple-tree/simpleSchemaFormatV1.js +8 -1
- package/lib/simple-tree/simpleSchemaFormatV1.js.map +1 -1
- package/lib/simple-tree/toStoredSchema.d.ts +58 -11
- package/lib/simple-tree/toStoredSchema.d.ts.map +1 -1
- package/lib/simple-tree/toStoredSchema.js +204 -31
- package/lib/simple-tree/toStoredSchema.js.map +1 -1
- package/lib/simple-tree/treeSchema.d.ts +23 -0
- package/lib/simple-tree/treeSchema.d.ts.map +1 -0
- package/lib/simple-tree/treeSchema.js +21 -0
- package/lib/simple-tree/treeSchema.js.map +1 -0
- package/lib/simple-tree/unhydratedFlexTreeFromInsertable.d.ts +13 -4
- package/lib/simple-tree/unhydratedFlexTreeFromInsertable.d.ts.map +1 -1
- package/lib/simple-tree/unhydratedFlexTreeFromInsertable.js +26 -9
- package/lib/simple-tree/unhydratedFlexTreeFromInsertable.js.map +1 -1
- package/lib/tableSchema.d.ts +117 -63
- package/lib/tableSchema.d.ts.map +1 -1
- package/lib/tableSchema.js +160 -59
- package/lib/tableSchema.js.map +1 -1
- package/lib/treeFactory.d.ts.map +1 -1
- package/lib/treeFactory.js +18 -4
- package/lib/treeFactory.js.map +1 -1
- package/lib/util/index.d.ts +2 -1
- package/lib/util/index.d.ts.map +1 -1
- package/lib/util/index.js +2 -1
- package/lib/util/index.js.map +1 -1
- package/lib/util/rangeMap.d.ts +24 -12
- package/lib/util/rangeMap.d.ts.map +1 -1
- package/lib/util/rangeMap.js +44 -5
- package/lib/util/rangeMap.js.map +1 -1
- package/lib/util/readSnapshotBlob.d.ts +13 -0
- package/lib/util/readSnapshotBlob.d.ts.map +1 -0
- package/lib/util/readSnapshotBlob.js +14 -0
- package/lib/util/readSnapshotBlob.js.map +1 -0
- package/package.json +21 -21
- package/src/codec/codec.ts +15 -1
- package/src/codec/versioned/codec.ts +1 -1
- package/src/codec/versioned/format.ts +4 -1
- package/src/core/change-family/changeFamily.ts +5 -0
- package/src/core/change-family/index.ts +1 -0
- package/src/core/index.ts +7 -2
- package/src/core/rebase/changeRebaser.ts +6 -1
- package/src/core/rebase/index.ts +1 -0
- package/src/core/rebase/types.ts +8 -1
- package/src/core/rebase/utils.ts +31 -7
- package/src/core/tree/detachedFieldIndex.ts +71 -14
- package/src/core/tree/index.ts +9 -3
- package/src/core/tree/pathTree.ts +16 -4
- package/src/feature-libraries/chunked-forest/basicChunk.ts +7 -1
- package/src/feature-libraries/chunked-forest/chunkTree.ts +6 -1
- package/src/feature-libraries/chunked-forest/codec/incrementalEncodingPolicy.ts +15 -7
- package/src/feature-libraries/chunked-forest/codec/schemaBasedEncode.ts +9 -9
- package/src/feature-libraries/default-schema/defaultEditBuilder.ts +393 -127
- package/src/feature-libraries/default-schema/defaultFieldKinds.ts +35 -38
- package/src/feature-libraries/default-schema/index.ts +16 -5
- package/src/feature-libraries/default-schema/locationBasedEditBuilder.ts +180 -0
- package/src/feature-libraries/default-schema/mappedEditBuilder.ts +35 -9
- package/src/feature-libraries/deltaUtils.ts +6 -1
- package/src/feature-libraries/detachedFieldIndexSummarizer.ts +62 -15
- package/src/feature-libraries/flex-tree/context.ts +17 -0
- package/src/feature-libraries/flex-tree/flexTreeTypes.ts +7 -8
- package/src/feature-libraries/flex-tree/lazyField.ts +66 -24
- package/src/feature-libraries/forest-summary/codec.ts +8 -8
- package/src/feature-libraries/forest-summary/forestSummarizer.ts +45 -37
- package/src/feature-libraries/forest-summary/format.ts +4 -4
- package/src/feature-libraries/forest-summary/incrementalSummaryBuilder.ts +23 -39
- package/src/feature-libraries/forest-summary/index.ts +2 -1
- package/src/feature-libraries/forest-summary/summaryTypes.ts +61 -0
- package/src/feature-libraries/index.ts +22 -9
- package/src/feature-libraries/mapTreeCursor.ts +2 -1
- package/src/feature-libraries/mitigatedChangeFamily.ts +3 -1
- package/src/feature-libraries/modular-schema/comparison.ts +63 -5
- package/src/feature-libraries/modular-schema/crossFieldQueries.ts +142 -44
- package/src/feature-libraries/modular-schema/fieldChangeHandler.ts +36 -57
- package/src/feature-libraries/modular-schema/fieldKind.ts +24 -40
- package/src/feature-libraries/modular-schema/genericFieldKind.ts +10 -19
- package/src/feature-libraries/modular-schema/genericFieldKindCodecs.ts +1 -1
- package/src/feature-libraries/modular-schema/index.ts +21 -15
- package/src/feature-libraries/modular-schema/modularChangeCodecV1.ts +732 -0
- package/src/feature-libraries/modular-schema/modularChangeCodecV2.ts +790 -0
- package/src/feature-libraries/modular-schema/modularChangeCodecs.ts +29 -499
- package/src/feature-libraries/modular-schema/modularChangeFamily.ts +2542 -742
- package/src/feature-libraries/modular-schema/{modularChangeFormat.ts → modularChangeFormatV1.ts} +2 -1
- package/src/feature-libraries/modular-schema/modularChangeFormatV2.ts +62 -0
- package/src/feature-libraries/modular-schema/modularChangeTypes.ts +98 -10
- package/src/feature-libraries/optional-field/index.ts +1 -3
- package/src/feature-libraries/optional-field/optionalField.ts +317 -574
- package/src/feature-libraries/optional-field/optionalFieldChangeTypes.ts +24 -38
- package/src/feature-libraries/optional-field/optionalFieldCodecV2.ts +89 -35
- package/src/feature-libraries/schema-index/schemaSummarizer.ts +59 -18
- package/src/feature-libraries/sequence-field/compose.ts +134 -519
- package/src/feature-libraries/sequence-field/helperTypes.ts +34 -19
- package/src/feature-libraries/sequence-field/index.ts +0 -9
- package/src/feature-libraries/sequence-field/invert.ts +103 -228
- package/src/feature-libraries/sequence-field/markQueue.ts +2 -2
- package/src/feature-libraries/sequence-field/moveEffectTable.ts +8 -191
- package/src/feature-libraries/sequence-field/rebase.ts +168 -203
- package/src/feature-libraries/sequence-field/replaceRevisions.ts +31 -52
- package/src/feature-libraries/sequence-field/sequenceFieldChangeHandler.ts +0 -2
- package/src/feature-libraries/sequence-field/sequenceFieldCodecV2.ts +643 -220
- package/src/feature-libraries/sequence-field/sequenceFieldCodecV3.ts +56 -68
- package/src/feature-libraries/sequence-field/sequenceFieldEditor.ts +25 -27
- package/src/feature-libraries/sequence-field/sequenceFieldToDelta.ts +19 -129
- package/src/feature-libraries/sequence-field/types.ts +34 -64
- package/src/feature-libraries/sequence-field/utils.ts +133 -346
- package/src/index.ts +3 -2
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/independentView.ts +1 -1
- package/src/shared-tree/index.ts +3 -2
- package/src/shared-tree/schematizeTree.ts +21 -8
- package/src/shared-tree/schematizingTreeView.ts +50 -68
- package/src/shared-tree/sharedTree.ts +39 -12
- package/src/shared-tree/sharedTreeChangeCodecs.ts +5 -1
- package/src/shared-tree/sharedTreeChangeEnricher.ts +31 -11
- package/src/shared-tree/sharedTreeChangeFamily.ts +7 -4
- package/src/shared-tree/sharedTreeEditBuilder.ts +46 -12
- package/src/shared-tree/treeAlpha.ts +2 -3
- package/src/shared-tree/treeCheckout.ts +104 -31
- package/src/shared-tree-core/branch.ts +8 -2
- package/src/shared-tree-core/editManager.ts +16 -2
- package/src/shared-tree-core/editManagerCodecs.ts +17 -5
- package/src/shared-tree-core/{editManagerCodecsV5.ts → editManagerCodecsVSharedBranches.ts} +3 -3
- package/src/shared-tree-core/editManagerFormatCommons.ts +22 -7
- package/src/shared-tree-core/editManagerFormatV1toV4.ts +3 -1
- package/src/shared-tree-core/{editManagerFormatV5.ts → editManagerFormatVSharedBranches.ts} +2 -2
- package/src/shared-tree-core/editManagerSummarizer.ts +58 -16
- package/src/shared-tree-core/index.ts +11 -3
- package/src/shared-tree-core/messageCodecV1ToV4.ts +2 -1
- package/src/shared-tree-core/{messageCodecV5.ts → messageCodecVSharedBranches.ts} +3 -3
- package/src/shared-tree-core/messageCodecs.ts +17 -5
- package/src/shared-tree-core/messageFormat.ts +22 -7
- package/src/shared-tree-core/messageFormatV1ToV4.ts +16 -2
- package/src/shared-tree-core/{messageFormatV5.ts → messageFormatVSharedBranches.ts} +4 -6
- package/src/shared-tree-core/sharedTreeCore.ts +67 -76
- package/src/shared-tree-core/summaryTypes.ts +122 -0
- package/src/shared-tree-core/versionedSummarizer.ts +107 -0
- package/src/simple-tree/api/configuration.ts +21 -68
- package/src/simple-tree/api/dirtyIndex.ts +11 -0
- package/src/simple-tree/api/discrepancies.ts +1 -1
- package/src/simple-tree/api/getSimpleSchema.ts +13 -6
- package/src/simple-tree/api/incrementalAllowedTypes.ts +15 -3
- package/src/simple-tree/api/index.ts +3 -4
- package/src/simple-tree/api/schemaCompatibilityTester.ts +1 -1
- package/src/simple-tree/api/schemaFactoryAlpha.ts +2 -2
- package/src/simple-tree/api/schemaFactoryRecursive.ts +0 -2
- package/src/simple-tree/api/schemaFromSimple.ts +11 -5
- package/src/simple-tree/api/simpleSchemaCodec.ts +17 -3
- package/src/simple-tree/api/simpleSchemaToJsonSchema.ts +1 -1
- package/src/simple-tree/api/snapshotCompatibilityChecker.ts +18 -10
- package/src/simple-tree/api/typesUnsafe.ts +7 -3
- package/src/simple-tree/core/allowedTypes.ts +3 -3
- package/src/simple-tree/core/index.ts +2 -2
- package/src/simple-tree/core/toStored.ts +22 -55
- package/src/simple-tree/core/unhydratedFlexTree.ts +87 -36
- package/src/simple-tree/core/walkSchema.ts +6 -0
- package/src/simple-tree/createContext.ts +26 -11
- package/src/simple-tree/fieldSchema.ts +16 -7
- package/src/simple-tree/index.ts +12 -11
- package/src/simple-tree/node-kinds/array/arrayNode.ts +12 -7
- package/src/simple-tree/node-kinds/array/arrayNodeTypes.ts +3 -3
- package/src/simple-tree/node-kinds/common.ts +2 -5
- package/src/simple-tree/node-kinds/map/mapNode.ts +9 -6
- package/src/simple-tree/node-kinds/map/mapNodeTypes.ts +3 -3
- package/src/simple-tree/node-kinds/object/objectNode.ts +26 -26
- package/src/simple-tree/node-kinds/object/objectNodeTypes.ts +6 -2
- package/src/simple-tree/node-kinds/record/recordNode.ts +15 -11
- package/src/simple-tree/node-kinds/record/recordNodeTypes.ts +3 -3
- package/src/simple-tree/prepareForInsertion.ts +343 -200
- package/src/simple-tree/simpleSchema.ts +79 -32
- package/src/simple-tree/simpleSchemaFormatV1.ts +9 -1
- package/src/simple-tree/toStoredSchema.ts +319 -61
- package/src/simple-tree/treeSchema.ts +54 -0
- package/src/simple-tree/unhydratedFlexTreeFromInsertable.ts +42 -14
- package/src/tableSchema.ts +485 -166
- package/src/treeFactory.ts +19 -5
- package/src/util/index.ts +5 -0
- package/src/util/rangeMap.ts +72 -18
- package/src/util/readSnapshotBlob.ts +23 -0
- package/dist/feature-libraries/modular-schema/modularChangeFormat.d.ts.map +0 -1
- package/dist/feature-libraries/modular-schema/modularChangeFormat.js.map +0 -1
- package/dist/feature-libraries/sequence-field/relevantRemovedRoots.d.ts +0 -9
- package/dist/feature-libraries/sequence-field/relevantRemovedRoots.d.ts.map +0 -1
- package/dist/feature-libraries/sequence-field/relevantRemovedRoots.js +0 -50
- package/dist/feature-libraries/sequence-field/relevantRemovedRoots.js.map +0 -1
- package/dist/shared-tree-core/editManagerCodecsV5.d.ts.map +0 -1
- package/dist/shared-tree-core/editManagerCodecsV5.js.map +0 -1
- package/dist/shared-tree-core/editManagerFormatV5.d.ts.map +0 -1
- package/dist/shared-tree-core/editManagerFormatV5.js.map +0 -1
- package/dist/shared-tree-core/messageCodecV5.d.ts.map +0 -1
- package/dist/shared-tree-core/messageCodecV5.js.map +0 -1
- package/dist/shared-tree-core/messageFormatV5.d.ts.map +0 -1
- package/dist/shared-tree-core/messageFormatV5.js.map +0 -1
- package/dist/simple-tree/api/viewSchemaToSimpleSchema.d.ts +0 -40
- package/dist/simple-tree/api/viewSchemaToSimpleSchema.d.ts.map +0 -1
- package/dist/simple-tree/api/viewSchemaToSimpleSchema.js +0 -177
- package/dist/simple-tree/api/viewSchemaToSimpleSchema.js.map +0 -1
- package/docs/main/sequence-field/move-composition.md +0 -46
- package/lib/feature-libraries/modular-schema/modularChangeFormat.d.ts.map +0 -1
- package/lib/feature-libraries/modular-schema/modularChangeFormat.js.map +0 -1
- package/lib/feature-libraries/sequence-field/relevantRemovedRoots.d.ts +0 -9
- package/lib/feature-libraries/sequence-field/relevantRemovedRoots.d.ts.map +0 -1
- package/lib/feature-libraries/sequence-field/relevantRemovedRoots.js +0 -46
- package/lib/feature-libraries/sequence-field/relevantRemovedRoots.js.map +0 -1
- package/lib/shared-tree-core/editManagerCodecsV5.d.ts.map +0 -1
- package/lib/shared-tree-core/editManagerCodecsV5.js.map +0 -1
- package/lib/shared-tree-core/editManagerFormatV5.d.ts.map +0 -1
- package/lib/shared-tree-core/editManagerFormatV5.js.map +0 -1
- package/lib/shared-tree-core/messageCodecV5.d.ts.map +0 -1
- package/lib/shared-tree-core/messageCodecV5.js.map +0 -1
- package/lib/shared-tree-core/messageFormatV5.d.ts.map +0 -1
- package/lib/shared-tree-core/messageFormatV5.js.map +0 -1
- package/lib/simple-tree/api/viewSchemaToSimpleSchema.d.ts +0 -40
- package/lib/simple-tree/api/viewSchemaToSimpleSchema.d.ts.map +0 -1
- package/lib/simple-tree/api/viewSchemaToSimpleSchema.js +0 -171
- package/lib/simple-tree/api/viewSchemaToSimpleSchema.js.map +0 -1
- package/src/feature-libraries/sequence-field/relevantRemovedRoots.ts +0 -57
- package/src/simple-tree/api/viewSchemaToSimpleSchema.ts +0 -209
|
@@ -22,12 +22,10 @@ import {
|
|
|
22
22
|
EditBuilder,
|
|
23
23
|
type FieldKey,
|
|
24
24
|
type FieldKindIdentifier,
|
|
25
|
-
type FieldUpPath,
|
|
26
25
|
type RevisionInfo,
|
|
27
26
|
type RevisionMetadataSource,
|
|
28
27
|
type RevisionTag,
|
|
29
28
|
type TaggedChange,
|
|
30
|
-
type UpPath,
|
|
31
29
|
makeDetachedNodeId,
|
|
32
30
|
replaceAtomRevisions,
|
|
33
31
|
revisionMetadataSourceFromInfo,
|
|
@@ -36,10 +34,18 @@ import {
|
|
|
36
34
|
areEqualChangeAtomIdOpts,
|
|
37
35
|
tagChange,
|
|
38
36
|
makeAnonChange,
|
|
39
|
-
newChangeAtomIdRangeMap,
|
|
40
37
|
type DeltaDetachedNodeChanges,
|
|
41
38
|
type DeltaDetachedNodeRename,
|
|
42
39
|
mapTaggedChange,
|
|
40
|
+
newChangeAtomIdRangeMap,
|
|
41
|
+
newChangeAtomIdTransform,
|
|
42
|
+
type ChangeAtomIdRangeMap,
|
|
43
|
+
offsetChangeAtomId,
|
|
44
|
+
type NormalizedUpPath,
|
|
45
|
+
type NormalizedFieldUpPath,
|
|
46
|
+
isDetachedUpPathRoot,
|
|
47
|
+
subtractChangeAtomIds,
|
|
48
|
+
makeChangeAtomId,
|
|
43
49
|
} from "../../core/index.js";
|
|
44
50
|
import {
|
|
45
51
|
type IdAllocationState,
|
|
@@ -55,14 +61,19 @@ import {
|
|
|
55
61
|
type TupleBTree,
|
|
56
62
|
RangeMap,
|
|
57
63
|
balancedReduce,
|
|
64
|
+
type RangeQueryEntry,
|
|
65
|
+
type RangeQueryResultFragment,
|
|
58
66
|
} from "../../util/index.js";
|
|
59
67
|
import type { TreeChunk } from "../chunked-forest/index.js";
|
|
60
68
|
|
|
61
69
|
import {
|
|
62
|
-
type
|
|
70
|
+
type ComposeNodeManager,
|
|
63
71
|
type CrossFieldMap,
|
|
64
72
|
CrossFieldTarget,
|
|
65
|
-
|
|
73
|
+
type DetachedNodeEntry,
|
|
74
|
+
type InvertNodeManager,
|
|
75
|
+
type RebaseDetachedNodeEntry,
|
|
76
|
+
type RebaseNodeManager,
|
|
66
77
|
setInCrossFieldMap,
|
|
67
78
|
} from "./crossFieldQueries.js";
|
|
68
79
|
import {
|
|
@@ -74,17 +85,25 @@ import { convertGenericChange, genericFieldKind } from "./genericFieldKind.js";
|
|
|
74
85
|
import type { GenericChangeset } from "./genericFieldKindTypes.js";
|
|
75
86
|
import {
|
|
76
87
|
type ChangeAtomIdBTree,
|
|
88
|
+
type ChangeAtomIdKey,
|
|
77
89
|
type CrossFieldKey,
|
|
78
90
|
type CrossFieldKeyRange,
|
|
79
91
|
type CrossFieldKeyTable,
|
|
92
|
+
type CrossFieldRangeTable,
|
|
80
93
|
type FieldChange,
|
|
81
94
|
type FieldChangeMap,
|
|
82
95
|
type FieldChangeset,
|
|
83
96
|
type FieldId,
|
|
97
|
+
getFromChangeAtomIdMap,
|
|
84
98
|
type ModularChangeset,
|
|
85
|
-
|
|
99
|
+
newCrossFieldRangeTable,
|
|
86
100
|
type NodeChangeset,
|
|
87
101
|
type NodeId,
|
|
102
|
+
type NodeLocation,
|
|
103
|
+
rangeQueryChangeAtomIdMap,
|
|
104
|
+
type RebaseVersion,
|
|
105
|
+
type RootNodeTable,
|
|
106
|
+
setInChangeAtomIdMap,
|
|
88
107
|
} from "./modularChangeTypes.js";
|
|
89
108
|
import type { FlexFieldKind } from "./fieldKind.js";
|
|
90
109
|
|
|
@@ -171,14 +190,14 @@ export class ModularChangeFamily
|
|
|
171
190
|
}
|
|
172
191
|
|
|
173
192
|
public compose(changes: TaggedChange<ModularChangeset>[]): ModularChangeset {
|
|
174
|
-
const {
|
|
193
|
+
const { maxId } = getRevInfoFromTaggedChanges(changes);
|
|
175
194
|
const idState: IdAllocationState = { maxId };
|
|
176
195
|
|
|
177
196
|
const pairwiseDelegate = (
|
|
178
197
|
left: ModularChangeset,
|
|
179
198
|
right: ModularChangeset,
|
|
180
199
|
): ModularChangeset => {
|
|
181
|
-
return this.composePair(left, right,
|
|
200
|
+
return this.composePair(left, right, idState);
|
|
182
201
|
};
|
|
183
202
|
|
|
184
203
|
const innerChanges = changes.map((change) => change.change);
|
|
@@ -188,10 +207,11 @@ export class ModularChangeFamily
|
|
|
188
207
|
private composePair(
|
|
189
208
|
change1: ModularChangeset,
|
|
190
209
|
change2: ModularChangeset,
|
|
191
|
-
revInfos: RevisionInfo[],
|
|
192
210
|
idState: IdAllocationState,
|
|
193
211
|
): ModularChangeset {
|
|
194
|
-
const
|
|
212
|
+
const revInfos = composeRevInfos(change1.revisions, change2.revisions);
|
|
213
|
+
|
|
214
|
+
const { fieldChanges, nodeChanges, nodeToParent, nodeAliases, crossFieldKeys, rootNodes } =
|
|
195
215
|
this.composeAllFields(change1, change2, revInfos, idState);
|
|
196
216
|
|
|
197
217
|
const { allBuilds, allDestroys, allRefreshers } = composeBuildsDestroysAndRefreshers(
|
|
@@ -199,7 +219,7 @@ export class ModularChangeFamily
|
|
|
199
219
|
change2,
|
|
200
220
|
);
|
|
201
221
|
|
|
202
|
-
|
|
222
|
+
const composed = makeModularChangeset({
|
|
203
223
|
fieldChanges,
|
|
204
224
|
nodeChanges,
|
|
205
225
|
nodeToParent,
|
|
@@ -207,10 +227,15 @@ export class ModularChangeFamily
|
|
|
207
227
|
crossFieldKeys,
|
|
208
228
|
maxId: idState.maxId,
|
|
209
229
|
revisions: revInfos,
|
|
230
|
+
rootNodes,
|
|
210
231
|
builds: allBuilds,
|
|
211
232
|
destroys: allDestroys,
|
|
212
233
|
refreshers: allRefreshers,
|
|
213
234
|
});
|
|
235
|
+
|
|
236
|
+
// XXX: This is an expensive assert which should be disabled before merging.
|
|
237
|
+
this.validateChangeset(composed);
|
|
238
|
+
return composed;
|
|
214
239
|
}
|
|
215
240
|
|
|
216
241
|
private composeAllFields(
|
|
@@ -240,14 +265,38 @@ export class ModularChangeFamily
|
|
|
240
265
|
mergeTupleBTrees(change1.nodeChanges, change2.nodeChanges),
|
|
241
266
|
);
|
|
242
267
|
|
|
243
|
-
const composedNodeToParent: ChangeAtomIdBTree<
|
|
268
|
+
const composedNodeToParent: ChangeAtomIdBTree<NodeLocation> = brand(
|
|
244
269
|
mergeTupleBTrees(change1.nodeToParent, change2.nodeToParent),
|
|
245
270
|
);
|
|
246
271
|
const composedNodeAliases: ChangeAtomIdBTree<NodeId> = brand(
|
|
247
272
|
mergeTupleBTrees(change1.nodeAliases, change2.nodeAliases),
|
|
248
273
|
);
|
|
249
274
|
|
|
250
|
-
const
|
|
275
|
+
const pendingCompositions: PendingCompositions = {
|
|
276
|
+
nodeIdsToCompose: [],
|
|
277
|
+
affectedBaseFields: newTupleBTree(),
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
const movedCrossFieldKeys: CrossFieldKeyTable = newCrossFieldRangeTable();
|
|
281
|
+
const removedCrossFieldKeys: CrossFieldRangeTable<boolean> = newCrossFieldRangeTable();
|
|
282
|
+
|
|
283
|
+
const composedRoots = composeRootTables(
|
|
284
|
+
change1,
|
|
285
|
+
change2,
|
|
286
|
+
composedNodeToParent,
|
|
287
|
+
movedCrossFieldKeys,
|
|
288
|
+
removedCrossFieldKeys,
|
|
289
|
+
pendingCompositions,
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
const crossFieldTable = newComposeTable(
|
|
293
|
+
change1,
|
|
294
|
+
change2,
|
|
295
|
+
composedRoots,
|
|
296
|
+
movedCrossFieldKeys,
|
|
297
|
+
removedCrossFieldKeys,
|
|
298
|
+
pendingCompositions,
|
|
299
|
+
);
|
|
251
300
|
|
|
252
301
|
const composedFields = this.composeFieldMaps(
|
|
253
302
|
change1.fieldChanges,
|
|
@@ -268,17 +317,32 @@ export class ModularChangeFamily
|
|
|
268
317
|
revisionMetadata,
|
|
269
318
|
);
|
|
270
319
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
)
|
|
320
|
+
for (const entry of crossFieldTable.renamesToDelete.entries()) {
|
|
321
|
+
deleteNodeRenameFrom(crossFieldTable.composedRootNodes, entry.start, entry.length);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
for (const [nodeId, location] of crossFieldTable.movedNodeToParent.entries()) {
|
|
325
|
+
// Moved nodes are from change2.
|
|
326
|
+
// If there is a corresponding node in change1, then composedNodeToParent will already have the correct entry,
|
|
327
|
+
// because the location of the node is the same in change1 and the composed change
|
|
328
|
+
// (since they have the same input context).
|
|
329
|
+
if (crossFieldTable.newToBaseNodeId.get(nodeId) === undefined) {
|
|
330
|
+
composedNodeToParent.set(nodeId, location);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
276
334
|
return {
|
|
277
335
|
fieldChanges: composedFields,
|
|
278
336
|
nodeChanges: composedNodeChanges,
|
|
279
337
|
nodeToParent: composedNodeToParent,
|
|
280
338
|
nodeAliases: composedNodeAliases,
|
|
281
|
-
crossFieldKeys:
|
|
339
|
+
crossFieldKeys: composeCrossFieldKeyTables(
|
|
340
|
+
change1.crossFieldKeys,
|
|
341
|
+
change2.crossFieldKeys,
|
|
342
|
+
crossFieldTable.movedCrossFieldKeys,
|
|
343
|
+
crossFieldTable.removedCrossFieldKeys,
|
|
344
|
+
),
|
|
345
|
+
rootNodes: composedRoots,
|
|
282
346
|
};
|
|
283
347
|
}
|
|
284
348
|
|
|
@@ -290,17 +354,16 @@ export class ModularChangeFamily
|
|
|
290
354
|
): void {
|
|
291
355
|
const context = crossFieldTable.fieldToContext.get(fieldChange);
|
|
292
356
|
assert(context !== undefined, 0x8cc /* Should have context for every invalidated field */);
|
|
293
|
-
const {
|
|
357
|
+
const { change1: fieldChange1, change2: fieldChange2, composedChange } = context;
|
|
358
|
+
|
|
359
|
+
crossFieldTable.pendingCompositions.affectedBaseFields.delete(
|
|
360
|
+
fieldIdKeyFromFieldId(context.fieldId),
|
|
361
|
+
);
|
|
294
362
|
|
|
295
363
|
const rebaser = getChangeHandler(this.fieldKinds, composedChange.fieldKind).rebaser;
|
|
296
364
|
const composeNodes = (child1: NodeId | undefined, child2: NodeId | undefined): NodeId => {
|
|
297
|
-
if (
|
|
298
|
-
child1
|
|
299
|
-
child2 !== undefined &&
|
|
300
|
-
getFromChangeAtomIdMap(crossFieldTable.newToBaseNodeId, child2) === undefined
|
|
301
|
-
) {
|
|
302
|
-
setInChangeAtomIdMap(crossFieldTable.newToBaseNodeId, child2, child1);
|
|
303
|
-
crossFieldTable.pendingCompositions.nodeIdsToCompose.push([child1, child2]);
|
|
365
|
+
if (child1 !== undefined && child2 !== undefined) {
|
|
366
|
+
addNodesToCompose(crossFieldTable, child1, child2);
|
|
304
367
|
}
|
|
305
368
|
|
|
306
369
|
return child1 ?? child2 ?? fail(0xb22 /* Should not compose two undefined nodes */);
|
|
@@ -311,7 +374,7 @@ export class ModularChangeFamily
|
|
|
311
374
|
fieldChange2,
|
|
312
375
|
composeNodes,
|
|
313
376
|
genId,
|
|
314
|
-
new
|
|
377
|
+
new ComposeNodeManagerI(crossFieldTable, context.fieldId, false),
|
|
315
378
|
revisionMetadata,
|
|
316
379
|
);
|
|
317
380
|
composedChange.change = brand(amendedChange);
|
|
@@ -323,7 +386,7 @@ export class ModularChangeFamily
|
|
|
323
386
|
* - discovering that two node changesets refer to the same node (`nodeIdsToCompose`)
|
|
324
387
|
* - a previously composed field being invalidated by a cross field effect (`invalidatedFields`)
|
|
325
388
|
* - a field which was copied directly from an input changeset being invalidated by a cross field effect
|
|
326
|
-
* (`affectedBaseFields`
|
|
389
|
+
* (`affectedBaseFields`)
|
|
327
390
|
*
|
|
328
391
|
* Updating an element may invalidate further elements. This function runs until there is no more invalidation.
|
|
329
392
|
*/
|
|
@@ -331,72 +394,59 @@ export class ModularChangeFamily
|
|
|
331
394
|
table: ComposeTable,
|
|
332
395
|
composedFields: FieldChangeMap,
|
|
333
396
|
composedNodes: ChangeAtomIdBTree<NodeChangeset>,
|
|
334
|
-
composedNodeToParent: ChangeAtomIdBTree<
|
|
397
|
+
composedNodeToParent: ChangeAtomIdBTree<NodeLocation>,
|
|
335
398
|
nodeAliases: ChangeAtomIdBTree<NodeId>,
|
|
336
399
|
genId: IdAllocator,
|
|
337
400
|
metadata: RevisionMetadataSource,
|
|
338
401
|
): void {
|
|
339
402
|
const pending = table.pendingCompositions;
|
|
340
|
-
while (
|
|
341
|
-
|
|
342
|
-
pending.nodeIdsToCompose.length > 0 ||
|
|
343
|
-
pending.affectedBaseFields.length > 0 ||
|
|
344
|
-
pending.affectedNewFields.length > 0
|
|
345
|
-
) {
|
|
346
|
-
// Note that the call to `composeNodesById` can add entries to `crossFieldTable.nodeIdPairs`.
|
|
347
|
-
for (const [id1, id2] of pending.nodeIdsToCompose) {
|
|
348
|
-
this.composeNodesById(
|
|
349
|
-
table.baseChange.nodeChanges,
|
|
350
|
-
table.newChange.nodeChanges,
|
|
351
|
-
composedNodes,
|
|
352
|
-
composedNodeToParent,
|
|
353
|
-
nodeAliases,
|
|
354
|
-
id1,
|
|
355
|
-
id2,
|
|
356
|
-
genId,
|
|
357
|
-
table,
|
|
358
|
-
metadata,
|
|
359
|
-
);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
pending.nodeIdsToCompose.length = 0;
|
|
363
|
-
|
|
364
|
-
this.composeAffectedFields(
|
|
403
|
+
while (pending.nodeIdsToCompose.length > 0 || pending.affectedBaseFields.length > 0) {
|
|
404
|
+
this.processPendingNodeCompositions(
|
|
365
405
|
table,
|
|
366
|
-
table.baseChange,
|
|
367
|
-
true,
|
|
368
|
-
pending.affectedBaseFields,
|
|
369
|
-
composedFields,
|
|
370
406
|
composedNodes,
|
|
407
|
+
composedNodeToParent,
|
|
408
|
+
nodeAliases,
|
|
371
409
|
genId,
|
|
372
410
|
metadata,
|
|
373
411
|
);
|
|
374
412
|
|
|
375
413
|
this.composeAffectedFields(
|
|
376
414
|
table,
|
|
377
|
-
table.
|
|
378
|
-
|
|
379
|
-
pending.affectedNewFields,
|
|
415
|
+
table.baseChange,
|
|
416
|
+
pending.affectedBaseFields,
|
|
380
417
|
composedFields,
|
|
381
418
|
composedNodes,
|
|
382
419
|
genId,
|
|
383
420
|
metadata,
|
|
384
421
|
);
|
|
385
|
-
|
|
386
|
-
this.processInvalidatedCompositions(table, genId, metadata);
|
|
387
422
|
}
|
|
388
423
|
}
|
|
389
424
|
|
|
390
|
-
private
|
|
425
|
+
private processPendingNodeCompositions(
|
|
391
426
|
table: ComposeTable,
|
|
427
|
+
composedNodes: ChangeAtomIdBTree<NodeChangeset>,
|
|
428
|
+
composedNodeToParent: ChangeAtomIdBTree<NodeLocation>,
|
|
429
|
+
nodeAliases: ChangeAtomIdBTree<NodeId>,
|
|
392
430
|
genId: IdAllocator,
|
|
393
431
|
metadata: RevisionMetadataSource,
|
|
394
432
|
): void {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
433
|
+
// Note that the call to `composeNodesById` can add entries to `crossFieldTable.nodeIdPairs`.
|
|
434
|
+
for (const [id1, id2] of table.pendingCompositions.nodeIdsToCompose) {
|
|
435
|
+
this.composeNodesById(
|
|
436
|
+
table.baseChange,
|
|
437
|
+
table.newChange,
|
|
438
|
+
composedNodes,
|
|
439
|
+
composedNodeToParent,
|
|
440
|
+
nodeAliases,
|
|
441
|
+
id1,
|
|
442
|
+
id2,
|
|
443
|
+
genId,
|
|
444
|
+
table,
|
|
445
|
+
metadata,
|
|
446
|
+
);
|
|
399
447
|
}
|
|
448
|
+
|
|
449
|
+
table.pendingCompositions.nodeIdsToCompose.length = 0;
|
|
400
450
|
}
|
|
401
451
|
|
|
402
452
|
/**
|
|
@@ -413,63 +463,79 @@ export class ModularChangeFamily
|
|
|
413
463
|
private composeAffectedFields(
|
|
414
464
|
table: ComposeTable,
|
|
415
465
|
change: ModularChangeset,
|
|
416
|
-
areBaseFields: boolean,
|
|
417
466
|
affectedFields: BTree<FieldIdKey, true>,
|
|
418
467
|
composedFields: FieldChangeMap,
|
|
419
468
|
composedNodes: ChangeAtomIdBTree<NodeChangeset>,
|
|
420
469
|
genId: IdAllocator,
|
|
421
470
|
metadata: RevisionMetadataSource,
|
|
422
471
|
): void {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
472
|
+
const fieldsToProcess = affectedFields.clone();
|
|
473
|
+
affectedFields.clear();
|
|
474
|
+
|
|
475
|
+
for (const fieldIdKey of fieldsToProcess.keys()) {
|
|
476
|
+
const fieldId = fieldIdFromFieldIdKey(fieldIdKey);
|
|
477
|
+
const fieldChange = fieldChangeFromId(change, fieldId);
|
|
426
478
|
|
|
427
479
|
if (
|
|
428
480
|
table.fieldToContext.has(fieldChange) ||
|
|
429
481
|
table.newFieldToBaseField.has(fieldChange)
|
|
430
482
|
) {
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
483
|
+
this.composeInvalidatedField(fieldChange, table, genId, metadata);
|
|
484
|
+
} else {
|
|
485
|
+
this.composeFieldWithNoNewChange(
|
|
486
|
+
table,
|
|
487
|
+
fieldChange,
|
|
488
|
+
fieldId,
|
|
489
|
+
composedFields,
|
|
490
|
+
composedNodes,
|
|
491
|
+
genId,
|
|
492
|
+
metadata,
|
|
493
|
+
);
|
|
435
494
|
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
436
497
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
table,
|
|
448
|
-
metadata,
|
|
449
|
-
);
|
|
498
|
+
private composeFieldWithNoNewChange(
|
|
499
|
+
table: ComposeTable,
|
|
500
|
+
baseFieldChange: FieldChange,
|
|
501
|
+
fieldId: FieldId,
|
|
502
|
+
composedFields: FieldChangeMap,
|
|
503
|
+
composedNodes: ChangeAtomIdBTree<NodeChangeset>,
|
|
504
|
+
genId: IdAllocator,
|
|
505
|
+
metadata: RevisionMetadataSource,
|
|
506
|
+
): void {
|
|
507
|
+
const emptyChange = this.createEmptyFieldChange(baseFieldChange.fieldKind);
|
|
450
508
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
509
|
+
const composedField = this.composeFieldChanges(
|
|
510
|
+
fieldId,
|
|
511
|
+
baseFieldChange,
|
|
512
|
+
emptyChange,
|
|
513
|
+
genId,
|
|
514
|
+
table,
|
|
515
|
+
metadata,
|
|
516
|
+
);
|
|
455
517
|
|
|
456
|
-
|
|
457
|
-
|
|
518
|
+
if (fieldId.nodeId === undefined) {
|
|
519
|
+
composedFields.set(fieldId.field, composedField);
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
458
522
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
}
|
|
523
|
+
const nodeId = normalizeNodeId(
|
|
524
|
+
getFromChangeAtomIdMap(table.newToBaseNodeId, fieldId.nodeId) ?? fieldId.nodeId,
|
|
525
|
+
table.baseChange.nodeAliases,
|
|
526
|
+
);
|
|
464
527
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
528
|
+
// We clone the node changeset before mutating it, as it may be from one of the input changesets.
|
|
529
|
+
const nodeChangeset: Mutable<NodeChangeset> = cloneNodeChangeset(
|
|
530
|
+
nodeChangeFromId(composedNodes, table.baseChange.nodeAliases, nodeId),
|
|
531
|
+
);
|
|
532
|
+
setInChangeAtomIdMap(composedNodes, nodeId, nodeChangeset);
|
|
468
533
|
|
|
469
|
-
|
|
534
|
+
if (nodeChangeset.fieldChanges === undefined) {
|
|
535
|
+
nodeChangeset.fieldChanges = new Map();
|
|
470
536
|
}
|
|
471
537
|
|
|
472
|
-
|
|
538
|
+
nodeChangeset.fieldChanges.set(fieldId.field, composedField);
|
|
473
539
|
}
|
|
474
540
|
|
|
475
541
|
private composeFieldMaps(
|
|
@@ -488,6 +554,18 @@ export class ModularChangeFamily
|
|
|
488
554
|
for (const [field, fieldChange1] of change1) {
|
|
489
555
|
const fieldId: FieldId = { nodeId: parentId, field };
|
|
490
556
|
const fieldChange2 = change2.get(field);
|
|
557
|
+
|
|
558
|
+
const cachedComposedFieldChange =
|
|
559
|
+
crossFieldTable.fieldToContext.get(fieldChange1)?.composedChange;
|
|
560
|
+
|
|
561
|
+
if (fieldChange2 === undefined && cachedComposedFieldChange !== undefined) {
|
|
562
|
+
// This can happen if the field was previous processed in `composeFieldWithNoNewChange`.
|
|
563
|
+
// If `change2` does not have a change for this field, then without this check we would
|
|
564
|
+
// lose the composed field change and instead simply have `change1`'s change.
|
|
565
|
+
composedFields.set(field, cachedComposedFieldChange);
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
|
|
491
569
|
const composedField =
|
|
492
570
|
fieldChange2 !== undefined
|
|
493
571
|
? this.composeFieldChanges(
|
|
@@ -519,7 +597,7 @@ export class ModularChangeFamily
|
|
|
519
597
|
* will be added to `crossFieldTable.pendingCompositions.nodeIdsToCompose`.
|
|
520
598
|
*
|
|
521
599
|
* Any fields which had cross-field information sent to them as part of this field composition
|
|
522
|
-
* will be added to
|
|
600
|
+
* will be added to `affectedBaseFields` in `crossFieldTable.pendingCompositions`.
|
|
523
601
|
*
|
|
524
602
|
* Any composed `FieldChange` which is invalidated by new cross-field information will be added to `crossFieldTable.invalidatedFields`.
|
|
525
603
|
*/
|
|
@@ -538,15 +616,14 @@ export class ModularChangeFamily
|
|
|
538
616
|
change2: change2Normalized,
|
|
539
617
|
} = this.normalizeFieldChanges(change1, change2);
|
|
540
618
|
|
|
541
|
-
const manager = new
|
|
619
|
+
const manager = new ComposeNodeManagerI(crossFieldTable, fieldId);
|
|
542
620
|
|
|
543
621
|
const composedChange = changeHandler.rebaser.compose(
|
|
544
622
|
change1Normalized,
|
|
545
623
|
change2Normalized,
|
|
546
624
|
(child1, child2) => {
|
|
547
625
|
if (child1 !== undefined && child2 !== undefined) {
|
|
548
|
-
|
|
549
|
-
crossFieldTable.pendingCompositions.nodeIdsToCompose.push([child1, child2]);
|
|
626
|
+
addNodesToCompose(crossFieldTable, child1, child2);
|
|
550
627
|
}
|
|
551
628
|
return child1 ?? child2 ?? fail(0xb23 /* Should not compose two undefined nodes */);
|
|
552
629
|
},
|
|
@@ -572,19 +649,19 @@ export class ModularChangeFamily
|
|
|
572
649
|
}
|
|
573
650
|
|
|
574
651
|
private composeNodesById(
|
|
575
|
-
|
|
576
|
-
|
|
652
|
+
change1: ModularChangeset,
|
|
653
|
+
change2: ModularChangeset,
|
|
577
654
|
composedNodes: ChangeAtomIdBTree<NodeChangeset>,
|
|
578
|
-
composedNodeToParent: ChangeAtomIdBTree<
|
|
579
|
-
|
|
655
|
+
composedNodeToParent: ChangeAtomIdBTree<NodeLocation>,
|
|
656
|
+
composedAliases: ChangeAtomIdBTree<NodeId>,
|
|
580
657
|
id1: NodeId,
|
|
581
658
|
id2: NodeId,
|
|
582
659
|
idAllocator: IdAllocator,
|
|
583
660
|
crossFieldTable: ComposeTable,
|
|
584
661
|
revisionMetadata: RevisionMetadataSource,
|
|
585
662
|
): void {
|
|
586
|
-
const nodeChangeset1 = nodeChangeFromId(
|
|
587
|
-
const nodeChangeset2 = nodeChangeFromId(
|
|
663
|
+
const nodeChangeset1 = nodeChangeFromId(change1.nodeChanges, change1.nodeAliases, id1);
|
|
664
|
+
const nodeChangeset2 = nodeChangeFromId(change2.nodeChanges, change2.nodeAliases, id2);
|
|
588
665
|
const composedNodeChangeset = this.composeNodeChanges(
|
|
589
666
|
id1,
|
|
590
667
|
nodeChangeset1,
|
|
@@ -599,13 +676,11 @@ export class ModularChangeFamily
|
|
|
599
676
|
if (!areEqualChangeAtomIds(id1, id2)) {
|
|
600
677
|
composedNodes.delete([id2.revision, id2.localId]);
|
|
601
678
|
composedNodeToParent.delete([id2.revision, id2.localId]);
|
|
602
|
-
setInChangeAtomIdMap(
|
|
679
|
+
setInChangeAtomIdMap(composedAliases, id2, id1);
|
|
603
680
|
|
|
604
681
|
// We need to delete id1 to avoid forming a cycle in case id1 already had an alias.
|
|
605
|
-
|
|
682
|
+
composedAliases.delete([id1.revision, id1.localId]);
|
|
606
683
|
}
|
|
607
|
-
|
|
608
|
-
crossFieldTable.composedNodes.add(composedNodeChangeset);
|
|
609
684
|
}
|
|
610
685
|
|
|
611
686
|
private composeNodeChanges(
|
|
@@ -640,7 +715,7 @@ export class ModularChangeFamily
|
|
|
640
715
|
revisionMetadata,
|
|
641
716
|
);
|
|
642
717
|
|
|
643
|
-
const composedNodeChange: NodeChangeset = {};
|
|
718
|
+
const composedNodeChange: Mutable<NodeChangeset> = {};
|
|
644
719
|
|
|
645
720
|
if (composedFieldChanges.size > 0) {
|
|
646
721
|
composedNodeChange.fieldChanges = composedFieldChanges;
|
|
@@ -692,9 +767,14 @@ export class ModularChangeFamily
|
|
|
692
767
|
const genId: IdAllocator = idAllocatorFromMaxId(change.change.maxId ?? -1);
|
|
693
768
|
|
|
694
769
|
const crossFieldTable: InvertTable = {
|
|
695
|
-
|
|
770
|
+
change: change.change,
|
|
771
|
+
entries: newChangeAtomIdRangeMap(),
|
|
696
772
|
originalFieldToContext: new Map(),
|
|
773
|
+
invertRevision: revisionForInvert,
|
|
697
774
|
invertedNodeToParent: brand(change.change.nodeToParent.clone()),
|
|
775
|
+
invalidatedFields: new Set(),
|
|
776
|
+
invertedRoots: invertRootTable(change.change, isRollback),
|
|
777
|
+
attachToDetachId: newChangeAtomIdTransform(),
|
|
698
778
|
};
|
|
699
779
|
const { revInfos: oldRevInfos } = getRevInfoFromTaggedChanges([change]);
|
|
700
780
|
const revisionMetadata = revisionMetadataSourceFromInfo(oldRevInfos);
|
|
@@ -735,7 +815,7 @@ export class ModularChangeFamily
|
|
|
735
815
|
context !== undefined,
|
|
736
816
|
0x851 /* Should have context for every invalidated field */,
|
|
737
817
|
);
|
|
738
|
-
const { invertedField
|
|
818
|
+
const { invertedField } = context;
|
|
739
819
|
|
|
740
820
|
const amendedChange = getChangeHandler(
|
|
741
821
|
this.fieldKinds,
|
|
@@ -745,7 +825,7 @@ export class ModularChangeFamily
|
|
|
745
825
|
isRollback,
|
|
746
826
|
genId,
|
|
747
827
|
revisionForInvert,
|
|
748
|
-
new
|
|
828
|
+
new InvertNodeManagerI(crossFieldTable, context.fieldId),
|
|
749
829
|
revisionMetadata,
|
|
750
830
|
);
|
|
751
831
|
invertedField.change = brand(amendedChange);
|
|
@@ -754,10 +834,13 @@ export class ModularChangeFamily
|
|
|
754
834
|
|
|
755
835
|
const crossFieldKeys = this.makeCrossFieldKeyTable(invertedFields, invertedNodes);
|
|
756
836
|
|
|
837
|
+
this.processInvertRenames(crossFieldTable);
|
|
838
|
+
|
|
757
839
|
return makeModularChangeset({
|
|
758
840
|
fieldChanges: invertedFields,
|
|
759
841
|
nodeChanges: invertedNodes,
|
|
760
842
|
nodeToParent: crossFieldTable.invertedNodeToParent,
|
|
843
|
+
rootNodes: crossFieldTable.invertedRoots,
|
|
761
844
|
nodeAliases: change.change.nodeAliases,
|
|
762
845
|
crossFieldKeys,
|
|
763
846
|
maxId: genId.getMaxId(),
|
|
@@ -781,7 +864,7 @@ export class ModularChangeFamily
|
|
|
781
864
|
|
|
782
865
|
for (const [field, fieldChange] of changes) {
|
|
783
866
|
const fieldId = { nodeId: parentId, field };
|
|
784
|
-
const manager = new
|
|
867
|
+
const manager = new InvertNodeManagerI(crossFieldTable, fieldId);
|
|
785
868
|
const invertedChange = getChangeHandler(
|
|
786
869
|
this.fieldKinds,
|
|
787
870
|
fieldChange.fieldKind,
|
|
@@ -818,7 +901,7 @@ export class ModularChangeFamily
|
|
|
818
901
|
revisionMetadata: RevisionMetadataSource,
|
|
819
902
|
revisionForInvert: RevisionTag,
|
|
820
903
|
): NodeChangeset {
|
|
821
|
-
const inverse: NodeChangeset = {};
|
|
904
|
+
const inverse: Mutable<NodeChangeset> = {};
|
|
822
905
|
|
|
823
906
|
// If the node has a constraint, it should be inverted to a node-exist-on-revert constraint. This ensure that if
|
|
824
907
|
// the inverse is inverted again, the original input constraint will be restored.
|
|
@@ -848,6 +931,17 @@ export class ModularChangeFamily
|
|
|
848
931
|
return inverse;
|
|
849
932
|
}
|
|
850
933
|
|
|
934
|
+
private processInvertRenames(table: InvertTable): void {
|
|
935
|
+
for (const {
|
|
936
|
+
start: newAttachId,
|
|
937
|
+
value: originalDetachId,
|
|
938
|
+
length,
|
|
939
|
+
} of table.attachToDetachId.entries()) {
|
|
940
|
+
// Note that the detach location is already set in `invertDetach`.
|
|
941
|
+
addNodeRename(table.invertedRoots, originalDetachId, newAttachId, length, undefined);
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
|
|
851
945
|
public rebase(
|
|
852
946
|
taggedChange: TaggedChange<ModularChangeset>,
|
|
853
947
|
potentiallyConflictedOver: TaggedChange<ModularChangeset>,
|
|
@@ -867,17 +961,41 @@ export class ModularChangeFamily
|
|
|
867
961
|
const idState: IdAllocationState = { maxId };
|
|
868
962
|
const genId: IdAllocator = idAllocatorFromState(idState);
|
|
869
963
|
|
|
964
|
+
const affectedBaseFields: TupleBTree<FieldIdKey, boolean> = newTupleBTree();
|
|
965
|
+
const nodesToRebase: [newChangeset: NodeId, baseChangeset: NodeId][] = [];
|
|
966
|
+
|
|
967
|
+
const rebasedNodeToParent: ChangeAtomIdBTree<NodeLocation> = brand(
|
|
968
|
+
change.nodeToParent.clone(),
|
|
969
|
+
);
|
|
970
|
+
|
|
971
|
+
const rebaseVersion = Math.max(
|
|
972
|
+
change.rebaseVersion,
|
|
973
|
+
over.change.rebaseVersion,
|
|
974
|
+
) as RebaseVersion;
|
|
975
|
+
|
|
976
|
+
const rebasedRootNodes = rebaseRoots(
|
|
977
|
+
change,
|
|
978
|
+
over.change,
|
|
979
|
+
affectedBaseFields,
|
|
980
|
+
nodesToRebase,
|
|
981
|
+
rebasedNodeToParent,
|
|
982
|
+
rebaseVersion,
|
|
983
|
+
);
|
|
870
984
|
const crossFieldTable: RebaseTable = {
|
|
871
|
-
|
|
985
|
+
rebaseVersion,
|
|
986
|
+
entries: newDetachedEntryMap(),
|
|
872
987
|
newChange: change,
|
|
873
988
|
baseChange: over.change,
|
|
874
989
|
baseFieldToContext: new Map(),
|
|
990
|
+
baseRoots: over.change.rootNodes,
|
|
991
|
+
rebasedRootNodes,
|
|
875
992
|
baseToRebasedNodeId: newTupleBTree(),
|
|
876
993
|
rebasedFields: new Set(),
|
|
877
|
-
rebasedNodeToParent
|
|
878
|
-
|
|
994
|
+
rebasedNodeToParent,
|
|
995
|
+
rebasedDetachLocations: newChangeAtomIdRangeMap(),
|
|
996
|
+
movedDetaches: newChangeAtomIdRangeMap(),
|
|
879
997
|
nodeIdPairs: [],
|
|
880
|
-
affectedBaseFields
|
|
998
|
+
affectedBaseFields,
|
|
881
999
|
fieldsWithUnattachedChild: new Set(),
|
|
882
1000
|
};
|
|
883
1001
|
|
|
@@ -893,13 +1011,14 @@ export class ModularChangeFamily
|
|
|
893
1011
|
const rebasedNodes: ChangeAtomIdBTree<NodeChangeset> = brand(change.nodeChanges.clone());
|
|
894
1012
|
|
|
895
1013
|
const rebasedFields = this.rebaseIntersectingFields(
|
|
1014
|
+
nodesToRebase,
|
|
896
1015
|
crossFieldTable,
|
|
897
1016
|
rebasedNodes,
|
|
898
1017
|
genId,
|
|
899
1018
|
rebaseMetadata,
|
|
900
1019
|
);
|
|
901
1020
|
|
|
902
|
-
this.
|
|
1021
|
+
this.rebaseInvalidatedFields(
|
|
903
1022
|
rebasedFields,
|
|
904
1023
|
rebasedNodes,
|
|
905
1024
|
crossFieldTable,
|
|
@@ -907,25 +1026,59 @@ export class ModularChangeFamily
|
|
|
907
1026
|
genId,
|
|
908
1027
|
);
|
|
909
1028
|
|
|
1029
|
+
fixupRebasedDetachLocations(crossFieldTable);
|
|
1030
|
+
|
|
910
1031
|
const constraintState = newConstraintState(change.constraintViolationCount ?? 0);
|
|
911
1032
|
const revertConstraintState = newConstraintState(
|
|
912
1033
|
change.constraintViolationCountOnRevert ?? 0,
|
|
913
1034
|
);
|
|
914
|
-
|
|
1035
|
+
|
|
1036
|
+
this.updateConstraints(
|
|
915
1037
|
rebasedFields,
|
|
916
|
-
|
|
917
|
-
|
|
1038
|
+
rebasedNodes,
|
|
1039
|
+
rebasedRootNodes,
|
|
918
1040
|
constraintState,
|
|
919
1041
|
revertConstraintState,
|
|
920
|
-
|
|
1042
|
+
);
|
|
1043
|
+
|
|
1044
|
+
const fieldsWithRootMoves = getFieldsWithRootMoves(
|
|
1045
|
+
crossFieldTable.rebasedRootNodes,
|
|
1046
|
+
change.nodeAliases,
|
|
1047
|
+
);
|
|
1048
|
+
|
|
1049
|
+
const fieldToRootChanges = getFieldToRootChanges(
|
|
1050
|
+
crossFieldTable.rebasedRootNodes,
|
|
1051
|
+
change.nodeAliases,
|
|
921
1052
|
);
|
|
922
1053
|
|
|
923
1054
|
const rebased = makeModularChangeset({
|
|
924
|
-
fieldChanges: this.pruneFieldMap(
|
|
1055
|
+
fieldChanges: this.pruneFieldMap(
|
|
1056
|
+
rebasedFields,
|
|
1057
|
+
undefined,
|
|
1058
|
+
rebasedNodes,
|
|
1059
|
+
crossFieldTable.rebasedNodeToParent,
|
|
1060
|
+
change.nodeAliases,
|
|
1061
|
+
crossFieldTable.rebasedRootNodes,
|
|
1062
|
+
fieldsWithRootMoves,
|
|
1063
|
+
fieldToRootChanges,
|
|
1064
|
+
),
|
|
925
1065
|
nodeChanges: rebasedNodes,
|
|
926
1066
|
nodeToParent: crossFieldTable.rebasedNodeToParent,
|
|
1067
|
+
rootNodes: this.pruneRoots(
|
|
1068
|
+
crossFieldTable.rebasedRootNodes,
|
|
1069
|
+
rebasedNodes,
|
|
1070
|
+
crossFieldTable.rebasedNodeToParent,
|
|
1071
|
+
change.nodeAliases,
|
|
1072
|
+
fieldsWithRootMoves,
|
|
1073
|
+
fieldToRootChanges,
|
|
1074
|
+
),
|
|
1075
|
+
// TODO: Do we need to include aliases for node changesets added during rebasing?
|
|
927
1076
|
nodeAliases: change.nodeAliases,
|
|
928
|
-
crossFieldKeys:
|
|
1077
|
+
crossFieldKeys: rebaseCrossFieldKeys(
|
|
1078
|
+
change.crossFieldKeys,
|
|
1079
|
+
crossFieldTable.movedDetaches,
|
|
1080
|
+
crossFieldTable.rebasedDetachLocations,
|
|
1081
|
+
),
|
|
929
1082
|
maxId: idState.maxId,
|
|
930
1083
|
revisions: change.revisions,
|
|
931
1084
|
constraintViolationCount: constraintState.violationCount,
|
|
@@ -933,14 +1086,18 @@ export class ModularChangeFamily
|
|
|
933
1086
|
builds: change.builds,
|
|
934
1087
|
destroys: change.destroys,
|
|
935
1088
|
refreshers: change.refreshers,
|
|
1089
|
+
rebaseVersion,
|
|
936
1090
|
});
|
|
937
1091
|
|
|
1092
|
+
// XXX: This is an expensive assert which should be disabled before merging.
|
|
1093
|
+
this.validateChangeset(rebased);
|
|
938
1094
|
return rebased;
|
|
939
1095
|
}
|
|
940
1096
|
|
|
941
1097
|
// This performs a first pass on all fields which have both new and base changes.
|
|
942
1098
|
// TODO: Can we also handle additional passes in this method?
|
|
943
1099
|
private rebaseIntersectingFields(
|
|
1100
|
+
rootChanges: [newChangeset: NodeId, baseChangeset: NodeId][],
|
|
944
1101
|
crossFieldTable: RebaseTable,
|
|
945
1102
|
rebasedNodes: ChangeAtomIdBTree<NodeChangeset>,
|
|
946
1103
|
genId: IdAllocator,
|
|
@@ -957,6 +1114,18 @@ export class ModularChangeFamily
|
|
|
957
1114
|
metadata,
|
|
958
1115
|
);
|
|
959
1116
|
|
|
1117
|
+
for (const [newChildChange, baseChildChange] of rootChanges) {
|
|
1118
|
+
const rebasedNode = this.rebaseNodeChange(
|
|
1119
|
+
newChildChange,
|
|
1120
|
+
baseChildChange,
|
|
1121
|
+
genId,
|
|
1122
|
+
crossFieldTable,
|
|
1123
|
+
metadata,
|
|
1124
|
+
);
|
|
1125
|
+
|
|
1126
|
+
setInChangeAtomIdMap(rebasedNodes, newChildChange, rebasedNode);
|
|
1127
|
+
}
|
|
1128
|
+
|
|
960
1129
|
// This loop processes all fields which have both base and new changes.
|
|
961
1130
|
// Note that the call to `rebaseNodeChange` can add entries to `crossFieldTable.nodeIdPairs`.
|
|
962
1131
|
for (const [newId, baseId, _attachState] of crossFieldTable.nodeIdPairs) {
|
|
@@ -974,146 +1143,150 @@ export class ModularChangeFamily
|
|
|
974
1143
|
return rebasedFields;
|
|
975
1144
|
}
|
|
976
1145
|
|
|
977
|
-
|
|
978
|
-
|
|
1146
|
+
private rebaseFieldWithoutNewChanges(
|
|
1147
|
+
baseFieldChange: FieldChange,
|
|
1148
|
+
baseFieldId: FieldId,
|
|
1149
|
+
crossFieldTable: RebaseTable,
|
|
979
1150
|
rebasedFields: FieldChangeMap,
|
|
980
1151
|
rebasedNodes: ChangeAtomIdBTree<NodeChangeset>,
|
|
981
|
-
crossFieldTable: RebaseTable,
|
|
982
1152
|
genId: IdAllocator,
|
|
983
1153
|
metadata: RebaseRevisionMetadata,
|
|
1154
|
+
|
|
1155
|
+
/**
|
|
1156
|
+
* The ID of a node in `baseFieldChange` which should be included in the rebased field change.
|
|
1157
|
+
*/
|
|
1158
|
+
baseNodeId?: NodeId,
|
|
984
1159
|
): void {
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
1160
|
+
// This field has no changes in the new changeset, otherwise it would have been added to
|
|
1161
|
+
// `crossFieldTable.baseFieldToContext` when processing fields with both base and new changes.
|
|
1162
|
+
const rebaseChild = (
|
|
1163
|
+
child: NodeId | undefined,
|
|
1164
|
+
baseChild: NodeId | undefined,
|
|
1165
|
+
stateChange: NodeAttachState | undefined,
|
|
1166
|
+
): NodeId | undefined => {
|
|
1167
|
+
assert(child === undefined, 0x9c3 /* There should be no new changes in this field */);
|
|
1168
|
+
if (baseChild === undefined || baseNodeId === undefined) {
|
|
1169
|
+
return undefined;
|
|
1170
|
+
}
|
|
991
1171
|
|
|
992
|
-
|
|
993
|
-
baseChange.
|
|
994
|
-
baseChange.nodeChanges,
|
|
1172
|
+
return areEqualChangeAtomIds(
|
|
1173
|
+
normalizeNodeId(baseChild, crossFieldTable.baseChange.nodeAliases),
|
|
995
1174
|
baseNodeId,
|
|
996
|
-
)
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
0x9c2 /* Cross field key registered for empty field */,
|
|
1001
|
-
);
|
|
1002
|
-
if (crossFieldTable.baseFieldToContext.has(baseFieldChange)) {
|
|
1003
|
-
// This field has already been processed because there were changes to rebase.
|
|
1004
|
-
continue;
|
|
1005
|
-
}
|
|
1175
|
+
)
|
|
1176
|
+
? baseNodeId
|
|
1177
|
+
: undefined;
|
|
1178
|
+
};
|
|
1006
1179
|
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
stateChange: NodeAttachState | undefined,
|
|
1013
|
-
): NodeId | undefined => {
|
|
1014
|
-
assert(child === undefined, 0x9c3 /* There should be no new changes in this field */);
|
|
1015
|
-
return undefined;
|
|
1016
|
-
};
|
|
1180
|
+
const handler = getChangeHandler(this.fieldKinds, baseFieldChange.fieldKind);
|
|
1181
|
+
const fieldChange: FieldChange = {
|
|
1182
|
+
...baseFieldChange,
|
|
1183
|
+
change: brand(handler.createEmpty()),
|
|
1184
|
+
};
|
|
1017
1185
|
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
};
|
|
1186
|
+
const rebasedNodeId =
|
|
1187
|
+
baseFieldId.nodeId !== undefined
|
|
1188
|
+
? rebasedNodeIdFromBaseNodeId(crossFieldTable, baseFieldId.nodeId)
|
|
1189
|
+
: undefined;
|
|
1023
1190
|
|
|
1024
|
-
|
|
1025
|
-
baseNodeId !== undefined
|
|
1026
|
-
? rebasedNodeIdFromBaseNodeId(crossFieldTable, baseNodeId)
|
|
1027
|
-
: undefined;
|
|
1191
|
+
const fieldId: FieldId = { nodeId: rebasedNodeId, field: baseFieldId.field };
|
|
1028
1192
|
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1193
|
+
const rebasedField: unknown = handler.rebaser.rebase(
|
|
1194
|
+
fieldChange.change,
|
|
1195
|
+
baseFieldChange.change,
|
|
1196
|
+
rebaseChild,
|
|
1197
|
+
genId,
|
|
1198
|
+
new RebaseNodeManagerI(crossFieldTable, fieldId),
|
|
1199
|
+
metadata,
|
|
1200
|
+
crossFieldTable.rebaseVersion,
|
|
1201
|
+
);
|
|
1038
1202
|
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1203
|
+
const rebasedFieldChange: FieldChange = {
|
|
1204
|
+
...baseFieldChange,
|
|
1205
|
+
change: brand(rebasedField),
|
|
1206
|
+
};
|
|
1043
1207
|
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
});
|
|
1052
|
-
crossFieldTable.rebasedFields.add(rebasedFieldChange);
|
|
1208
|
+
const context: RebaseFieldContext = {
|
|
1209
|
+
newChange: fieldChange,
|
|
1210
|
+
baseChange: baseFieldChange,
|
|
1211
|
+
rebasedChange: rebasedFieldChange,
|
|
1212
|
+
fieldId,
|
|
1213
|
+
baseNodeIds: newTupleBTree(),
|
|
1214
|
+
};
|
|
1053
1215
|
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
rebasedNodes,
|
|
1057
|
-
crossFieldTable,
|
|
1058
|
-
rebasedFieldChange,
|
|
1059
|
-
fieldId,
|
|
1060
|
-
genId,
|
|
1061
|
-
metadata,
|
|
1062
|
-
);
|
|
1216
|
+
if (baseNodeId !== undefined) {
|
|
1217
|
+
setInChangeAtomIdMap(context.baseNodeIds, baseNodeId, true);
|
|
1063
1218
|
}
|
|
1064
|
-
}
|
|
1065
1219
|
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
idAllocator: IdAllocator,
|
|
1072
|
-
): void {
|
|
1073
|
-
this.rebaseFieldsWithoutNewChanges(
|
|
1220
|
+
crossFieldTable.baseFieldToContext.set(baseFieldChange, context);
|
|
1221
|
+
|
|
1222
|
+
crossFieldTable.rebasedFields.add(rebasedFieldChange);
|
|
1223
|
+
|
|
1224
|
+
this.attachRebasedField(
|
|
1074
1225
|
rebasedFields,
|
|
1075
1226
|
rebasedNodes,
|
|
1076
|
-
|
|
1077
|
-
|
|
1227
|
+
crossFieldTable,
|
|
1228
|
+
rebasedFieldChange,
|
|
1229
|
+
fieldId,
|
|
1230
|
+
genId,
|
|
1078
1231
|
metadata,
|
|
1079
1232
|
);
|
|
1080
|
-
|
|
1081
|
-
this.rebaseFieldsWithUnattachedChild(table, metadata, idAllocator);
|
|
1082
|
-
this.rebaseInvalidatedFields(table, metadata, idAllocator);
|
|
1083
1233
|
}
|
|
1084
1234
|
|
|
1085
1235
|
private rebaseInvalidatedFields(
|
|
1236
|
+
rebasedFields: FieldChangeMap,
|
|
1237
|
+
rebasedNodes: ChangeAtomIdBTree<NodeChangeset>,
|
|
1086
1238
|
crossFieldTable: RebaseTable,
|
|
1087
1239
|
rebaseMetadata: RebaseRevisionMetadata,
|
|
1088
1240
|
genId: IdAllocator,
|
|
1089
1241
|
): void {
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1242
|
+
while (crossFieldTable.affectedBaseFields.size > 0) {
|
|
1243
|
+
const baseFields = crossFieldTable.affectedBaseFields.clone();
|
|
1244
|
+
crossFieldTable.affectedBaseFields.clear();
|
|
1245
|
+
|
|
1246
|
+
for (const baseFieldIdKey of baseFields.keys()) {
|
|
1247
|
+
const baseFieldId = normalizeFieldId(
|
|
1248
|
+
fieldIdFromFieldIdKey(baseFieldIdKey),
|
|
1249
|
+
crossFieldTable.baseChange.nodeAliases,
|
|
1250
|
+
);
|
|
1096
1251
|
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1252
|
+
const baseField = fieldChangeFromId(crossFieldTable.baseChange, baseFieldId);
|
|
1253
|
+
|
|
1254
|
+
assert(
|
|
1255
|
+
baseField !== undefined,
|
|
1256
|
+
0x9c2 /* Cross field key registered for empty field */,
|
|
1257
|
+
);
|
|
1258
|
+
|
|
1259
|
+
const context = crossFieldTable.baseFieldToContext.get(baseField);
|
|
1260
|
+
if (context === undefined) {
|
|
1261
|
+
this.rebaseFieldWithoutNewChanges(
|
|
1262
|
+
baseField,
|
|
1263
|
+
baseFieldId,
|
|
1264
|
+
crossFieldTable,
|
|
1265
|
+
rebasedFields,
|
|
1266
|
+
rebasedNodes,
|
|
1267
|
+
genId,
|
|
1268
|
+
rebaseMetadata,
|
|
1269
|
+
);
|
|
1270
|
+
} else {
|
|
1271
|
+
this.rebaseInvalidatedField(
|
|
1272
|
+
baseField,
|
|
1273
|
+
crossFieldTable,
|
|
1274
|
+
context,
|
|
1275
|
+
rebaseMetadata,
|
|
1276
|
+
genId,
|
|
1277
|
+
);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1105
1280
|
}
|
|
1106
1281
|
}
|
|
1107
1282
|
|
|
1108
1283
|
private rebaseInvalidatedField(
|
|
1109
1284
|
baseField: FieldChange,
|
|
1110
1285
|
crossFieldTable: RebaseTable,
|
|
1286
|
+
context: RebaseFieldContext,
|
|
1111
1287
|
rebaseMetadata: RebaseRevisionMetadata,
|
|
1112
1288
|
genId: IdAllocator,
|
|
1113
|
-
allowInval = false,
|
|
1114
1289
|
): void {
|
|
1115
|
-
const context = crossFieldTable.baseFieldToContext.get(baseField);
|
|
1116
|
-
assert(context !== undefined, 0x852 /* Every field should have a context */);
|
|
1117
1290
|
const {
|
|
1118
1291
|
changeHandler,
|
|
1119
1292
|
change1: fieldChangeset,
|
|
@@ -1128,25 +1301,28 @@ export class ModularChangeFamily
|
|
|
1128
1301
|
return curr;
|
|
1129
1302
|
}
|
|
1130
1303
|
|
|
1131
|
-
if (base !== undefined) {
|
|
1132
|
-
|
|
1133
|
-
if (areEqualChangeAtomIds(base, id)) {
|
|
1134
|
-
return base;
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
1304
|
+
if (base !== undefined && getFromChangeAtomIdMap(context.baseNodeIds, base) === true) {
|
|
1305
|
+
return base;
|
|
1137
1306
|
}
|
|
1138
1307
|
|
|
1139
1308
|
return undefined;
|
|
1140
1309
|
};
|
|
1141
1310
|
|
|
1311
|
+
let allowInval = false;
|
|
1312
|
+
if (crossFieldTable.fieldsWithUnattachedChild.has(baseField)) {
|
|
1313
|
+
crossFieldTable.fieldsWithUnattachedChild.delete(baseField);
|
|
1314
|
+
allowInval = true;
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1142
1317
|
context.rebasedChange.change = brand(
|
|
1143
1318
|
changeHandler.rebaser.rebase(
|
|
1144
1319
|
fieldChangeset,
|
|
1145
1320
|
baseChangeset,
|
|
1146
1321
|
rebaseChild,
|
|
1147
1322
|
genId,
|
|
1148
|
-
new
|
|
1323
|
+
new RebaseNodeManagerI(crossFieldTable, context.fieldId, allowInval),
|
|
1149
1324
|
rebaseMetadata,
|
|
1325
|
+
crossFieldTable.rebaseVersion,
|
|
1150
1326
|
),
|
|
1151
1327
|
);
|
|
1152
1328
|
}
|
|
@@ -1166,13 +1342,19 @@ export class ModularChangeFamily
|
|
|
1166
1342
|
}
|
|
1167
1343
|
const rebasedNode = getFromChangeAtomIdMap(rebasedNodes, nodeId);
|
|
1168
1344
|
if (rebasedNode !== undefined) {
|
|
1169
|
-
|
|
1170
|
-
|
|
1345
|
+
const updatedRebasedNode: Mutable<NodeChangeset> = cloneNodeChangeset(rebasedNode);
|
|
1346
|
+
setInChangeAtomIdMap(rebasedNodes, nodeId, updatedRebasedNode);
|
|
1347
|
+
|
|
1348
|
+
if (updatedRebasedNode.fieldChanges === undefined) {
|
|
1349
|
+
updatedRebasedNode.fieldChanges = new Map([[fieldKey, rebasedField]]);
|
|
1171
1350
|
return;
|
|
1172
1351
|
}
|
|
1173
1352
|
|
|
1174
|
-
assert(
|
|
1175
|
-
|
|
1353
|
+
assert(
|
|
1354
|
+
!updatedRebasedNode.fieldChanges.has(fieldKey),
|
|
1355
|
+
0x9c4 /* Expected an empty field */,
|
|
1356
|
+
);
|
|
1357
|
+
updatedRebasedNode.fieldChanges.set(fieldKey, rebasedField);
|
|
1176
1358
|
return;
|
|
1177
1359
|
}
|
|
1178
1360
|
|
|
@@ -1183,14 +1365,14 @@ export class ModularChangeFamily
|
|
|
1183
1365
|
setInChangeAtomIdMap(rebasedNodes, nodeId, newNode);
|
|
1184
1366
|
setInChangeAtomIdMap(table.baseToRebasedNodeId, nodeId, nodeId);
|
|
1185
1367
|
|
|
1186
|
-
const
|
|
1368
|
+
const parentBase = getNodeParent(table.baseChange, nodeId);
|
|
1187
1369
|
|
|
1188
1370
|
this.attachRebasedNode(
|
|
1189
1371
|
rebasedFields,
|
|
1190
1372
|
rebasedNodes,
|
|
1191
1373
|
table,
|
|
1192
1374
|
nodeId,
|
|
1193
|
-
|
|
1375
|
+
parentBase,
|
|
1194
1376
|
idAllocator,
|
|
1195
1377
|
metadata,
|
|
1196
1378
|
);
|
|
@@ -1201,65 +1383,100 @@ export class ModularChangeFamily
|
|
|
1201
1383
|
rebasedNodes: ChangeAtomIdBTree<NodeChangeset>,
|
|
1202
1384
|
table: RebaseTable,
|
|
1203
1385
|
baseNodeId: NodeId,
|
|
1204
|
-
|
|
1386
|
+
parentBase: NodeLocation,
|
|
1205
1387
|
idAllocator: IdAllocator,
|
|
1206
1388
|
metadata: RebaseRevisionMetadata,
|
|
1207
1389
|
): void {
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1390
|
+
if (parentBase.root !== undefined) {
|
|
1391
|
+
const renamedRoot = firstAttachIdFromDetachId(
|
|
1392
|
+
table.baseChange.rootNodes,
|
|
1393
|
+
parentBase.root,
|
|
1394
|
+
1,
|
|
1395
|
+
).value;
|
|
1396
|
+
|
|
1397
|
+
const attachField = table.baseChange.crossFieldKeys.getFirst(
|
|
1398
|
+
{ ...renamedRoot, target: CrossFieldTarget.Destination },
|
|
1399
|
+
1,
|
|
1400
|
+
).value;
|
|
1401
|
+
|
|
1402
|
+
if (attachField !== undefined) {
|
|
1403
|
+
// The base change inserts this node into `attachField`, so the rebased change should represent this node there.
|
|
1404
|
+
const normalizedAttachField = normalizeFieldId(
|
|
1405
|
+
attachField,
|
|
1406
|
+
table.baseChange.nodeAliases,
|
|
1407
|
+
);
|
|
1408
|
+
|
|
1409
|
+
const entry: DetachedNodeEntry = table.entries.getFirst(renamedRoot, 1).value ?? {};
|
|
1410
|
+
table.entries.set(renamedRoot, 1, { ...entry, nodeChange: baseNodeId });
|
|
1411
|
+
table.affectedBaseFields.set(fieldIdKeyFromFieldId(normalizedAttachField), true);
|
|
1412
|
+
this.attachRebasedNode(
|
|
1413
|
+
rebasedFields,
|
|
1414
|
+
rebasedNodes,
|
|
1415
|
+
table,
|
|
1416
|
+
baseNodeId,
|
|
1417
|
+
{ field: normalizedAttachField },
|
|
1418
|
+
idAllocator,
|
|
1419
|
+
metadata,
|
|
1420
|
+
);
|
|
1421
|
+
} else {
|
|
1422
|
+
const baseDetachLocation = table.baseChange.rootNodes.detachLocations.getFirst(
|
|
1423
|
+
parentBase.root,
|
|
1424
|
+
1,
|
|
1425
|
+
).value;
|
|
1426
|
+
|
|
1427
|
+
assignRootChange(
|
|
1428
|
+
table.rebasedRootNodes,
|
|
1429
|
+
table.rebasedNodeToParent,
|
|
1430
|
+
renamedRoot,
|
|
1431
|
+
baseNodeId,
|
|
1432
|
+
baseDetachLocation,
|
|
1433
|
+
table.rebaseVersion,
|
|
1434
|
+
);
|
|
1435
|
+
|
|
1436
|
+
// We need to make sure the rebased changeset includes the detach location,
|
|
1437
|
+
// so we add that field to `affectedBaseFields` unless it's already been processed.
|
|
1438
|
+
if (
|
|
1439
|
+
baseDetachLocation !== undefined &&
|
|
1440
|
+
!table.baseFieldToContext.has(
|
|
1441
|
+
fieldChangeFromId(table.baseChange, baseDetachLocation),
|
|
1442
|
+
)
|
|
1443
|
+
) {
|
|
1444
|
+
table.affectedBaseFields.set(fieldIdKeyFromFieldId(baseDetachLocation), true);
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1216
1447
|
|
|
1217
|
-
const context = table.baseFieldToContext.get(baseFieldChange);
|
|
1218
|
-
if (context !== undefined) {
|
|
1219
|
-
// We've already processed this field.
|
|
1220
|
-
// The new child node will be attached in rebaseFieldsWithUnattachedChild.
|
|
1221
|
-
context.baseNodeIds.push(baseNodeId);
|
|
1222
|
-
table.fieldsWithUnattachedChild.add(baseFieldChange);
|
|
1223
1448
|
return;
|
|
1224
1449
|
}
|
|
1225
1450
|
|
|
1226
|
-
const
|
|
1227
|
-
|
|
1228
|
-
const fieldChange: FieldChange = {
|
|
1229
|
-
...baseFieldChange,
|
|
1230
|
-
change: brand(handler.createEmpty()),
|
|
1231
|
-
};
|
|
1451
|
+
const parentFieldIdBase = parentBase.field;
|
|
1452
|
+
const baseFieldChange = fieldChangeFromId(table.baseChange, parentFieldIdBase);
|
|
1232
1453
|
|
|
1233
|
-
const
|
|
1234
|
-
|
|
1235
|
-
baseFieldChange.change,
|
|
1236
|
-
(_idNew, idBase) =>
|
|
1237
|
-
idBase !== undefined && areEqualChangeAtomIds(idBase, baseNodeId)
|
|
1238
|
-
? baseNodeId
|
|
1239
|
-
: undefined,
|
|
1240
|
-
idAllocator,
|
|
1241
|
-
new RebaseManager(table, baseFieldChange, rebasedFieldId),
|
|
1242
|
-
metadata,
|
|
1243
|
-
);
|
|
1454
|
+
const rebasedFieldId = rebasedFieldIdFromBaseId(table, parentFieldIdBase);
|
|
1455
|
+
setInChangeAtomIdMap(table.rebasedNodeToParent, baseNodeId, { field: rebasedFieldId });
|
|
1244
1456
|
|
|
1245
|
-
const
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
baseNodeIds
|
|
1253
|
-
|
|
1457
|
+
const context = table.baseFieldToContext.get(baseFieldChange);
|
|
1458
|
+
if (context !== undefined) {
|
|
1459
|
+
// We've already processed this field.
|
|
1460
|
+
// The new child node will be attached in the next pass.
|
|
1461
|
+
// Note that adding to `fieldsWithUnattachedChild` allows that field to generate new invalidations,
|
|
1462
|
+
// so to avoid invalidation cycles we make sure we only add to it once per new unattached child.
|
|
1463
|
+
// This is done by checking whether `context.baseNodeIds` already contained `baseNodeId`.
|
|
1464
|
+
if (setInChangeAtomIdMap(context.baseNodeIds, baseNodeId, true)) {
|
|
1465
|
+
table.fieldsWithUnattachedChild.add(baseFieldChange);
|
|
1466
|
+
table.affectedBaseFields.set(fieldIdKeyFromFieldId(parentFieldIdBase), true);
|
|
1467
|
+
}
|
|
1468
|
+
return;
|
|
1469
|
+
}
|
|
1254
1470
|
|
|
1255
|
-
this.
|
|
1471
|
+
this.rebaseFieldWithoutNewChanges(
|
|
1472
|
+
baseFieldChange,
|
|
1473
|
+
parentFieldIdBase,
|
|
1474
|
+
table,
|
|
1256
1475
|
rebasedFields,
|
|
1257
1476
|
rebasedNodes,
|
|
1258
|
-
table,
|
|
1259
|
-
rebasedField,
|
|
1260
|
-
rebasedFieldId,
|
|
1261
1477
|
idAllocator,
|
|
1262
1478
|
metadata,
|
|
1479
|
+
baseNodeId,
|
|
1263
1480
|
);
|
|
1264
1481
|
}
|
|
1265
1482
|
|
|
@@ -1298,7 +1515,7 @@ export class ModularChangeFamily
|
|
|
1298
1515
|
change2: baseChangeset,
|
|
1299
1516
|
} = this.normalizeFieldChanges(fieldChange, baseChange);
|
|
1300
1517
|
|
|
1301
|
-
const manager = new
|
|
1518
|
+
const manager = new RebaseNodeManagerI(crossFieldTable, fieldId);
|
|
1302
1519
|
|
|
1303
1520
|
const rebasedField = changeHandler.rebaser.rebase(
|
|
1304
1521
|
fieldChangeset,
|
|
@@ -1307,6 +1524,7 @@ export class ModularChangeFamily
|
|
|
1307
1524
|
genId,
|
|
1308
1525
|
manager,
|
|
1309
1526
|
revisionMetadata,
|
|
1527
|
+
crossFieldTable.rebaseVersion,
|
|
1310
1528
|
);
|
|
1311
1529
|
|
|
1312
1530
|
const rebasedFieldChange: FieldChange = {
|
|
@@ -1321,7 +1539,7 @@ export class ModularChangeFamily
|
|
|
1321
1539
|
newChange: fieldChange,
|
|
1322
1540
|
rebasedChange: rebasedFieldChange,
|
|
1323
1541
|
fieldId,
|
|
1324
|
-
baseNodeIds:
|
|
1542
|
+
baseNodeIds: newTupleBTree(),
|
|
1325
1543
|
});
|
|
1326
1544
|
|
|
1327
1545
|
crossFieldTable.rebasedFields.add(rebasedFieldChange);
|
|
@@ -1337,8 +1555,16 @@ export class ModularChangeFamily
|
|
|
1337
1555
|
crossFieldTable: RebaseTable,
|
|
1338
1556
|
revisionMetadata: RebaseRevisionMetadata,
|
|
1339
1557
|
): NodeChangeset {
|
|
1340
|
-
const change = nodeChangeFromId(
|
|
1341
|
-
|
|
1558
|
+
const change = nodeChangeFromId(
|
|
1559
|
+
crossFieldTable.newChange.nodeChanges,
|
|
1560
|
+
crossFieldTable.newChange.nodeAliases,
|
|
1561
|
+
newId,
|
|
1562
|
+
);
|
|
1563
|
+
const over = nodeChangeFromId(
|
|
1564
|
+
crossFieldTable.baseChange.nodeChanges,
|
|
1565
|
+
crossFieldTable.baseChange.nodeAliases,
|
|
1566
|
+
baseId,
|
|
1567
|
+
);
|
|
1342
1568
|
|
|
1343
1569
|
const baseMap: FieldChangeMap = over?.fieldChanges ?? new Map();
|
|
1344
1570
|
|
|
@@ -1354,7 +1580,7 @@ export class ModularChangeFamily
|
|
|
1354
1580
|
)
|
|
1355
1581
|
: change.fieldChanges;
|
|
1356
1582
|
|
|
1357
|
-
const rebasedChange: NodeChangeset = {};
|
|
1583
|
+
const rebasedChange: Mutable<NodeChangeset> = {};
|
|
1358
1584
|
|
|
1359
1585
|
if (fieldChanges !== undefined && fieldChanges.size > 0) {
|
|
1360
1586
|
rebasedChange.fieldChanges = fieldChanges;
|
|
@@ -1372,6 +1598,37 @@ export class ModularChangeFamily
|
|
|
1372
1598
|
return rebasedChange;
|
|
1373
1599
|
}
|
|
1374
1600
|
|
|
1601
|
+
private updateConstraints(
|
|
1602
|
+
rebasedFields: FieldChangeMap,
|
|
1603
|
+
rebasedNodes: ChangeAtomIdBTree<NodeChangeset>,
|
|
1604
|
+
rebasedRoots: RootNodeTable,
|
|
1605
|
+
constraintState: ConstraintState,
|
|
1606
|
+
revertConstraintState: ConstraintState,
|
|
1607
|
+
): void {
|
|
1608
|
+
this.updateConstraintsForFields(
|
|
1609
|
+
rebasedFields,
|
|
1610
|
+
NodeAttachState.Attached,
|
|
1611
|
+
NodeAttachState.Attached,
|
|
1612
|
+
constraintState,
|
|
1613
|
+
revertConstraintState,
|
|
1614
|
+
rebasedNodes,
|
|
1615
|
+
);
|
|
1616
|
+
|
|
1617
|
+
for (const [_detachId, nodeId] of rebasedRoots.nodeChanges.entries()) {
|
|
1618
|
+
// XXX: This is incorrect if the rebased changeset attaches the node.
|
|
1619
|
+
// Efficiently computing whether the changeset attaches the node would require maintaining a mapping from node ID to attach ID.
|
|
1620
|
+
const detachedInOutput = true;
|
|
1621
|
+
this.updateConstraintsForNode(
|
|
1622
|
+
nodeId,
|
|
1623
|
+
NodeAttachState.Detached,
|
|
1624
|
+
detachedInOutput ? NodeAttachState.Detached : NodeAttachState.Attached,
|
|
1625
|
+
rebasedNodes,
|
|
1626
|
+
constraintState,
|
|
1627
|
+
revertConstraintState,
|
|
1628
|
+
);
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1375
1632
|
private updateConstraintsForFields(
|
|
1376
1633
|
fields: FieldChangeMap,
|
|
1377
1634
|
parentInputAttachState: NodeAttachState,
|
|
@@ -1382,20 +1639,18 @@ export class ModularChangeFamily
|
|
|
1382
1639
|
): void {
|
|
1383
1640
|
for (const field of fields.values()) {
|
|
1384
1641
|
const handler = getChangeHandler(this.fieldKinds, field.fieldKind);
|
|
1385
|
-
for (const [nodeId
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
? NodeAttachState.Detached
|
|
1390
|
-
: NodeAttachState.Attached;
|
|
1391
|
-
const isOutputDetached = outputIndex === undefined;
|
|
1642
|
+
for (const [nodeId] of handler.getNestedChanges(field.change)) {
|
|
1643
|
+
// XXX: This is incorrect if the rebased changeset detaches this node.
|
|
1644
|
+
// Efficiently computing whether the changeset detaches the node would require maintaining a mapping from node ID to detach ID.
|
|
1645
|
+
const isOutputDetached = false;
|
|
1392
1646
|
const outputAttachState =
|
|
1393
1647
|
parentOutputAttachState === NodeAttachState.Detached || isOutputDetached
|
|
1394
1648
|
? NodeAttachState.Detached
|
|
1395
1649
|
: NodeAttachState.Attached;
|
|
1650
|
+
|
|
1396
1651
|
this.updateConstraintsForNode(
|
|
1397
1652
|
nodeId,
|
|
1398
|
-
|
|
1653
|
+
parentInputAttachState,
|
|
1399
1654
|
outputAttachState,
|
|
1400
1655
|
nodes,
|
|
1401
1656
|
constraintState,
|
|
@@ -1413,12 +1668,15 @@ export class ModularChangeFamily
|
|
|
1413
1668
|
constraintState: ConstraintState,
|
|
1414
1669
|
revertConstraintState: ConstraintState,
|
|
1415
1670
|
): void {
|
|
1416
|
-
const node =
|
|
1417
|
-
|
|
1671
|
+
const node = getFromChangeAtomIdMap(nodes, nodeId) ?? fail(0xb24 /* Unknown node ID */);
|
|
1672
|
+
|
|
1673
|
+
const updatedNode: Mutable<NodeChangeset> = { ...node };
|
|
1674
|
+
setInChangeAtomIdMap(nodes, nodeId, updatedNode);
|
|
1675
|
+
|
|
1418
1676
|
if (node.nodeExistsConstraint !== undefined) {
|
|
1419
1677
|
const isNowViolated = inputAttachState === NodeAttachState.Detached;
|
|
1420
1678
|
if (node.nodeExistsConstraint.violated !== isNowViolated) {
|
|
1421
|
-
|
|
1679
|
+
updatedNode.nodeExistsConstraint = {
|
|
1422
1680
|
...node.nodeExistsConstraint,
|
|
1423
1681
|
violated: isNowViolated,
|
|
1424
1682
|
};
|
|
@@ -1428,7 +1686,7 @@ export class ModularChangeFamily
|
|
|
1428
1686
|
if (node.nodeExistsConstraintOnRevert !== undefined) {
|
|
1429
1687
|
const isNowViolated = outputAttachState === NodeAttachState.Detached;
|
|
1430
1688
|
if (node.nodeExistsConstraintOnRevert.violated !== isNowViolated) {
|
|
1431
|
-
|
|
1689
|
+
updatedNode.nodeExistsConstraintOnRevert = {
|
|
1432
1690
|
...node.nodeExistsConstraintOnRevert,
|
|
1433
1691
|
violated: isNowViolated,
|
|
1434
1692
|
};
|
|
@@ -1450,7 +1708,13 @@ export class ModularChangeFamily
|
|
|
1450
1708
|
|
|
1451
1709
|
private pruneFieldMap(
|
|
1452
1710
|
changeset: FieldChangeMap | undefined,
|
|
1711
|
+
parentId: NodeId | undefined,
|
|
1453
1712
|
nodeMap: ChangeAtomIdBTree<NodeChangeset>,
|
|
1713
|
+
nodeToParent: ChangeAtomIdBTree<NodeLocation>,
|
|
1714
|
+
aliases: ChangeAtomIdBTree<NodeId>,
|
|
1715
|
+
roots: RootNodeTable,
|
|
1716
|
+
fieldsWithRootMoves: TupleBTree<FieldIdKey, boolean>,
|
|
1717
|
+
fieldsToRootChanges: TupleBTree<FieldIdKey, ChangeAtomId[]>,
|
|
1454
1718
|
): FieldChangeMap | undefined {
|
|
1455
1719
|
if (changeset === undefined) {
|
|
1456
1720
|
return undefined;
|
|
@@ -1461,10 +1725,48 @@ export class ModularChangeFamily
|
|
|
1461
1725
|
const handler = getChangeHandler(this.fieldKinds, fieldChange.fieldKind);
|
|
1462
1726
|
|
|
1463
1727
|
const prunedFieldChangeset = handler.rebaser.prune(fieldChange.change, (nodeId) =>
|
|
1464
|
-
this.pruneNodeChange(
|
|
1728
|
+
this.pruneNodeChange(
|
|
1729
|
+
nodeId,
|
|
1730
|
+
nodeMap,
|
|
1731
|
+
nodeToParent,
|
|
1732
|
+
aliases,
|
|
1733
|
+
roots,
|
|
1734
|
+
fieldsWithRootMoves,
|
|
1735
|
+
fieldsToRootChanges,
|
|
1736
|
+
),
|
|
1465
1737
|
);
|
|
1466
1738
|
|
|
1467
|
-
|
|
1739
|
+
const fieldId: FieldId = { nodeId: parentId, field };
|
|
1740
|
+
const fieldIdKey = fieldIdKeyFromFieldId(fieldId);
|
|
1741
|
+
const rootsWithChanges = fieldsToRootChanges.get(fieldIdKey) ?? [];
|
|
1742
|
+
let hasRootWithNodeChange = false;
|
|
1743
|
+
for (const rootId of rootsWithChanges) {
|
|
1744
|
+
const nodeId =
|
|
1745
|
+
getFromChangeAtomIdMap(roots.nodeChanges, rootId) ?? fail("No root change found");
|
|
1746
|
+
|
|
1747
|
+
const isRootChangeEmpty =
|
|
1748
|
+
this.pruneNodeChange(
|
|
1749
|
+
nodeId,
|
|
1750
|
+
nodeMap,
|
|
1751
|
+
nodeToParent,
|
|
1752
|
+
aliases,
|
|
1753
|
+
roots,
|
|
1754
|
+
fieldsWithRootMoves,
|
|
1755
|
+
fieldsToRootChanges,
|
|
1756
|
+
) === undefined;
|
|
1757
|
+
|
|
1758
|
+
if (isRootChangeEmpty) {
|
|
1759
|
+
roots.nodeChanges.delete([rootId.revision, rootId.localId]);
|
|
1760
|
+
tryRemoveDetachLocation(roots, rootId, 1);
|
|
1761
|
+
} else {
|
|
1762
|
+
hasRootWithNodeChange = true;
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
const hasRootChanges =
|
|
1767
|
+
hasRootWithNodeChange || fieldsWithRootMoves.get(fieldIdKey) === true;
|
|
1768
|
+
|
|
1769
|
+
if (!handler.isEmpty(prunedFieldChangeset) || hasRootChanges) {
|
|
1468
1770
|
prunedChangeset.set(field, { ...fieldChange, change: brand(prunedFieldChangeset) });
|
|
1469
1771
|
}
|
|
1470
1772
|
}
|
|
@@ -1472,14 +1774,64 @@ export class ModularChangeFamily
|
|
|
1472
1774
|
return prunedChangeset.size > 0 ? prunedChangeset : undefined;
|
|
1473
1775
|
}
|
|
1474
1776
|
|
|
1777
|
+
private pruneRoots(
|
|
1778
|
+
roots: RootNodeTable,
|
|
1779
|
+
nodeMap: ChangeAtomIdBTree<NodeChangeset>,
|
|
1780
|
+
nodeToParent: ChangeAtomIdBTree<NodeLocation>,
|
|
1781
|
+
aliases: ChangeAtomIdBTree<NodeId>,
|
|
1782
|
+
fieldsWithRootMoves: TupleBTree<FieldIdKey, boolean>,
|
|
1783
|
+
fieldsToRootChanges: TupleBTree<FieldIdKey, ChangeAtomId[]>,
|
|
1784
|
+
): RootNodeTable {
|
|
1785
|
+
const pruned: RootNodeTable = { ...roots, nodeChanges: newTupleBTree() };
|
|
1786
|
+
for (const [rootIdKey, nodeId] of roots.nodeChanges.entries()) {
|
|
1787
|
+
const rootId: ChangeAtomId = { revision: rootIdKey[0], localId: rootIdKey[1] };
|
|
1788
|
+
const hasDetachLocation = roots.detachLocations.getFirst(rootId, 1).value !== undefined;
|
|
1789
|
+
|
|
1790
|
+
// If the root has a detach location it should be pruned by recursion when pruning the field it was detached from.
|
|
1791
|
+
const prunedId = hasDetachLocation
|
|
1792
|
+
? nodeId
|
|
1793
|
+
: this.pruneNodeChange(
|
|
1794
|
+
nodeId,
|
|
1795
|
+
nodeMap,
|
|
1796
|
+
nodeToParent,
|
|
1797
|
+
aliases,
|
|
1798
|
+
roots,
|
|
1799
|
+
fieldsWithRootMoves,
|
|
1800
|
+
fieldsToRootChanges,
|
|
1801
|
+
);
|
|
1802
|
+
|
|
1803
|
+
if (prunedId !== undefined) {
|
|
1804
|
+
pruned.nodeChanges.set(rootIdKey, prunedId);
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
tryRemoveDetachLocation(pruned, rootId, 1);
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
return pruned;
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1475
1813
|
private pruneNodeChange(
|
|
1476
1814
|
nodeId: NodeId,
|
|
1477
|
-
|
|
1815
|
+
nodes: ChangeAtomIdBTree<NodeChangeset>,
|
|
1816
|
+
nodeToParent: ChangeAtomIdBTree<NodeLocation>,
|
|
1817
|
+
aliases: ChangeAtomIdBTree<NodeId>,
|
|
1818
|
+
roots: RootNodeTable,
|
|
1819
|
+
fieldsWithRootMoves: TupleBTree<FieldIdKey, boolean>,
|
|
1820
|
+
fieldsToRootChanges: TupleBTree<FieldIdKey, ChangeAtomId[]>,
|
|
1478
1821
|
): NodeId | undefined {
|
|
1479
|
-
const changeset = nodeChangeFromId(
|
|
1822
|
+
const changeset = nodeChangeFromId(nodes, aliases, nodeId);
|
|
1480
1823
|
const prunedFields =
|
|
1481
1824
|
changeset.fieldChanges !== undefined
|
|
1482
|
-
? this.pruneFieldMap(
|
|
1825
|
+
? this.pruneFieldMap(
|
|
1826
|
+
changeset.fieldChanges,
|
|
1827
|
+
nodeId,
|
|
1828
|
+
nodes,
|
|
1829
|
+
nodeToParent,
|
|
1830
|
+
aliases,
|
|
1831
|
+
roots,
|
|
1832
|
+
fieldsWithRootMoves,
|
|
1833
|
+
fieldsToRootChanges,
|
|
1834
|
+
)
|
|
1483
1835
|
: undefined;
|
|
1484
1836
|
|
|
1485
1837
|
const prunedChange = { ...changeset, fieldChanges: prunedFields };
|
|
@@ -1488,10 +1840,14 @@ export class ModularChangeFamily
|
|
|
1488
1840
|
}
|
|
1489
1841
|
|
|
1490
1842
|
if (isEmptyNodeChangeset(prunedChange)) {
|
|
1491
|
-
|
|
1843
|
+
const nodeIdKey: ChangeAtomIdKey = [nodeId.revision, nodeId.localId];
|
|
1844
|
+
|
|
1845
|
+
// TODO: Shouldn't we also delete all aliases associated with this node?
|
|
1846
|
+
nodes.delete(nodeIdKey);
|
|
1847
|
+
nodeToParent.delete(nodeIdKey);
|
|
1492
1848
|
return undefined;
|
|
1493
1849
|
} else {
|
|
1494
|
-
setInChangeAtomIdMap(
|
|
1850
|
+
setInChangeAtomIdMap(nodes, nodeId, prunedChange);
|
|
1495
1851
|
return nodeId;
|
|
1496
1852
|
}
|
|
1497
1853
|
}
|
|
@@ -1520,12 +1876,12 @@ export class ModularChangeFamily
|
|
|
1520
1876
|
);
|
|
1521
1877
|
}
|
|
1522
1878
|
|
|
1523
|
-
const updatedNodeToParent: ChangeAtomIdBTree<
|
|
1524
|
-
for (const [[revision, id],
|
|
1879
|
+
const updatedNodeToParent: ChangeAtomIdBTree<NodeLocation> = newTupleBTree();
|
|
1880
|
+
for (const [[revision, id], location] of change.nodeToParent.entries()) {
|
|
1525
1881
|
updatedNodeToParent.set(
|
|
1526
1882
|
[replaceRevision(revision, oldRevisions, newRevision), id],
|
|
1527
|
-
|
|
1528
|
-
|
|
1883
|
+
replaceNodeLocationRevision(
|
|
1884
|
+
normalizeNodeLocation(location, change.nodeAliases),
|
|
1529
1885
|
oldRevisions,
|
|
1530
1886
|
newRevision,
|
|
1531
1887
|
),
|
|
@@ -1537,15 +1893,24 @@ export class ModularChangeFamily
|
|
|
1537
1893
|
fieldChanges: updatedFields,
|
|
1538
1894
|
nodeChanges: updatedNodes,
|
|
1539
1895
|
nodeToParent: updatedNodeToParent,
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
nodeAliases: newTupleBTree(),
|
|
1543
|
-
crossFieldKeys: replaceCrossFieldKeyTableRevisions(
|
|
1544
|
-
change.crossFieldKeys,
|
|
1896
|
+
rootNodes: replaceRootTableRevision(
|
|
1897
|
+
change.rootNodes,
|
|
1545
1898
|
oldRevisions,
|
|
1546
1899
|
newRevision,
|
|
1547
1900
|
change.nodeAliases,
|
|
1548
1901
|
),
|
|
1902
|
+
|
|
1903
|
+
// We've updated all references to old node IDs, so we no longer need an alias table.
|
|
1904
|
+
nodeAliases: newTupleBTree(),
|
|
1905
|
+
crossFieldKeys: change.crossFieldKeys.mapEntries(
|
|
1906
|
+
(key) => replaceCrossFieldKeyRevision(key, oldRevisions, newRevision),
|
|
1907
|
+
(id) =>
|
|
1908
|
+
replaceFieldIdRevision(
|
|
1909
|
+
normalizeFieldId(id, change.nodeAliases),
|
|
1910
|
+
oldRevisions,
|
|
1911
|
+
newRevision,
|
|
1912
|
+
),
|
|
1913
|
+
),
|
|
1549
1914
|
};
|
|
1550
1915
|
|
|
1551
1916
|
if (change.builds !== undefined) {
|
|
@@ -1613,7 +1978,7 @@ export class ModularChangeFamily
|
|
|
1613
1978
|
fields: FieldChangeMap,
|
|
1614
1979
|
nodes: ChangeAtomIdBTree<NodeChangeset>,
|
|
1615
1980
|
): CrossFieldKeyTable {
|
|
1616
|
-
const keys: CrossFieldKeyTable =
|
|
1981
|
+
const keys: CrossFieldKeyTable = newCrossFieldRangeTable();
|
|
1617
1982
|
this.populateCrossFieldKeyTableForFieldMap(keys, fields, undefined);
|
|
1618
1983
|
nodes.forEachPair(([revision, localId], node) => {
|
|
1619
1984
|
if (node.fieldChanges !== undefined) {
|
|
@@ -1654,60 +2019,102 @@ export class ModularChangeFamily
|
|
|
1654
2019
|
}
|
|
1655
2020
|
|
|
1656
2021
|
public validateChangeset(change: ModularChangeset): void {
|
|
1657
|
-
|
|
2022
|
+
const unreachableNodes: ChangeAtomIdBTree<NodeLocation> = brand(
|
|
2023
|
+
change.nodeToParent.clone(),
|
|
2024
|
+
);
|
|
2025
|
+
|
|
2026
|
+
const unreachableCFKs = change.crossFieldKeys.clone();
|
|
2027
|
+
|
|
2028
|
+
this.validateFieldChanges(
|
|
2029
|
+
change,
|
|
2030
|
+
change.fieldChanges,
|
|
2031
|
+
undefined,
|
|
2032
|
+
unreachableNodes,
|
|
2033
|
+
unreachableCFKs,
|
|
2034
|
+
);
|
|
1658
2035
|
|
|
1659
2036
|
for (const [[revision, localId], node] of change.nodeChanges.entries()) {
|
|
1660
2037
|
if (node.fieldChanges === undefined) {
|
|
1661
2038
|
continue;
|
|
1662
2039
|
}
|
|
1663
2040
|
|
|
1664
|
-
const nodeId
|
|
1665
|
-
|
|
2041
|
+
const nodeId = normalizeNodeId({ revision, localId }, change.nodeAliases);
|
|
2042
|
+
this.validateFieldChanges(
|
|
2043
|
+
change,
|
|
2044
|
+
node.fieldChanges,
|
|
2045
|
+
nodeId,
|
|
2046
|
+
unreachableNodes,
|
|
2047
|
+
unreachableCFKs,
|
|
2048
|
+
);
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
for (const [detachIdKey, nodeId] of change.rootNodes.nodeChanges.entries()) {
|
|
2052
|
+
const detachId: ChangeAtomId = { revision: detachIdKey[0], localId: detachIdKey[1] };
|
|
2053
|
+
const location = getNodeParent(change, nodeId);
|
|
2054
|
+
assert(areEqualChangeAtomIdOpts(location.root, detachId), "Inconsistent node location");
|
|
1666
2055
|
|
|
1667
|
-
|
|
2056
|
+
const normalizedNodeId = normalizeNodeId(nodeId, change.nodeAliases);
|
|
2057
|
+
unreachableNodes.delete([normalizedNodeId.revision, normalizedNodeId.localId]);
|
|
2058
|
+
|
|
2059
|
+
const fieldChanges = nodeChangeFromId(
|
|
2060
|
+
change.nodeChanges,
|
|
2061
|
+
change.nodeAliases,
|
|
2062
|
+
nodeId,
|
|
2063
|
+
).fieldChanges;
|
|
2064
|
+
|
|
2065
|
+
if (fieldChanges !== undefined) {
|
|
2066
|
+
this.validateFieldChanges(
|
|
2067
|
+
change,
|
|
2068
|
+
fieldChanges,
|
|
2069
|
+
normalizedNodeId,
|
|
2070
|
+
unreachableNodes,
|
|
2071
|
+
unreachableCFKs,
|
|
2072
|
+
);
|
|
2073
|
+
}
|
|
1668
2074
|
}
|
|
1669
2075
|
|
|
1670
|
-
assert(
|
|
1671
|
-
|
|
1672
|
-
0xa4d /* Node table contains unparented nodes */,
|
|
1673
|
-
);
|
|
2076
|
+
assert(unreachableNodes.size === 0, "Unreachable nodes found");
|
|
2077
|
+
assert(unreachableCFKs.entries().length === 0, "Unreachable cross-field keys found");
|
|
1674
2078
|
}
|
|
1675
2079
|
|
|
1676
2080
|
/**
|
|
1677
|
-
* Asserts that each
|
|
1678
|
-
*
|
|
2081
|
+
* Asserts that each node has a correct entry in `change.nodeToParent`,
|
|
2082
|
+
* and each cross field key has a correct entry in `change.crossFieldKeys`.
|
|
1679
2083
|
* @returns the number of children found.
|
|
1680
2084
|
*/
|
|
1681
2085
|
private validateFieldChanges(
|
|
1682
2086
|
change: ModularChangeset,
|
|
1683
2087
|
fieldChanges: FieldChangeMap,
|
|
1684
2088
|
nodeParent: NodeId | undefined,
|
|
1685
|
-
|
|
1686
|
-
|
|
2089
|
+
unreachableNodes: ChangeAtomIdBTree<NodeLocation>,
|
|
2090
|
+
unreachableCFKs: CrossFieldRangeTable<FieldId>,
|
|
2091
|
+
): void {
|
|
1687
2092
|
for (const [field, fieldChange] of fieldChanges.entries()) {
|
|
1688
2093
|
const fieldId = { nodeId: nodeParent, field };
|
|
1689
2094
|
const handler = getChangeHandler(this.fieldKinds, fieldChange.fieldKind);
|
|
1690
2095
|
for (const [child, _index] of handler.getNestedChanges(fieldChange.change)) {
|
|
1691
|
-
const parentFieldId =
|
|
2096
|
+
const parentFieldId = getNodeParent(change, child);
|
|
1692
2097
|
assert(
|
|
1693
|
-
areEqualFieldIds(parentFieldId, fieldId),
|
|
2098
|
+
parentFieldId.field !== undefined && areEqualFieldIds(parentFieldId.field, fieldId),
|
|
1694
2099
|
0xa4e /* Inconsistent node parentage */,
|
|
1695
2100
|
);
|
|
1696
|
-
|
|
2101
|
+
|
|
2102
|
+
unreachableNodes.delete([child.revision, child.localId]);
|
|
1697
2103
|
}
|
|
1698
2104
|
|
|
1699
2105
|
for (const keyRange of handler.getCrossFieldKeys(fieldChange.change)) {
|
|
1700
2106
|
const fields = getFieldsForCrossFieldKey(change, keyRange.key, keyRange.count);
|
|
1701
|
-
assert(
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
areEqualFieldIds(
|
|
1705
|
-
|
|
1706
|
-
|
|
2107
|
+
assert(fields.length > 0, "Unregistered cross-field key");
|
|
2108
|
+
for (const fieldFromLookup of fields) {
|
|
2109
|
+
assert(
|
|
2110
|
+
areEqualFieldIds(fieldFromLookup, fieldId),
|
|
2111
|
+
0xa4f /* Inconsistent cross field keys */,
|
|
2112
|
+
);
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
unreachableCFKs.delete(keyRange.key, keyRange.count);
|
|
1707
2116
|
}
|
|
1708
2117
|
}
|
|
1709
|
-
|
|
1710
|
-
return numChildren;
|
|
1711
2118
|
}
|
|
1712
2119
|
|
|
1713
2120
|
private getEffectiveChange(change: ModularChangeset): ModularChangeset {
|
|
@@ -1723,7 +2130,8 @@ export class ModularChangeFamily
|
|
|
1723
2130
|
private muteChange(change: ModularChangeset): ModularChangeset {
|
|
1724
2131
|
const muted: Mutable<ModularChangeset> = {
|
|
1725
2132
|
...change,
|
|
1726
|
-
|
|
2133
|
+
rootNodes: muteRootChanges(change.rootNodes),
|
|
2134
|
+
crossFieldKeys: newCrossFieldRangeTable(),
|
|
1727
2135
|
fieldChanges: this.muteFieldChanges(change.fieldChanges),
|
|
1728
2136
|
nodeChanges: brand(change.nodeChanges.mapValues((v) => this.muteNodeChange(v))),
|
|
1729
2137
|
};
|
|
@@ -1755,37 +2163,16 @@ export class ModularChangeFamily
|
|
|
1755
2163
|
}
|
|
1756
2164
|
}
|
|
1757
2165
|
|
|
1758
|
-
function
|
|
1759
|
-
|
|
2166
|
+
function replaceCrossFieldKeyRevision(
|
|
2167
|
+
key: CrossFieldKey,
|
|
1760
2168
|
oldRevisions: Set<RevisionTag | undefined>,
|
|
1761
2169
|
newRevision: RevisionTag | undefined,
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
target: key.target,
|
|
1769
|
-
revision: replaceRevision(key.revision, oldRevisions, newRevision),
|
|
1770
|
-
localId: key.localId,
|
|
1771
|
-
};
|
|
1772
|
-
|
|
1773
|
-
const field = entry.value;
|
|
1774
|
-
const normalizedFieldId = normalizeFieldId(field, nodeAliases);
|
|
1775
|
-
const updatedNodeId =
|
|
1776
|
-
normalizedFieldId.nodeId !== undefined
|
|
1777
|
-
? replaceAtomRevisions(normalizedFieldId.nodeId, oldRevisions, newRevision)
|
|
1778
|
-
: undefined;
|
|
1779
|
-
|
|
1780
|
-
const updatedValue: FieldId = {
|
|
1781
|
-
...normalizedFieldId,
|
|
1782
|
-
nodeId: updatedNodeId,
|
|
1783
|
-
};
|
|
1784
|
-
|
|
1785
|
-
updated.set(updatedKey, entry.length, updatedValue);
|
|
1786
|
-
}
|
|
1787
|
-
|
|
1788
|
-
return updated;
|
|
2170
|
+
): CrossFieldKey {
|
|
2171
|
+
return {
|
|
2172
|
+
target: key.target,
|
|
2173
|
+
revision: replaceRevision(key.revision, oldRevisions, newRevision),
|
|
2174
|
+
localId: key.localId,
|
|
2175
|
+
};
|
|
1789
2176
|
}
|
|
1790
2177
|
|
|
1791
2178
|
function replaceRevision(
|
|
@@ -1879,6 +2266,20 @@ function composeBuildsDestroysAndRefreshers(
|
|
|
1879
2266
|
}
|
|
1880
2267
|
}
|
|
1881
2268
|
|
|
2269
|
+
// 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.
|
|
2270
|
+
if (change1.builds !== undefined && change2.refreshers !== undefined) {
|
|
2271
|
+
for (const [key, chunk] of change2.refreshers.entries()) {
|
|
2272
|
+
assert(chunk.topLevelLength === 1, "Expected refresher chunk to have length 1");
|
|
2273
|
+
const match = change1.builds.getPairOrNextLower(key);
|
|
2274
|
+
if (match !== undefined) {
|
|
2275
|
+
const [buildKey, buildChunk] = match;
|
|
2276
|
+
if (buildKey[0] === key[0] && buildKey[1] + buildChunk.topLevelLength > key[1]) {
|
|
2277
|
+
allRefreshers.delete(key);
|
|
2278
|
+
}
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
|
|
1882
2283
|
return { allBuilds, allDestroys, allRefreshers };
|
|
1883
2284
|
}
|
|
1884
2285
|
|
|
@@ -1910,27 +2311,69 @@ export function* relevantRemovedRoots(
|
|
|
1910
2311
|
change: ModularChangeset,
|
|
1911
2312
|
fieldKinds: ReadonlyMap<FieldKindIdentifier, FlexFieldKind>,
|
|
1912
2313
|
): Iterable<DeltaDetachedNodeId> {
|
|
1913
|
-
|
|
2314
|
+
const rootIds: ChangeAtomIdRangeMap<boolean> = newChangeAtomIdRangeMap();
|
|
2315
|
+
addAttachesToSet(change, rootIds);
|
|
2316
|
+
addRenamesToSet(change, rootIds);
|
|
2317
|
+
|
|
2318
|
+
for (const [[revision, localId]] of change.rootNodes.nodeChanges.entries()) {
|
|
2319
|
+
rootIds.set({ revision, localId }, 1, true);
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
for (const entry of rootIds.entries()) {
|
|
2323
|
+
for (let offset = 0; offset < entry.length; offset++) {
|
|
2324
|
+
const detachId = offsetChangeAtomId(entry.start, offset);
|
|
2325
|
+
yield makeDetachedNodeId(detachId.revision, detachId.localId);
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
1914
2328
|
}
|
|
1915
2329
|
|
|
1916
|
-
function
|
|
1917
|
-
change:
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
for (const
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
2330
|
+
function addAttachesToSet(
|
|
2331
|
+
change: ModularChangeset,
|
|
2332
|
+
rootIds: ChangeAtomIdRangeMap<boolean>,
|
|
2333
|
+
): void {
|
|
2334
|
+
// This includes each attach which does not have a corresponding detach.
|
|
2335
|
+
for (const entry of change.crossFieldKeys.entries()) {
|
|
2336
|
+
if (entry.start.target !== CrossFieldTarget.Destination) {
|
|
2337
|
+
continue;
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2340
|
+
for (const detachIdEntry of change.rootNodes.newToOldId.getAll2(
|
|
2341
|
+
entry.start,
|
|
2342
|
+
entry.length,
|
|
2343
|
+
)) {
|
|
2344
|
+
const detachId =
|
|
2345
|
+
detachIdEntry.value ?? offsetChangeAtomId(entry.start, detachIdEntry.offset);
|
|
2346
|
+
for (const detachEntry of change.crossFieldKeys.getAll2(
|
|
2347
|
+
{ ...detachId, target: CrossFieldTarget.Source },
|
|
2348
|
+
detachIdEntry.length,
|
|
2349
|
+
)) {
|
|
2350
|
+
if (detachEntry.value === undefined) {
|
|
2351
|
+
rootIds.set(
|
|
2352
|
+
offsetChangeAtomId(detachId, detachEntry.offset),
|
|
2353
|
+
detachEntry.length,
|
|
2354
|
+
true,
|
|
2355
|
+
);
|
|
2356
|
+
}
|
|
1931
2357
|
}
|
|
1932
|
-
}
|
|
1933
|
-
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
function addRenamesToSet(
|
|
2363
|
+
change: ModularChangeset,
|
|
2364
|
+
rootIds: ChangeAtomIdRangeMap<boolean>,
|
|
2365
|
+
): void {
|
|
2366
|
+
for (const renameEntry of change.rootNodes.oldToNewId.entries()) {
|
|
2367
|
+
for (const detachEntry of change.crossFieldKeys.getAll2(
|
|
2368
|
+
{ ...renameEntry.start, target: CrossFieldTarget.Source },
|
|
2369
|
+
renameEntry.length,
|
|
2370
|
+
)) {
|
|
2371
|
+
// We only want to include renames of nodes which are detached in the input context of the changeset.
|
|
2372
|
+
// So if there is a detach for the node, the rename is not relevant.
|
|
2373
|
+
if (detachEntry.value === undefined) {
|
|
2374
|
+
rootIds.set(renameEntry.start, renameEntry.length, true);
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
1934
2377
|
}
|
|
1935
2378
|
}
|
|
1936
2379
|
|
|
@@ -2003,6 +2446,7 @@ export function updateRefreshers(
|
|
|
2003
2446
|
nodeChanges,
|
|
2004
2447
|
nodeToParent: change.nodeToParent,
|
|
2005
2448
|
nodeAliases: change.nodeAliases,
|
|
2449
|
+
rootNodes: change.rootNodes,
|
|
2006
2450
|
crossFieldKeys: change.crossFieldKeys,
|
|
2007
2451
|
maxId: maxId as number,
|
|
2008
2452
|
revisions,
|
|
@@ -2026,18 +2470,42 @@ export function intoDelta(
|
|
|
2026
2470
|
): DeltaRoot {
|
|
2027
2471
|
const change = taggedChange.change;
|
|
2028
2472
|
const rootDelta: Mutable<DeltaRoot> = {};
|
|
2029
|
-
const global: DeltaDetachedNodeChanges[] = [];
|
|
2030
|
-
const rename: DeltaDetachedNodeRename[] = [];
|
|
2031
2473
|
|
|
2032
2474
|
if (!hasConflicts(change)) {
|
|
2033
2475
|
// If there are no constraint violations, then tree changes apply.
|
|
2034
2476
|
const fieldDeltas = intoDeltaImpl(
|
|
2035
2477
|
change.fieldChanges,
|
|
2036
2478
|
change.nodeChanges,
|
|
2479
|
+
change.nodeAliases,
|
|
2037
2480
|
fieldKinds,
|
|
2038
|
-
global,
|
|
2039
|
-
rename,
|
|
2040
2481
|
);
|
|
2482
|
+
|
|
2483
|
+
const global: DeltaDetachedNodeChanges[] = [];
|
|
2484
|
+
for (const [[major, minor], nodeId] of change.rootNodes.nodeChanges.entries()) {
|
|
2485
|
+
global.push({
|
|
2486
|
+
id: { major, minor },
|
|
2487
|
+
fields: deltaFromNodeChange(
|
|
2488
|
+
nodeChangeFromId(change.nodeChanges, change.nodeAliases, nodeId),
|
|
2489
|
+
change.nodeChanges,
|
|
2490
|
+
change.nodeAliases,
|
|
2491
|
+
fieldKinds,
|
|
2492
|
+
),
|
|
2493
|
+
});
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
const rename: DeltaDetachedNodeRename[] = [];
|
|
2497
|
+
for (const {
|
|
2498
|
+
start: oldId,
|
|
2499
|
+
value: newId,
|
|
2500
|
+
length,
|
|
2501
|
+
} of change.rootNodes.oldToNewId.entries()) {
|
|
2502
|
+
rename.push({
|
|
2503
|
+
count: length,
|
|
2504
|
+
oldId: makeDetachedNodeId(oldId.revision, oldId.localId),
|
|
2505
|
+
newId: makeDetachedNodeId(newId.revision, newId.localId),
|
|
2506
|
+
});
|
|
2507
|
+
}
|
|
2508
|
+
|
|
2041
2509
|
if (fieldDeltas.size > 0) {
|
|
2042
2510
|
rootDelta.fields = fieldDeltas;
|
|
2043
2511
|
}
|
|
@@ -2066,6 +2534,7 @@ export function intoDelta(
|
|
|
2066
2534
|
if (change.refreshers && change.refreshers.size > 0) {
|
|
2067
2535
|
rootDelta.refreshers = copyDetachedNodes(change.refreshers);
|
|
2068
2536
|
}
|
|
2537
|
+
|
|
2069
2538
|
return rootDelta;
|
|
2070
2539
|
}
|
|
2071
2540
|
|
|
@@ -2091,29 +2560,22 @@ function copyDetachedNodes(
|
|
|
2091
2560
|
function intoDeltaImpl(
|
|
2092
2561
|
change: FieldChangeMap,
|
|
2093
2562
|
nodeChanges: ChangeAtomIdBTree<NodeChangeset>,
|
|
2563
|
+
nodeAliases: ChangeAtomIdBTree<NodeId>,
|
|
2094
2564
|
fieldKinds: ReadonlyMap<FieldKindIdentifier, FlexFieldKind>,
|
|
2095
|
-
global: DeltaDetachedNodeChanges[],
|
|
2096
|
-
rename: DeltaDetachedNodeRename[],
|
|
2097
2565
|
): Map<FieldKey, DeltaFieldChanges> {
|
|
2098
2566
|
const delta: Map<FieldKey, DeltaFieldChanges> = new Map();
|
|
2099
2567
|
|
|
2100
2568
|
for (const [field, fieldChange] of change) {
|
|
2101
|
-
const
|
|
2102
|
-
local: fieldChanges,
|
|
2103
|
-
global: fieldGlobal,
|
|
2104
|
-
rename: fieldRename,
|
|
2105
|
-
} = getChangeHandler(fieldKinds, fieldChange.fieldKind).intoDelta(
|
|
2569
|
+
const fieldDelta = getChangeHandler(fieldKinds, fieldChange.fieldKind).intoDelta(
|
|
2106
2570
|
fieldChange.change,
|
|
2107
2571
|
(childChange): DeltaFieldMap => {
|
|
2108
|
-
const nodeChange = nodeChangeFromId(nodeChanges, childChange);
|
|
2109
|
-
return deltaFromNodeChange(nodeChange, nodeChanges,
|
|
2572
|
+
const nodeChange = nodeChangeFromId(nodeChanges, nodeAliases, childChange);
|
|
2573
|
+
return deltaFromNodeChange(nodeChange, nodeChanges, nodeAliases, fieldKinds);
|
|
2110
2574
|
},
|
|
2111
2575
|
);
|
|
2112
|
-
if (
|
|
2113
|
-
delta.set(field,
|
|
2576
|
+
if (fieldDelta !== undefined && fieldDelta.length > 0) {
|
|
2577
|
+
delta.set(field, fieldDelta);
|
|
2114
2578
|
}
|
|
2115
|
-
fieldGlobal?.forEach((c) => global.push(c));
|
|
2116
|
-
fieldRename?.forEach((r) => rename.push(r));
|
|
2117
2579
|
}
|
|
2118
2580
|
return delta;
|
|
2119
2581
|
}
|
|
@@ -2121,12 +2583,11 @@ function intoDeltaImpl(
|
|
|
2121
2583
|
function deltaFromNodeChange(
|
|
2122
2584
|
change: NodeChangeset,
|
|
2123
2585
|
nodeChanges: ChangeAtomIdBTree<NodeChangeset>,
|
|
2586
|
+
nodeAliases: ChangeAtomIdBTree<NodeId>,
|
|
2124
2587
|
fieldKinds: ReadonlyMap<FieldKindIdentifier, FlexFieldKind>,
|
|
2125
|
-
global: DeltaDetachedNodeChanges[],
|
|
2126
|
-
rename: DeltaDetachedNodeRename[],
|
|
2127
2588
|
): DeltaFieldMap {
|
|
2128
2589
|
if (change.fieldChanges !== undefined) {
|
|
2129
|
-
return intoDeltaImpl(change.fieldChanges, nodeChanges,
|
|
2590
|
+
return intoDeltaImpl(change.fieldChanges, nodeChanges, nodeAliases, fieldKinds);
|
|
2130
2591
|
}
|
|
2131
2592
|
// TODO: update the API to allow undefined to be returned here
|
|
2132
2593
|
return new Map();
|
|
@@ -2191,19 +2652,21 @@ export function getChangeHandler(
|
|
|
2191
2652
|
return getFieldKind(fieldKinds, kind).changeHandler;
|
|
2192
2653
|
}
|
|
2193
2654
|
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
interface CrossFieldTable<TFieldData> {
|
|
2197
|
-
srcTable: CrossFieldMap<unknown>;
|
|
2198
|
-
dstTable: CrossFieldMap<unknown>;
|
|
2199
|
-
srcDependents: CrossFieldMap<TFieldData>;
|
|
2200
|
-
dstDependents: CrossFieldMap<TFieldData>;
|
|
2201
|
-
invalidatedFields: Set<TFieldData>;
|
|
2202
|
-
}
|
|
2655
|
+
interface InvertTable {
|
|
2656
|
+
change: ModularChangeset;
|
|
2203
2657
|
|
|
2204
|
-
|
|
2658
|
+
// Entries are keyed on attach ID
|
|
2659
|
+
entries: CrossFieldMap<NodeId>;
|
|
2205
2660
|
originalFieldToContext: Map<FieldChange, InvertContext>;
|
|
2206
|
-
invertedNodeToParent: ChangeAtomIdBTree<
|
|
2661
|
+
invertedNodeToParent: ChangeAtomIdBTree<NodeLocation>;
|
|
2662
|
+
invertRevision: RevisionTag;
|
|
2663
|
+
invalidatedFields: Set<FieldChange>;
|
|
2664
|
+
invertedRoots: RootNodeTable;
|
|
2665
|
+
|
|
2666
|
+
/**
|
|
2667
|
+
* Maps from attach ID in the inverted changeset to the corresponding detach ID in the base changeset.
|
|
2668
|
+
*/
|
|
2669
|
+
attachToDetachId: ChangeAtomIdRangeMap<ChangeAtomId>;
|
|
2207
2670
|
}
|
|
2208
2671
|
|
|
2209
2672
|
interface InvertContext {
|
|
@@ -2211,7 +2674,11 @@ interface InvertContext {
|
|
|
2211
2674
|
invertedField: FieldChange;
|
|
2212
2675
|
}
|
|
2213
2676
|
|
|
2214
|
-
interface RebaseTable
|
|
2677
|
+
interface RebaseTable {
|
|
2678
|
+
readonly rebaseVersion: RebaseVersion;
|
|
2679
|
+
|
|
2680
|
+
// Entries are keyed on attach ID
|
|
2681
|
+
readonly entries: CrossFieldMap<RebaseDetachedNodeEntry>;
|
|
2215
2682
|
readonly baseChange: ModularChangeset;
|
|
2216
2683
|
readonly newChange: ModularChangeset;
|
|
2217
2684
|
|
|
@@ -2220,10 +2687,13 @@ interface RebaseTable extends CrossFieldTable<FieldChange> {
|
|
|
2220
2687
|
* to the context for the field.
|
|
2221
2688
|
*/
|
|
2222
2689
|
readonly baseFieldToContext: Map<FieldChange, RebaseFieldContext>;
|
|
2690
|
+
readonly baseRoots: RootNodeTable;
|
|
2223
2691
|
readonly baseToRebasedNodeId: ChangeAtomIdBTree<NodeId>;
|
|
2224
2692
|
readonly rebasedFields: Set<FieldChange>;
|
|
2225
|
-
readonly rebasedNodeToParent: ChangeAtomIdBTree<
|
|
2226
|
-
readonly
|
|
2693
|
+
readonly rebasedNodeToParent: ChangeAtomIdBTree<NodeLocation>;
|
|
2694
|
+
readonly rebasedDetachLocations: ChangeAtomIdRangeMap<FieldId>;
|
|
2695
|
+
readonly movedDetaches: ChangeAtomIdRangeMap<boolean>;
|
|
2696
|
+
readonly rebasedRootNodes: RootNodeTable;
|
|
2227
2697
|
|
|
2228
2698
|
/**
|
|
2229
2699
|
* List of unprocessed (newId, baseId) pairs encountered so far.
|
|
@@ -2237,7 +2707,7 @@ interface RebaseTable extends CrossFieldTable<FieldChange> {
|
|
|
2237
2707
|
readonly fieldsWithUnattachedChild: Set<FieldChange>;
|
|
2238
2708
|
}
|
|
2239
2709
|
|
|
2240
|
-
type FieldIdKey = [RevisionTag | undefined, ChangesetLocalId | undefined, FieldKey];
|
|
2710
|
+
export type FieldIdKey = [RevisionTag | undefined, ChangesetLocalId | undefined, FieldKey];
|
|
2241
2711
|
|
|
2242
2712
|
interface RebaseFieldContext {
|
|
2243
2713
|
baseChange: FieldChange;
|
|
@@ -2249,32 +2719,43 @@ interface RebaseFieldContext {
|
|
|
2249
2719
|
* The set of node IDs in the base changeset which should be included in the rebased field,
|
|
2250
2720
|
* even if there is no corresponding node changeset in the new change.
|
|
2251
2721
|
*/
|
|
2252
|
-
baseNodeIds:
|
|
2722
|
+
baseNodeIds: ChangeAtomIdBTree<boolean>;
|
|
2253
2723
|
}
|
|
2254
2724
|
|
|
2255
2725
|
function newComposeTable(
|
|
2256
2726
|
baseChange: ModularChangeset,
|
|
2257
2727
|
newChange: ModularChangeset,
|
|
2258
|
-
|
|
2728
|
+
composedRootNodes: RootNodeTable,
|
|
2729
|
+
movedCrossFieldKeys: CrossFieldKeyTable,
|
|
2730
|
+
removedCrossFieldKeys: CrossFieldRangeTable<boolean>,
|
|
2731
|
+
pendingCompositions: PendingCompositions,
|
|
2259
2732
|
): ComposeTable {
|
|
2260
2733
|
return {
|
|
2261
|
-
|
|
2734
|
+
rebaseVersion: Math.max(
|
|
2735
|
+
baseChange.rebaseVersion,
|
|
2736
|
+
newChange.rebaseVersion,
|
|
2737
|
+
) as RebaseVersion,
|
|
2738
|
+
entries: newDetachedEntryMap(),
|
|
2262
2739
|
baseChange,
|
|
2263
2740
|
newChange,
|
|
2264
2741
|
fieldToContext: new Map(),
|
|
2265
2742
|
newFieldToBaseField: new Map(),
|
|
2266
2743
|
newToBaseNodeId: newTupleBTree(),
|
|
2267
2744
|
composedNodes: new Set(),
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2745
|
+
movedNodeToParent: newTupleBTree(),
|
|
2746
|
+
composedRootNodes,
|
|
2747
|
+
movedCrossFieldKeys,
|
|
2748
|
+
removedCrossFieldKeys,
|
|
2749
|
+
renamesToDelete: newChangeAtomIdRangeMap(),
|
|
2750
|
+
pendingCompositions,
|
|
2274
2751
|
};
|
|
2275
2752
|
}
|
|
2276
2753
|
|
|
2277
|
-
interface ComposeTable
|
|
2754
|
+
interface ComposeTable {
|
|
2755
|
+
readonly rebaseVersion: RebaseVersion;
|
|
2756
|
+
|
|
2757
|
+
// Entries are keyed on detach ID
|
|
2758
|
+
readonly entries: ChangeAtomIdRangeMap<DetachedNodeEntry>;
|
|
2278
2759
|
readonly baseChange: ModularChangeset;
|
|
2279
2760
|
readonly newChange: ModularChangeset;
|
|
2280
2761
|
|
|
@@ -2285,7 +2766,11 @@ interface ComposeTable extends CrossFieldTable<FieldChange> {
|
|
|
2285
2766
|
readonly newFieldToBaseField: Map<FieldChange, FieldChange>;
|
|
2286
2767
|
readonly newToBaseNodeId: ChangeAtomIdBTree<NodeId>;
|
|
2287
2768
|
readonly composedNodes: Set<NodeChangeset>;
|
|
2288
|
-
readonly
|
|
2769
|
+
readonly movedNodeToParent: ChangeAtomIdBTree<NodeLocation>;
|
|
2770
|
+
readonly composedRootNodes: RootNodeTable;
|
|
2771
|
+
readonly movedCrossFieldKeys: CrossFieldKeyTable;
|
|
2772
|
+
readonly removedCrossFieldKeys: CrossFieldRangeTable<boolean>;
|
|
2773
|
+
readonly renamesToDelete: ChangeAtomIdRangeMap<boolean>;
|
|
2289
2774
|
readonly pendingCompositions: PendingCompositions;
|
|
2290
2775
|
}
|
|
2291
2776
|
|
|
@@ -2300,11 +2785,6 @@ interface PendingCompositions {
|
|
|
2300
2785
|
* The set of fields in the base changeset which have been affected by a cross field effect.
|
|
2301
2786
|
*/
|
|
2302
2787
|
readonly affectedBaseFields: BTree<FieldIdKey, true>;
|
|
2303
|
-
|
|
2304
|
-
/**
|
|
2305
|
-
* The set of fields in the new changeset which have been affected by a cross field effect.
|
|
2306
|
-
*/
|
|
2307
|
-
readonly affectedNewFields: BTree<FieldIdKey, true>;
|
|
2308
2788
|
}
|
|
2309
2789
|
|
|
2310
2790
|
interface ComposeFieldContext {
|
|
@@ -2317,16 +2797,6 @@ interface ComposeFieldContext {
|
|
|
2317
2797
|
composedChange: FieldChange;
|
|
2318
2798
|
}
|
|
2319
2799
|
|
|
2320
|
-
function newCrossFieldTable<T>(): CrossFieldTable<T> {
|
|
2321
|
-
return {
|
|
2322
|
-
srcTable: newChangeAtomIdRangeMap(),
|
|
2323
|
-
dstTable: newChangeAtomIdRangeMap(),
|
|
2324
|
-
srcDependents: newChangeAtomIdRangeMap(),
|
|
2325
|
-
dstDependents: newChangeAtomIdRangeMap(),
|
|
2326
|
-
invalidatedFields: new Set(),
|
|
2327
|
-
};
|
|
2328
|
-
}
|
|
2329
|
-
|
|
2330
2800
|
interface ConstraintState {
|
|
2331
2801
|
violationCount: number;
|
|
2332
2802
|
}
|
|
@@ -2337,283 +2807,697 @@ function newConstraintState(violationCount: number): ConstraintState {
|
|
|
2337
2807
|
};
|
|
2338
2808
|
}
|
|
2339
2809
|
|
|
2340
|
-
|
|
2810
|
+
class InvertNodeManagerI implements InvertNodeManager {
|
|
2341
2811
|
public constructor(
|
|
2342
|
-
|
|
2343
|
-
private readonly
|
|
2344
|
-
protected readonly allowInval = true,
|
|
2812
|
+
private readonly table: InvertTable,
|
|
2813
|
+
private readonly fieldId: FieldId,
|
|
2345
2814
|
) {}
|
|
2346
2815
|
|
|
2347
|
-
public
|
|
2348
|
-
|
|
2349
|
-
revision: RevisionTag | undefined,
|
|
2350
|
-
id: ChangesetLocalId,
|
|
2816
|
+
public invertDetach(
|
|
2817
|
+
detachId: ChangeAtomId,
|
|
2351
2818
|
count: number,
|
|
2352
|
-
|
|
2353
|
-
|
|
2819
|
+
nodeChange: NodeId | undefined,
|
|
2820
|
+
newAttachId: ChangeAtomId,
|
|
2354
2821
|
): void {
|
|
2355
|
-
if (
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2822
|
+
if (nodeChange !== undefined) {
|
|
2823
|
+
assert(count === 1, "A node change should only affect one node");
|
|
2824
|
+
|
|
2825
|
+
const attachEntry = firstAttachIdFromDetachId(
|
|
2826
|
+
this.table.change.rootNodes,
|
|
2827
|
+
detachId,
|
|
2828
|
+
count,
|
|
2829
|
+
);
|
|
2830
|
+
|
|
2831
|
+
const attachFieldEntry = this.table.change.crossFieldKeys.getFirst(
|
|
2832
|
+
{ target: CrossFieldTarget.Destination, ...attachEntry.value },
|
|
2833
|
+
count,
|
|
2834
|
+
);
|
|
2368
2835
|
|
|
2369
|
-
|
|
2836
|
+
if (attachFieldEntry.value !== undefined) {
|
|
2837
|
+
setInCrossFieldMap(this.table.entries, attachEntry.value, count, nodeChange);
|
|
2838
|
+
this.table.invalidatedFields.add(
|
|
2839
|
+
fieldChangeFromId(this.table.change, attachFieldEntry.value),
|
|
2840
|
+
);
|
|
2841
|
+
} else {
|
|
2842
|
+
assignRootChange(
|
|
2843
|
+
this.table.invertedRoots,
|
|
2844
|
+
this.table.invertedNodeToParent,
|
|
2845
|
+
attachEntry.value,
|
|
2846
|
+
nodeChange,
|
|
2847
|
+
this.fieldId,
|
|
2848
|
+
this.table.change.rebaseVersion,
|
|
2849
|
+
);
|
|
2370
2850
|
}
|
|
2371
2851
|
}
|
|
2372
|
-
setInCrossFieldMap(this.getMap(target), revision, id, count, newValue);
|
|
2373
|
-
}
|
|
2374
2852
|
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
count: number,
|
|
2380
|
-
addDependency: boolean,
|
|
2381
|
-
): RangeQueryResult<ChangeAtomId, unknown> {
|
|
2382
|
-
if (addDependency) {
|
|
2383
|
-
// We assume that if there is already an entry for this ID it is because
|
|
2384
|
-
// a field handler has called compose on the same node multiple times.
|
|
2385
|
-
// In this case we only want to update the latest version, so we overwrite the dependency.
|
|
2386
|
-
setInCrossFieldMap(
|
|
2387
|
-
this.getDependents(target),
|
|
2388
|
-
revision,
|
|
2389
|
-
id,
|
|
2853
|
+
if (!areEqualChangeAtomIds(detachId, newAttachId)) {
|
|
2854
|
+
for (const entry of doesChangeAttachNodes(
|
|
2855
|
+
this.table.change.crossFieldKeys,
|
|
2856
|
+
detachId,
|
|
2390
2857
|
count,
|
|
2391
|
-
|
|
2392
|
-
|
|
2858
|
+
)) {
|
|
2859
|
+
if (!entry.value) {
|
|
2860
|
+
this.table.attachToDetachId.set(newAttachId, count, detachId);
|
|
2861
|
+
this.table.invertedRoots.detachLocations.set(detachId, count, this.fieldId);
|
|
2862
|
+
}
|
|
2863
|
+
}
|
|
2393
2864
|
}
|
|
2394
|
-
return getFirstFromCrossFieldMap(this.getMap(target), revision, id, count);
|
|
2395
2865
|
}
|
|
2396
2866
|
|
|
2397
|
-
public
|
|
2398
|
-
|
|
2399
|
-
public abstract moveKey(
|
|
2400
|
-
target: CrossFieldTarget,
|
|
2401
|
-
revision: RevisionTag | undefined,
|
|
2402
|
-
id: ChangesetLocalId,
|
|
2867
|
+
public invertAttach(
|
|
2868
|
+
attachId: ChangeAtomId,
|
|
2403
2869
|
count: number,
|
|
2404
|
-
):
|
|
2870
|
+
): RangeQueryResult<DetachedNodeEntry> {
|
|
2871
|
+
let countToProcess = count;
|
|
2405
2872
|
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2873
|
+
const detachIdEntry = firstDetachIdFromAttachId(
|
|
2874
|
+
this.table.change.rootNodes,
|
|
2875
|
+
attachId,
|
|
2876
|
+
countToProcess,
|
|
2877
|
+
);
|
|
2411
2878
|
|
|
2412
|
-
|
|
2413
|
-
return target === CrossFieldTarget.Source
|
|
2414
|
-
? this.crossFieldTable.srcDependents
|
|
2415
|
-
: this.crossFieldTable.dstDependents;
|
|
2416
|
-
}
|
|
2417
|
-
}
|
|
2879
|
+
countToProcess = detachIdEntry.length;
|
|
2418
2880
|
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
) {
|
|
2426
|
-
super(table, field, allowInval);
|
|
2427
|
-
}
|
|
2881
|
+
const detachEntry = getFirstFieldForCrossFieldKey(
|
|
2882
|
+
this.table.change,
|
|
2883
|
+
{ target: CrossFieldTarget.Source, ...detachIdEntry.value },
|
|
2884
|
+
countToProcess,
|
|
2885
|
+
);
|
|
2886
|
+
countToProcess = detachEntry.length;
|
|
2428
2887
|
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2888
|
+
let result: RangeQueryResult<DetachedNodeEntry>;
|
|
2889
|
+
if (detachEntry.value !== undefined) {
|
|
2890
|
+
const moveEntry = this.table.entries.getFirst(attachId, countToProcess);
|
|
2891
|
+
result = { ...moveEntry, value: { nodeChange: moveEntry.value } };
|
|
2892
|
+
} else {
|
|
2893
|
+
// This node is detached in the input context of the original change.
|
|
2894
|
+
const nodeIdEntry = rangeQueryChangeAtomIdMap(
|
|
2895
|
+
this.table.change.rootNodes.nodeChanges,
|
|
2896
|
+
detachIdEntry.value,
|
|
2897
|
+
countToProcess,
|
|
2898
|
+
);
|
|
2432
2899
|
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
assert(false, 0x9c5 /* Keys should not be moved manually during invert */);
|
|
2440
|
-
}
|
|
2900
|
+
countToProcess = nodeIdEntry.length;
|
|
2901
|
+
result = {
|
|
2902
|
+
value: { nodeChange: nodeIdEntry.value, detachId: detachIdEntry.value },
|
|
2903
|
+
length: countToProcess,
|
|
2904
|
+
};
|
|
2905
|
+
}
|
|
2441
2906
|
|
|
2442
|
-
|
|
2443
|
-
|
|
2907
|
+
if (result.value?.nodeChange !== undefined) {
|
|
2908
|
+
setInChangeAtomIdMap(this.table.invertedNodeToParent, result.value.nodeChange, {
|
|
2909
|
+
field: this.fieldId,
|
|
2910
|
+
});
|
|
2911
|
+
}
|
|
2912
|
+
return result;
|
|
2444
2913
|
}
|
|
2445
2914
|
}
|
|
2446
2915
|
|
|
2447
|
-
class
|
|
2916
|
+
class RebaseNodeManagerI implements RebaseNodeManager {
|
|
2448
2917
|
public constructor(
|
|
2449
|
-
table: RebaseTable,
|
|
2450
|
-
currentField: FieldChange,
|
|
2918
|
+
private readonly table: RebaseTable,
|
|
2451
2919
|
private readonly fieldId: FieldId,
|
|
2452
|
-
allowInval = true,
|
|
2453
|
-
) {
|
|
2454
|
-
super(table, currentField, allowInval);
|
|
2455
|
-
}
|
|
2920
|
+
private readonly allowInval: boolean = true,
|
|
2921
|
+
) {}
|
|
2456
2922
|
|
|
2457
|
-
public
|
|
2458
|
-
|
|
2459
|
-
revision: RevisionTag | undefined,
|
|
2460
|
-
id: ChangesetLocalId,
|
|
2923
|
+
public getNewChangesForBaseAttach(
|
|
2924
|
+
baseAttachId: ChangeAtomId,
|
|
2461
2925
|
count: number,
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
): void {
|
|
2465
|
-
if (invalidateDependents && this.allowInval) {
|
|
2466
|
-
const newFieldIds = getFieldsForCrossFieldKey(
|
|
2467
|
-
this.table.newChange,
|
|
2468
|
-
{
|
|
2469
|
-
target,
|
|
2470
|
-
revision,
|
|
2471
|
-
localId: id,
|
|
2472
|
-
},
|
|
2473
|
-
count,
|
|
2474
|
-
);
|
|
2926
|
+
): RangeQueryResult<RebaseDetachedNodeEntry | undefined> {
|
|
2927
|
+
let countToProcess = count;
|
|
2475
2928
|
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2929
|
+
const detachEntry = firstDetachIdFromAttachId(
|
|
2930
|
+
this.table.baseChange.rootNodes,
|
|
2931
|
+
baseAttachId,
|
|
2932
|
+
countToProcess,
|
|
2933
|
+
);
|
|
2480
2934
|
|
|
2481
|
-
|
|
2482
|
-
this.table.baseChange,
|
|
2483
|
-
{
|
|
2484
|
-
target,
|
|
2485
|
-
revision,
|
|
2486
|
-
localId: id,
|
|
2487
|
-
},
|
|
2488
|
-
count,
|
|
2489
|
-
);
|
|
2935
|
+
countToProcess = detachEntry.length;
|
|
2490
2936
|
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2937
|
+
const nodeEntry = rangeQueryChangeAtomIdMap(
|
|
2938
|
+
this.table.newChange.rootNodes.nodeChanges,
|
|
2939
|
+
detachEntry.value,
|
|
2940
|
+
countToProcess,
|
|
2941
|
+
);
|
|
2495
2942
|
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
[baseFieldId.nodeId?.revision, baseFieldId.nodeId?.localId, baseFieldId.field],
|
|
2499
|
-
true,
|
|
2500
|
-
);
|
|
2501
|
-
}
|
|
2502
|
-
}
|
|
2943
|
+
countToProcess = nodeEntry.length;
|
|
2944
|
+
const newNodeId = nodeEntry.value;
|
|
2503
2945
|
|
|
2504
|
-
|
|
2505
|
-
|
|
2946
|
+
const newRenameEntry = this.table.newChange.rootNodes.oldToNewId.getFirst(
|
|
2947
|
+
detachEntry.value,
|
|
2948
|
+
countToProcess,
|
|
2949
|
+
);
|
|
2950
|
+
|
|
2951
|
+
countToProcess = newRenameEntry.length;
|
|
2952
|
+
|
|
2953
|
+
let result: RangeQueryResult<DetachedNodeEntry | undefined>;
|
|
2954
|
+
// eslint-disable-next-line unicorn/prefer-ternary
|
|
2955
|
+
if (newNodeId !== undefined || newRenameEntry.value !== undefined) {
|
|
2956
|
+
result = {
|
|
2957
|
+
...newRenameEntry,
|
|
2958
|
+
value: { detachId: newRenameEntry.value, nodeChange: newNodeId },
|
|
2959
|
+
};
|
|
2960
|
+
} else {
|
|
2961
|
+
// This handles the case where the base changeset has moved these nodes,
|
|
2962
|
+
// meaning they were attached in the input context of the base changeset.
|
|
2963
|
+
result = this.table.entries.getFirst(baseAttachId, countToProcess);
|
|
2964
|
+
}
|
|
2965
|
+
|
|
2966
|
+
// TODO: Consider moving these two checks into a separate method so that this function has no side effects.
|
|
2967
|
+
if (result.value?.detachId !== undefined) {
|
|
2968
|
+
this.table.rebasedDetachLocations.set(
|
|
2969
|
+
result.value.detachId,
|
|
2970
|
+
result.length,
|
|
2971
|
+
this.fieldId,
|
|
2972
|
+
);
|
|
2973
|
+
}
|
|
2974
|
+
|
|
2975
|
+
if (result.value?.nodeChange !== undefined) {
|
|
2976
|
+
setInChangeAtomIdMap(this.table.rebasedNodeToParent, result.value.nodeChange, {
|
|
2977
|
+
field: this.fieldId,
|
|
2978
|
+
});
|
|
2979
|
+
}
|
|
2506
2980
|
|
|
2507
|
-
|
|
2508
|
-
setInChangeAtomIdMap(this.table.rebasedNodeToParent, id, this.fieldId);
|
|
2981
|
+
return result;
|
|
2509
2982
|
}
|
|
2510
2983
|
|
|
2511
|
-
public
|
|
2512
|
-
|
|
2513
|
-
revision: RevisionTag | undefined,
|
|
2514
|
-
id: ChangesetLocalId,
|
|
2984
|
+
public rebaseOverDetach(
|
|
2985
|
+
baseDetachId: ChangeAtomId,
|
|
2515
2986
|
count: number,
|
|
2987
|
+
newDetachId: ChangeAtomId | undefined,
|
|
2988
|
+
nodeChange: NodeId | undefined,
|
|
2989
|
+
cellRename?: ChangeAtomId,
|
|
2516
2990
|
): void {
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2991
|
+
let countToProcess = count;
|
|
2992
|
+
const attachIdEntry = firstAttachIdFromDetachId(
|
|
2993
|
+
this.table.baseRoots,
|
|
2994
|
+
baseDetachId,
|
|
2995
|
+
countToProcess,
|
|
2996
|
+
);
|
|
2997
|
+
const baseAttachId = attachIdEntry.value;
|
|
2998
|
+
countToProcess = attachIdEntry.length;
|
|
2999
|
+
|
|
3000
|
+
const attachFieldEntry = getFirstFieldForCrossFieldKey(
|
|
3001
|
+
this.table.baseChange,
|
|
3002
|
+
{ ...baseAttachId, target: CrossFieldTarget.Destination },
|
|
3003
|
+
countToProcess,
|
|
3004
|
+
);
|
|
3005
|
+
countToProcess = attachFieldEntry.length;
|
|
3006
|
+
|
|
3007
|
+
const detachedMoveEntry = this.table.baseChange.rootNodes.outputDetachLocations.getFirst(
|
|
3008
|
+
baseDetachId,
|
|
3009
|
+
countToProcess,
|
|
3010
|
+
);
|
|
3011
|
+
countToProcess = detachedMoveEntry.length;
|
|
3012
|
+
|
|
3013
|
+
const destinationField = attachFieldEntry.value ?? detachedMoveEntry.value;
|
|
3014
|
+
if (destinationField !== undefined) {
|
|
3015
|
+
// The base detach is part of a move (or move of detach location) in the base changeset.
|
|
3016
|
+
setInCrossFieldMap(this.table.entries, baseAttachId, countToProcess, {
|
|
3017
|
+
nodeChange,
|
|
3018
|
+
detachId: newDetachId,
|
|
3019
|
+
cellRename,
|
|
3020
|
+
});
|
|
3021
|
+
|
|
3022
|
+
if (nodeChange !== undefined || newDetachId !== undefined) {
|
|
3023
|
+
this.invalidateBaseFields([destinationField]);
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
3026
|
+
|
|
3027
|
+
if (attachFieldEntry.value === undefined) {
|
|
3028
|
+
// These nodes are detached in the output context of the base changeset.
|
|
3029
|
+
if (nodeChange !== undefined) {
|
|
3030
|
+
assignRootChange(
|
|
3031
|
+
this.table.rebasedRootNodes,
|
|
3032
|
+
this.table.rebasedNodeToParent,
|
|
3033
|
+
baseAttachId,
|
|
3034
|
+
nodeChange,
|
|
3035
|
+
this.fieldId,
|
|
3036
|
+
this.table.rebaseVersion,
|
|
3037
|
+
);
|
|
3038
|
+
}
|
|
3039
|
+
|
|
3040
|
+
if (newDetachId !== undefined) {
|
|
3041
|
+
addNodeRename(
|
|
3042
|
+
this.table.rebasedRootNodes,
|
|
3043
|
+
baseAttachId,
|
|
3044
|
+
newDetachId,
|
|
3045
|
+
countToProcess,
|
|
3046
|
+
this.fieldId,
|
|
3047
|
+
);
|
|
3048
|
+
}
|
|
3049
|
+
}
|
|
3050
|
+
|
|
3051
|
+
if (newDetachId !== undefined) {
|
|
3052
|
+
this.table.movedDetaches.set(newDetachId, countToProcess, true);
|
|
3053
|
+
}
|
|
3054
|
+
|
|
3055
|
+
if (countToProcess < count) {
|
|
3056
|
+
const remainingCount = count - countToProcess;
|
|
3057
|
+
|
|
3058
|
+
const nextDetachId =
|
|
3059
|
+
newDetachId !== undefined
|
|
3060
|
+
? offsetChangeAtomId(newDetachId, countToProcess)
|
|
3061
|
+
: undefined;
|
|
3062
|
+
|
|
3063
|
+
this.rebaseOverDetach(
|
|
3064
|
+
offsetChangeAtomId(baseDetachId, countToProcess),
|
|
3065
|
+
remainingCount,
|
|
3066
|
+
nextDetachId,
|
|
3067
|
+
nodeChange,
|
|
3068
|
+
);
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
|
+
|
|
3072
|
+
public addDetach(id: ChangeAtomId, count: number): void {
|
|
3073
|
+
this.table.rebasedDetachLocations.set(id, count, this.fieldId);
|
|
3074
|
+
}
|
|
3075
|
+
|
|
3076
|
+
public removeDetach(id: ChangeAtomId, count: number): void {
|
|
3077
|
+
this.table.movedDetaches.set(id, count, true);
|
|
3078
|
+
}
|
|
3079
|
+
|
|
3080
|
+
public doesBaseAttachNodes(
|
|
3081
|
+
id: ChangeAtomId,
|
|
3082
|
+
count: number,
|
|
3083
|
+
): RangeQueryEntry<ChangeAtomId, boolean> {
|
|
3084
|
+
let countToProcess = count;
|
|
3085
|
+
const attachEntry = getFirstAttachField(
|
|
3086
|
+
this.table.baseChange.crossFieldKeys,
|
|
3087
|
+
id,
|
|
3088
|
+
countToProcess,
|
|
3089
|
+
);
|
|
3090
|
+
|
|
3091
|
+
countToProcess = attachEntry.length;
|
|
3092
|
+
return { start: id, value: attachEntry.value !== undefined, length: countToProcess };
|
|
3093
|
+
}
|
|
3094
|
+
|
|
3095
|
+
public getBaseRename(
|
|
3096
|
+
id: ChangeAtomId,
|
|
3097
|
+
count: number,
|
|
3098
|
+
): RangeQueryResult<ChangeAtomId | undefined> {
|
|
3099
|
+
return this.table.baseChange.rootNodes.oldToNewId.getFirst(id, count);
|
|
3100
|
+
}
|
|
3101
|
+
|
|
3102
|
+
public getNewRenameForBaseRename(
|
|
3103
|
+
baseRenameTo: ChangeAtomId,
|
|
3104
|
+
count: number,
|
|
3105
|
+
): RangeQueryResult<ChangeAtomId | undefined> {
|
|
3106
|
+
let countToProcess = count;
|
|
3107
|
+
const inputEntry = firstDetachIdFromAttachId(
|
|
3108
|
+
this.table.baseChange.rootNodes,
|
|
3109
|
+
baseRenameTo,
|
|
3110
|
+
countToProcess,
|
|
3111
|
+
);
|
|
3112
|
+
|
|
3113
|
+
const attachEntry = getFirstAttachField(
|
|
3114
|
+
this.table.baseChange.crossFieldKeys,
|
|
3115
|
+
baseRenameTo,
|
|
3116
|
+
countToProcess,
|
|
2521
3117
|
);
|
|
3118
|
+
|
|
3119
|
+
countToProcess = attachEntry.length;
|
|
3120
|
+
if (attachEntry.value !== undefined) {
|
|
3121
|
+
// These nodes are attached in the output context of the base changeset.
|
|
3122
|
+
return { value: undefined, length: countToProcess };
|
|
3123
|
+
}
|
|
3124
|
+
|
|
3125
|
+
countToProcess = inputEntry.length;
|
|
3126
|
+
const inputId = inputEntry.value;
|
|
3127
|
+
|
|
3128
|
+
const moveEntry = this.table.entries.getFirst(inputId, countToProcess);
|
|
3129
|
+
|
|
3130
|
+
countToProcess = moveEntry.length;
|
|
3131
|
+
if (moveEntry.value !== undefined) {
|
|
3132
|
+
return { ...moveEntry, value: moveEntry.value.cellRename ?? moveEntry.value.detachId };
|
|
3133
|
+
}
|
|
3134
|
+
|
|
3135
|
+
return this.table.newChange.rootNodes.oldToNewId.getFirst(inputId, countToProcess);
|
|
3136
|
+
}
|
|
3137
|
+
|
|
3138
|
+
private invalidateBaseFields(fields: FieldId[]): void {
|
|
3139
|
+
if (this.allowInval) {
|
|
3140
|
+
for (const fieldId of fields) {
|
|
3141
|
+
this.table.affectedBaseFields.set(fieldIdKeyFromFieldId(fieldId), true);
|
|
3142
|
+
}
|
|
3143
|
+
}
|
|
2522
3144
|
}
|
|
3145
|
+
}
|
|
2523
3146
|
|
|
2524
|
-
|
|
2525
|
-
|
|
3147
|
+
function assignRootChange(
|
|
3148
|
+
table: RootNodeTable,
|
|
3149
|
+
nodeToParent: ChangeAtomIdBTree<NodeLocation> | undefined,
|
|
3150
|
+
detachId: ChangeAtomId,
|
|
3151
|
+
nodeId: NodeId,
|
|
3152
|
+
detachLocation: FieldId | undefined,
|
|
3153
|
+
rebaseVersion: RebaseVersion,
|
|
3154
|
+
): void {
|
|
3155
|
+
assert(
|
|
3156
|
+
rebaseVersion >= 2 || detachLocation !== undefined,
|
|
3157
|
+
"All root changes need a detach location to support compatibility with older client versions",
|
|
3158
|
+
);
|
|
3159
|
+
|
|
3160
|
+
setInChangeAtomIdMap(table.nodeChanges, detachId, nodeId);
|
|
3161
|
+
|
|
3162
|
+
if (nodeToParent !== undefined) {
|
|
3163
|
+
setInChangeAtomIdMap(nodeToParent, nodeId, { root: detachId });
|
|
2526
3164
|
}
|
|
3165
|
+
|
|
3166
|
+
table.detachLocations.set(detachId, 1, detachLocation);
|
|
2527
3167
|
}
|
|
2528
3168
|
|
|
2529
|
-
|
|
2530
|
-
class ComposeManager extends CrossFieldManagerI<FieldChange> {
|
|
3169
|
+
class ComposeNodeManagerI implements ComposeNodeManager {
|
|
2531
3170
|
public constructor(
|
|
2532
|
-
table: ComposeTable,
|
|
2533
|
-
currentField: FieldChange,
|
|
3171
|
+
private readonly table: ComposeTable,
|
|
2534
3172
|
private readonly fieldId: FieldId,
|
|
2535
|
-
allowInval = true,
|
|
2536
|
-
) {
|
|
2537
|
-
|
|
3173
|
+
private readonly allowInval: boolean = true,
|
|
3174
|
+
) {}
|
|
3175
|
+
|
|
3176
|
+
public getNewChangesForBaseDetach(
|
|
3177
|
+
baseDetachId: ChangeAtomId,
|
|
3178
|
+
count: number,
|
|
3179
|
+
): RangeQueryResult<DetachedNodeEntry | undefined> {
|
|
3180
|
+
let countToProcess = count;
|
|
3181
|
+
|
|
3182
|
+
const baseAttachEntry = getFirstFieldForCrossFieldKey(
|
|
3183
|
+
this.table.baseChange,
|
|
3184
|
+
{ target: CrossFieldTarget.Destination, ...baseDetachId },
|
|
3185
|
+
countToProcess,
|
|
3186
|
+
);
|
|
3187
|
+
|
|
3188
|
+
countToProcess = baseAttachEntry.length;
|
|
3189
|
+
|
|
3190
|
+
let result: RangeQueryResult<DetachedNodeEntry | undefined>;
|
|
3191
|
+
if (baseAttachEntry.value !== undefined) {
|
|
3192
|
+
// The base detach was part of a move.
|
|
3193
|
+
// We check if we've previously seen a node change at the move destination.
|
|
3194
|
+
const entry = this.table.entries.getFirst(baseDetachId, countToProcess);
|
|
3195
|
+
result = { value: entry.value, length: entry.length };
|
|
3196
|
+
} else {
|
|
3197
|
+
// The detached nodes are still detached in the new change's input context.
|
|
3198
|
+
const rootEntry = rangeQueryChangeAtomIdMap(
|
|
3199
|
+
this.table.newChange.rootNodes.nodeChanges,
|
|
3200
|
+
baseDetachId,
|
|
3201
|
+
countToProcess,
|
|
3202
|
+
);
|
|
3203
|
+
|
|
3204
|
+
countToProcess = rootEntry.length;
|
|
3205
|
+
|
|
3206
|
+
const newRenameEntry = this.table.newChange.rootNodes.oldToNewId.getFirst(
|
|
3207
|
+
baseDetachId,
|
|
3208
|
+
countToProcess,
|
|
3209
|
+
);
|
|
3210
|
+
|
|
3211
|
+
countToProcess = newRenameEntry.length;
|
|
3212
|
+
|
|
3213
|
+
result = {
|
|
3214
|
+
value: { nodeChange: rootEntry.value, detachId: newRenameEntry.value },
|
|
3215
|
+
length: countToProcess,
|
|
3216
|
+
};
|
|
3217
|
+
}
|
|
3218
|
+
|
|
3219
|
+
// TODO: Consider moving this to a separate method so that this method can be side-effect free.
|
|
3220
|
+
if (result.value?.nodeChange !== undefined) {
|
|
3221
|
+
setInChangeAtomIdMap(this.table.movedNodeToParent, result.value.nodeChange, {
|
|
3222
|
+
field: this.fieldId,
|
|
3223
|
+
});
|
|
3224
|
+
}
|
|
3225
|
+
|
|
3226
|
+
return result;
|
|
2538
3227
|
}
|
|
2539
3228
|
|
|
2540
|
-
public
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
id: ChangesetLocalId,
|
|
3229
|
+
public composeAttachDetach(
|
|
3230
|
+
baseAttachId: ChangeAtomId,
|
|
3231
|
+
newDetachId: ChangeAtomId,
|
|
2544
3232
|
count: number,
|
|
2545
|
-
newValue: unknown,
|
|
2546
|
-
invalidateDependents: boolean,
|
|
2547
3233
|
): void {
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
3234
|
+
let countToProcess = count;
|
|
3235
|
+
|
|
3236
|
+
const newAttachEntry = getFirstAttachField(
|
|
3237
|
+
this.table.newChange.crossFieldKeys,
|
|
3238
|
+
newDetachId,
|
|
3239
|
+
countToProcess,
|
|
3240
|
+
);
|
|
3241
|
+
|
|
3242
|
+
countToProcess = newAttachEntry.length;
|
|
3243
|
+
|
|
3244
|
+
// Both changes can have the same ID if they came from inverse changesets.
|
|
3245
|
+
// If the new detach is part of a move,
|
|
3246
|
+
// then both input changesets contain the attach cross-field key for this ID.
|
|
3247
|
+
// The new attach may still exist in the composed changeset so we do not remove it here.
|
|
3248
|
+
// The new attach will typically cancel with a base detach,
|
|
3249
|
+
// in which case the cross-field key will be removed in `composeDetachAttach`.
|
|
3250
|
+
const hasNewAttachWithBaseAttachId =
|
|
3251
|
+
areEqualChangeAtomIds(baseAttachId, newDetachId) && newAttachEntry.value !== undefined;
|
|
3252
|
+
|
|
3253
|
+
if (!hasNewAttachWithBaseAttachId) {
|
|
3254
|
+
this.table.removedCrossFieldKeys.set(
|
|
3255
|
+
{ ...baseAttachId, target: CrossFieldTarget.Destination },
|
|
3256
|
+
countToProcess,
|
|
3257
|
+
true,
|
|
2557
3258
|
);
|
|
3259
|
+
}
|
|
2558
3260
|
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
3261
|
+
const baseDetachEntry = getFirstDetachField(
|
|
3262
|
+
this.table.baseChange.crossFieldKeys,
|
|
3263
|
+
baseAttachId,
|
|
3264
|
+
countToProcess,
|
|
3265
|
+
);
|
|
3266
|
+
|
|
3267
|
+
countToProcess = baseDetachEntry.length;
|
|
3268
|
+
|
|
3269
|
+
const baseRootIdEntry = firstDetachIdFromAttachId(
|
|
3270
|
+
this.table.baseChange.rootNodes,
|
|
3271
|
+
baseAttachId,
|
|
3272
|
+
countToProcess,
|
|
3273
|
+
);
|
|
3274
|
+
countToProcess = baseRootIdEntry.length;
|
|
3275
|
+
|
|
3276
|
+
const baseDetachId = baseRootIdEntry.value;
|
|
3277
|
+
|
|
3278
|
+
if (baseDetachEntry.value !== undefined) {
|
|
3279
|
+
// The base change moves these nodes.
|
|
3280
|
+
const prevEntry =
|
|
3281
|
+
this.table.entries.getFirst(baseAttachId, baseDetachEntry.length).value ?? {};
|
|
3282
|
+
|
|
3283
|
+
this.table.entries.set(baseAttachId, baseDetachEntry.length, {
|
|
3284
|
+
...prevEntry,
|
|
3285
|
+
detachId: newDetachId,
|
|
3286
|
+
});
|
|
3287
|
+
|
|
3288
|
+
// The new detach will replace the base detach, so we remove the key for the base detach, unless they have the same ID.
|
|
3289
|
+
if (!areEqualChangeAtomIds(baseAttachId, newDetachId)) {
|
|
3290
|
+
this.table.removedCrossFieldKeys.set(
|
|
3291
|
+
{ ...baseAttachId, target: CrossFieldTarget.Source },
|
|
3292
|
+
countToProcess,
|
|
3293
|
+
true,
|
|
2575
3294
|
);
|
|
3295
|
+
}
|
|
2576
3296
|
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
3297
|
+
this.table.movedCrossFieldKeys.set(
|
|
3298
|
+
{ ...newDetachId, target: CrossFieldTarget.Source },
|
|
3299
|
+
countToProcess,
|
|
3300
|
+
baseDetachEntry.value,
|
|
3301
|
+
);
|
|
3302
|
+
|
|
3303
|
+
this.invalidateBaseFields([baseDetachEntry.value]);
|
|
3304
|
+
} else {
|
|
3305
|
+
const baseDetachLocationEntry = this.table.baseChange.rootNodes.detachLocations.getFirst(
|
|
3306
|
+
baseDetachId,
|
|
3307
|
+
countToProcess,
|
|
3308
|
+
);
|
|
3309
|
+
countToProcess = baseDetachLocationEntry.length;
|
|
3310
|
+
|
|
3311
|
+
// These nodes were detached in the base change's input context,
|
|
3312
|
+
// so the net effect of the two changes is a rename.
|
|
3313
|
+
appendNodeRename(
|
|
3314
|
+
this.table.composedRootNodes,
|
|
3315
|
+
baseAttachId,
|
|
3316
|
+
newDetachId,
|
|
3317
|
+
baseDetachEntry.length,
|
|
3318
|
+
this.table.baseChange.rootNodes,
|
|
3319
|
+
baseDetachLocationEntry.value ?? this.fieldId,
|
|
3320
|
+
);
|
|
3321
|
+
|
|
3322
|
+
this.table.removedCrossFieldKeys.set(
|
|
3323
|
+
{ ...newDetachId, target: CrossFieldTarget.Source },
|
|
3324
|
+
countToProcess,
|
|
3325
|
+
true,
|
|
3326
|
+
);
|
|
3327
|
+
}
|
|
3328
|
+
|
|
3329
|
+
if (newAttachEntry.value === undefined) {
|
|
3330
|
+
const newOutputDetachLocationEntry =
|
|
3331
|
+
this.table.newChange.rootNodes.outputDetachLocations.getFirst(
|
|
3332
|
+
newDetachId,
|
|
3333
|
+
countToProcess,
|
|
2580
3334
|
);
|
|
2581
3335
|
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
3336
|
+
countToProcess = newOutputDetachLocationEntry.length;
|
|
3337
|
+
|
|
3338
|
+
this.table.composedRootNodes.outputDetachLocations.set(
|
|
3339
|
+
newDetachId,
|
|
3340
|
+
countToProcess,
|
|
3341
|
+
newOutputDetachLocationEntry.value ?? this.fieldId,
|
|
3342
|
+
);
|
|
3343
|
+
}
|
|
3344
|
+
|
|
3345
|
+
if (countToProcess < count) {
|
|
3346
|
+
const remainingCount = count - countToProcess;
|
|
3347
|
+
this.composeAttachDetach(
|
|
3348
|
+
offsetChangeAtomId(baseAttachId, countToProcess),
|
|
3349
|
+
offsetChangeAtomId(newDetachId, countToProcess),
|
|
3350
|
+
remainingCount,
|
|
3351
|
+
);
|
|
2589
3352
|
}
|
|
3353
|
+
}
|
|
3354
|
+
|
|
3355
|
+
public sendNewChangesToBaseSourceLocation(
|
|
3356
|
+
baseAttachId: ChangeAtomId,
|
|
3357
|
+
newChanges: NodeId,
|
|
3358
|
+
): void {
|
|
3359
|
+
const { value: baseDetachId } = firstDetachIdFromAttachId(
|
|
3360
|
+
this.table.baseChange.rootNodes,
|
|
3361
|
+
baseAttachId,
|
|
3362
|
+
1,
|
|
3363
|
+
);
|
|
3364
|
+
|
|
3365
|
+
const detachFields = getFieldsForCrossFieldKey(
|
|
3366
|
+
this.table.baseChange,
|
|
3367
|
+
{
|
|
3368
|
+
...baseDetachId,
|
|
3369
|
+
target: CrossFieldTarget.Source,
|
|
3370
|
+
},
|
|
3371
|
+
1,
|
|
3372
|
+
);
|
|
2590
3373
|
|
|
2591
|
-
|
|
3374
|
+
if (detachFields.length > 0) {
|
|
3375
|
+
// The base attach is part of a move in the base changeset.
|
|
3376
|
+
const prevEntry = this.table.entries.getFirst(baseDetachId, 1).value ?? {};
|
|
3377
|
+
this.table.entries.set(baseDetachId, 1, { ...prevEntry, nodeChange: newChanges });
|
|
3378
|
+
|
|
3379
|
+
if (newChanges !== undefined) {
|
|
3380
|
+
this.invalidateBaseFields(detachFields);
|
|
3381
|
+
}
|
|
3382
|
+
} else {
|
|
3383
|
+
const baseNodeId = getFromChangeAtomIdMap(
|
|
3384
|
+
this.table.baseChange.rootNodes.nodeChanges,
|
|
3385
|
+
baseDetachId,
|
|
3386
|
+
);
|
|
3387
|
+
|
|
3388
|
+
if (baseNodeId !== undefined) {
|
|
3389
|
+
addNodesToCompose(this.table, baseNodeId, newChanges);
|
|
3390
|
+
} else {
|
|
3391
|
+
assignRootChange(
|
|
3392
|
+
this.table.composedRootNodes,
|
|
3393
|
+
this.table.movedNodeToParent,
|
|
3394
|
+
baseDetachId,
|
|
3395
|
+
newChanges,
|
|
3396
|
+
this.fieldId,
|
|
3397
|
+
this.table.rebaseVersion,
|
|
3398
|
+
);
|
|
3399
|
+
}
|
|
3400
|
+
}
|
|
2592
3401
|
}
|
|
2593
3402
|
|
|
2594
|
-
|
|
2595
|
-
|
|
3403
|
+
private areSameNodes(
|
|
3404
|
+
baseDetachId: ChangeAtomId,
|
|
3405
|
+
newAttachId: ChangeAtomId,
|
|
3406
|
+
count: number,
|
|
3407
|
+
): RangeQueryResult<boolean> {
|
|
3408
|
+
const renamedDetachEntry = firstAttachIdFromDetachId(
|
|
3409
|
+
this.table.composedRootNodes,
|
|
3410
|
+
baseDetachId,
|
|
3411
|
+
count,
|
|
3412
|
+
);
|
|
3413
|
+
|
|
3414
|
+
const isReattachOfSameNodes = areEqualChangeAtomIds(renamedDetachEntry.value, newAttachId);
|
|
3415
|
+
return { ...renamedDetachEntry, value: isReattachOfSameNodes };
|
|
2596
3416
|
}
|
|
2597
3417
|
|
|
2598
|
-
public
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
id: ChangesetLocalId,
|
|
3418
|
+
public composeDetachAttach(
|
|
3419
|
+
baseDetachId: ChangeAtomId,
|
|
3420
|
+
newAttachId: ChangeAtomId,
|
|
2602
3421
|
count: number,
|
|
3422
|
+
composeToPin: boolean,
|
|
2603
3423
|
): void {
|
|
2604
|
-
|
|
3424
|
+
const areSameEntry = this.areSameNodes(baseDetachId, newAttachId, count);
|
|
3425
|
+
|
|
3426
|
+
const countToProcess = areSameEntry.length;
|
|
3427
|
+
if (areSameEntry.value) {
|
|
3428
|
+
// These nodes have been moved back to their original location, so the composed changeset should not have any renames for them.
|
|
3429
|
+
// Note that deleting the rename from `this.table.composedRootNodes` would change the result of this method
|
|
3430
|
+
// if it were rerun due to the field being invalidated, so we instead record that the rename should be deleted later.
|
|
3431
|
+
this.table.renamesToDelete.set(baseDetachId, countToProcess, true);
|
|
3432
|
+
}
|
|
3433
|
+
|
|
3434
|
+
if (composeToPin) {
|
|
3435
|
+
this.table.movedCrossFieldKeys.set(
|
|
3436
|
+
{ target: CrossFieldTarget.Source, ...newAttachId },
|
|
3437
|
+
countToProcess,
|
|
3438
|
+
this.fieldId,
|
|
3439
|
+
);
|
|
3440
|
+
|
|
3441
|
+
if (!areEqualChangeAtomIds(baseDetachId, newAttachId)) {
|
|
3442
|
+
// The pin will have `newAttachId` as both its detach and attach ID.
|
|
3443
|
+
// So we remove `baseDetachId` unless that is equal to the pin's detach ID.
|
|
3444
|
+
this.table.removedCrossFieldKeys.set(
|
|
3445
|
+
{ target: CrossFieldTarget.Source, ...baseDetachId },
|
|
3446
|
+
countToProcess,
|
|
3447
|
+
true,
|
|
3448
|
+
);
|
|
3449
|
+
}
|
|
3450
|
+
|
|
3451
|
+
// Note that while change2 should already have this key, change1 may have a rollback for the same ID in a different location.
|
|
3452
|
+
// In that case, change1's attach should be canceled out by a detach from change2.
|
|
3453
|
+
// Here we make sure that the composed change has the correct location (this field) for the attach ID.
|
|
3454
|
+
this.table.movedCrossFieldKeys.set(
|
|
3455
|
+
{ target: CrossFieldTarget.Destination, ...newAttachId },
|
|
3456
|
+
countToProcess,
|
|
3457
|
+
this.fieldId,
|
|
3458
|
+
);
|
|
3459
|
+
} else {
|
|
3460
|
+
this.table.removedCrossFieldKeys.set(
|
|
3461
|
+
{ target: CrossFieldTarget.Source, ...baseDetachId },
|
|
3462
|
+
countToProcess,
|
|
3463
|
+
true,
|
|
3464
|
+
);
|
|
3465
|
+
|
|
3466
|
+
this.table.removedCrossFieldKeys.set(
|
|
3467
|
+
{ target: CrossFieldTarget.Destination, ...newAttachId },
|
|
3468
|
+
countToProcess,
|
|
3469
|
+
true,
|
|
3470
|
+
);
|
|
3471
|
+
}
|
|
3472
|
+
|
|
3473
|
+
if (countToProcess < count) {
|
|
3474
|
+
this.composeAttachDetach(
|
|
3475
|
+
offsetChangeAtomId(baseDetachId, countToProcess),
|
|
3476
|
+
offsetChangeAtomId(newAttachId, countToProcess),
|
|
3477
|
+
count - countToProcess,
|
|
3478
|
+
);
|
|
3479
|
+
}
|
|
2605
3480
|
}
|
|
2606
3481
|
|
|
2607
|
-
private
|
|
2608
|
-
|
|
3482
|
+
private invalidateBaseFields(fields: FieldId[]): void {
|
|
3483
|
+
if (this.allowInval) {
|
|
3484
|
+
for (const fieldId of fields) {
|
|
3485
|
+
this.table.pendingCompositions.affectedBaseFields.set(
|
|
3486
|
+
fieldIdKeyFromFieldId(fieldId),
|
|
3487
|
+
true,
|
|
3488
|
+
);
|
|
3489
|
+
}
|
|
3490
|
+
}
|
|
2609
3491
|
}
|
|
2610
3492
|
}
|
|
2611
3493
|
|
|
2612
3494
|
function makeModularChangeset(
|
|
2613
3495
|
props: {
|
|
3496
|
+
rebaseVersion?: RebaseVersion;
|
|
2614
3497
|
fieldChanges?: FieldChangeMap;
|
|
2615
3498
|
nodeChanges?: ChangeAtomIdBTree<NodeChangeset>;
|
|
2616
|
-
|
|
3499
|
+
rootNodes?: RootNodeTable;
|
|
3500
|
+
nodeToParent?: ChangeAtomIdBTree<NodeLocation>;
|
|
2617
3501
|
nodeAliases?: ChangeAtomIdBTree<NodeId>;
|
|
2618
3502
|
crossFieldKeys?: CrossFieldKeyTable;
|
|
2619
3503
|
maxId: number;
|
|
@@ -2628,11 +3512,13 @@ function makeModularChangeset(
|
|
|
2628
3512
|
},
|
|
2629
3513
|
): ModularChangeset {
|
|
2630
3514
|
const changeset: Mutable<ModularChangeset> = {
|
|
3515
|
+
rebaseVersion: props.rebaseVersion ?? 1,
|
|
2631
3516
|
fieldChanges: props.fieldChanges ?? new Map(),
|
|
2632
3517
|
nodeChanges: props.nodeChanges ?? newTupleBTree(),
|
|
3518
|
+
rootNodes: props.rootNodes ?? newRootTable(),
|
|
2633
3519
|
nodeToParent: props.nodeToParent ?? newTupleBTree(),
|
|
2634
3520
|
nodeAliases: props.nodeAliases ?? newTupleBTree(),
|
|
2635
|
-
crossFieldKeys: props.crossFieldKeys ??
|
|
3521
|
+
crossFieldKeys: props.crossFieldKeys ?? newCrossFieldRangeTable(),
|
|
2636
3522
|
};
|
|
2637
3523
|
|
|
2638
3524
|
if (props.revisions !== undefined && props.revisions.length > 0) {
|
|
@@ -2659,6 +3545,7 @@ function makeModularChangeset(
|
|
|
2659
3545
|
if (props.refreshers !== undefined && props.refreshers.size > 0) {
|
|
2660
3546
|
changeset.refreshers = props.refreshers;
|
|
2661
3547
|
}
|
|
3548
|
+
|
|
2662
3549
|
return changeset;
|
|
2663
3550
|
}
|
|
2664
3551
|
|
|
@@ -2675,6 +3562,10 @@ export class ModularEditBuilder extends EditBuilder<ModularChangeset> {
|
|
|
2675
3562
|
this.idAllocator = idAllocatorFromMaxId();
|
|
2676
3563
|
}
|
|
2677
3564
|
|
|
3565
|
+
public isInTransaction(): boolean {
|
|
3566
|
+
return this.transactionDepth > 0;
|
|
3567
|
+
}
|
|
3568
|
+
|
|
2678
3569
|
public override enterTransaction(): void {
|
|
2679
3570
|
this.transactionDepth += 1;
|
|
2680
3571
|
if (this.transactionDepth === 1) {
|
|
@@ -2729,7 +3620,7 @@ export class ModularEditBuilder extends EditBuilder<ModularChangeset> {
|
|
|
2729
3620
|
* @param revision - the revision of the change
|
|
2730
3621
|
*/
|
|
2731
3622
|
public submitChange(
|
|
2732
|
-
field:
|
|
3623
|
+
field: NormalizedFieldUpPath,
|
|
2733
3624
|
fieldKind: FieldKindIdentifier,
|
|
2734
3625
|
change: FieldChangeset,
|
|
2735
3626
|
revision: RevisionTag,
|
|
@@ -2743,7 +3634,8 @@ export class ModularEditBuilder extends EditBuilder<ModularChangeset> {
|
|
|
2743
3634
|
fieldChange: { fieldKind, change },
|
|
2744
3635
|
nodeChanges: newTupleBTree(),
|
|
2745
3636
|
nodeToParent: newTupleBTree(),
|
|
2746
|
-
crossFieldKeys:
|
|
3637
|
+
crossFieldKeys: newCrossFieldRangeTable(),
|
|
3638
|
+
rootNodes: newRootTable(),
|
|
2747
3639
|
idAllocator: this.idAllocator,
|
|
2748
3640
|
localCrossFieldKeys,
|
|
2749
3641
|
revision,
|
|
@@ -2765,6 +3657,7 @@ export class ModularEditBuilder extends EditBuilder<ModularChangeset> {
|
|
|
2765
3657
|
? makeModularChangeset({
|
|
2766
3658
|
maxId: this.idAllocator.getMaxId(),
|
|
2767
3659
|
builds: change.builds,
|
|
3660
|
+
rootNodes: renameTableFromRenameDescriptions(change.renames ?? []),
|
|
2768
3661
|
revisions: [{ revision: change.revision }],
|
|
2769
3662
|
})
|
|
2770
3663
|
: buildModularChangesetFromField({
|
|
@@ -2775,7 +3668,8 @@ export class ModularEditBuilder extends EditBuilder<ModularChangeset> {
|
|
|
2775
3668
|
},
|
|
2776
3669
|
nodeChanges: newTupleBTree(),
|
|
2777
3670
|
nodeToParent: newTupleBTree(),
|
|
2778
|
-
crossFieldKeys:
|
|
3671
|
+
crossFieldKeys: newCrossFieldRangeTable(),
|
|
3672
|
+
rootNodes: newRootTable(),
|
|
2779
3673
|
idAllocator: this.idAllocator,
|
|
2780
3674
|
localCrossFieldKeys: getChangeHandler(
|
|
2781
3675
|
this.fieldKinds,
|
|
@@ -2802,7 +3696,7 @@ export class ModularEditBuilder extends EditBuilder<ModularChangeset> {
|
|
|
2802
3696
|
return brand(this.idAllocator.allocate(count));
|
|
2803
3697
|
}
|
|
2804
3698
|
|
|
2805
|
-
public addNodeExistsConstraint(path:
|
|
3699
|
+
public addNodeExistsConstraint(path: NormalizedUpPath, revision: RevisionTag): void {
|
|
2806
3700
|
const nodeChange: NodeChangeset = {
|
|
2807
3701
|
nodeExistsConstraint: { violated: false },
|
|
2808
3702
|
};
|
|
@@ -2814,7 +3708,8 @@ export class ModularEditBuilder extends EditBuilder<ModularChangeset> {
|
|
|
2814
3708
|
nodeChange,
|
|
2815
3709
|
nodeChanges: newTupleBTree(),
|
|
2816
3710
|
nodeToParent: newTupleBTree(),
|
|
2817
|
-
crossFieldKeys:
|
|
3711
|
+
crossFieldKeys: newCrossFieldRangeTable(),
|
|
3712
|
+
rootNodes: newRootTable(),
|
|
2818
3713
|
idAllocator: this.idAllocator,
|
|
2819
3714
|
revision,
|
|
2820
3715
|
}),
|
|
@@ -2823,7 +3718,7 @@ export class ModularEditBuilder extends EditBuilder<ModularChangeset> {
|
|
|
2823
3718
|
);
|
|
2824
3719
|
}
|
|
2825
3720
|
|
|
2826
|
-
public addNodeExistsConstraintOnRevert(path:
|
|
3721
|
+
public addNodeExistsConstraintOnRevert(path: NormalizedUpPath, revision: RevisionTag): void {
|
|
2827
3722
|
const nodeChange: NodeChangeset = {
|
|
2828
3723
|
nodeExistsConstraintOnRevert: { violated: false },
|
|
2829
3724
|
};
|
|
@@ -2835,7 +3730,8 @@ export class ModularEditBuilder extends EditBuilder<ModularChangeset> {
|
|
|
2835
3730
|
nodeChange,
|
|
2836
3731
|
nodeChanges: newTupleBTree(),
|
|
2837
3732
|
nodeToParent: newTupleBTree(),
|
|
2838
|
-
crossFieldKeys:
|
|
3733
|
+
crossFieldKeys: newCrossFieldRangeTable(),
|
|
3734
|
+
rootNodes: newRootTable(),
|
|
2839
3735
|
idAllocator: this.idAllocator,
|
|
2840
3736
|
revision,
|
|
2841
3737
|
}),
|
|
@@ -2845,12 +3741,13 @@ export class ModularEditBuilder extends EditBuilder<ModularChangeset> {
|
|
|
2845
3741
|
}
|
|
2846
3742
|
}
|
|
2847
3743
|
|
|
2848
|
-
function buildModularChangesetFromField(props: {
|
|
2849
|
-
path:
|
|
3744
|
+
export function buildModularChangesetFromField(props: {
|
|
3745
|
+
path: NormalizedFieldUpPath;
|
|
2850
3746
|
fieldChange: FieldChange;
|
|
2851
3747
|
nodeChanges: ChangeAtomIdBTree<NodeChangeset>;
|
|
2852
|
-
nodeToParent: ChangeAtomIdBTree<
|
|
3748
|
+
nodeToParent: ChangeAtomIdBTree<NodeLocation>;
|
|
2853
3749
|
crossFieldKeys: CrossFieldKeyTable;
|
|
3750
|
+
rootNodes: RootNodeTable;
|
|
2854
3751
|
localCrossFieldKeys?: CrossFieldKeyRange[];
|
|
2855
3752
|
revision: RevisionTag;
|
|
2856
3753
|
idAllocator?: IdAllocator;
|
|
@@ -2862,6 +3759,7 @@ function buildModularChangesetFromField(props: {
|
|
|
2862
3759
|
nodeChanges,
|
|
2863
3760
|
nodeToParent,
|
|
2864
3761
|
crossFieldKeys,
|
|
3762
|
+
rootNodes,
|
|
2865
3763
|
idAllocator = idAllocatorFromMaxId(),
|
|
2866
3764
|
localCrossFieldKeys = [],
|
|
2867
3765
|
childId,
|
|
@@ -2870,14 +3768,17 @@ function buildModularChangesetFromField(props: {
|
|
|
2870
3768
|
const fieldChanges: FieldChangeMap = new Map([[path.field, fieldChange]]);
|
|
2871
3769
|
|
|
2872
3770
|
if (path.parent === undefined) {
|
|
3771
|
+
const field = { nodeId: undefined, field: path.field };
|
|
2873
3772
|
for (const { key, count } of localCrossFieldKeys) {
|
|
2874
|
-
crossFieldKeys.set(key, count,
|
|
3773
|
+
crossFieldKeys.set(key, count, field);
|
|
2875
3774
|
}
|
|
2876
3775
|
|
|
2877
3776
|
if (childId !== undefined) {
|
|
2878
3777
|
setInChangeAtomIdMap(nodeToParent, childId, {
|
|
2879
|
-
|
|
2880
|
-
|
|
3778
|
+
field: {
|
|
3779
|
+
nodeId: undefined,
|
|
3780
|
+
field: path.field,
|
|
3781
|
+
},
|
|
2881
3782
|
});
|
|
2882
3783
|
}
|
|
2883
3784
|
|
|
@@ -2886,6 +3787,7 @@ function buildModularChangesetFromField(props: {
|
|
|
2886
3787
|
nodeChanges,
|
|
2887
3788
|
nodeToParent,
|
|
2888
3789
|
crossFieldKeys,
|
|
3790
|
+
rootNodes,
|
|
2889
3791
|
maxId: idAllocator.getMaxId(),
|
|
2890
3792
|
revisions: [{ revision }],
|
|
2891
3793
|
});
|
|
@@ -2896,6 +3798,7 @@ function buildModularChangesetFromField(props: {
|
|
|
2896
3798
|
};
|
|
2897
3799
|
|
|
2898
3800
|
const parentId: NodeId = { localId: brand(idAllocator.allocate()), revision };
|
|
3801
|
+
const fieldId = { nodeId: parentId, field: path.field };
|
|
2899
3802
|
|
|
2900
3803
|
for (const { key, count } of localCrossFieldKeys) {
|
|
2901
3804
|
crossFieldKeys.set(key, count, { nodeId: parentId, field: path.field });
|
|
@@ -2903,8 +3806,7 @@ function buildModularChangesetFromField(props: {
|
|
|
2903
3806
|
|
|
2904
3807
|
if (childId !== undefined) {
|
|
2905
3808
|
setInChangeAtomIdMap(nodeToParent, childId, {
|
|
2906
|
-
|
|
2907
|
-
field: path.field,
|
|
3809
|
+
field: fieldId,
|
|
2908
3810
|
});
|
|
2909
3811
|
}
|
|
2910
3812
|
|
|
@@ -2914,6 +3816,7 @@ function buildModularChangesetFromField(props: {
|
|
|
2914
3816
|
nodeChanges,
|
|
2915
3817
|
nodeToParent,
|
|
2916
3818
|
crossFieldKeys,
|
|
3819
|
+
rootNodes,
|
|
2917
3820
|
idAllocator,
|
|
2918
3821
|
revision,
|
|
2919
3822
|
nodeId: parentId,
|
|
@@ -2921,11 +3824,12 @@ function buildModularChangesetFromField(props: {
|
|
|
2921
3824
|
}
|
|
2922
3825
|
|
|
2923
3826
|
function buildModularChangesetFromNode(props: {
|
|
2924
|
-
path:
|
|
3827
|
+
path: NormalizedUpPath;
|
|
2925
3828
|
nodeChange: NodeChangeset;
|
|
2926
3829
|
nodeChanges: ChangeAtomIdBTree<NodeChangeset>;
|
|
2927
|
-
nodeToParent: ChangeAtomIdBTree<
|
|
3830
|
+
nodeToParent: ChangeAtomIdBTree<NodeLocation>;
|
|
2928
3831
|
crossFieldKeys: CrossFieldKeyTable;
|
|
3832
|
+
rootNodes: RootNodeTable;
|
|
2929
3833
|
idAllocator: IdAllocator;
|
|
2930
3834
|
revision: RevisionTag;
|
|
2931
3835
|
nodeId?: NodeId;
|
|
@@ -2935,27 +3839,43 @@ function buildModularChangesetFromNode(props: {
|
|
|
2935
3839
|
nodeId = { localId: brand(props.idAllocator.allocate()), revision: props.revision },
|
|
2936
3840
|
} = props;
|
|
2937
3841
|
setInChangeAtomIdMap(props.nodeChanges, nodeId, props.nodeChange);
|
|
2938
|
-
const fieldChangeset = genericFieldKind.changeHandler.editor.buildChildChanges([
|
|
2939
|
-
[path.parentIndex, nodeId],
|
|
2940
|
-
]);
|
|
2941
3842
|
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
3843
|
+
if (isDetachedUpPathRoot(path)) {
|
|
3844
|
+
props.rootNodes.nodeChanges.set(
|
|
3845
|
+
[path.detachedNodeId.major, brand(path.detachedNodeId.minor)],
|
|
3846
|
+
nodeId,
|
|
3847
|
+
);
|
|
3848
|
+
return makeModularChangeset({
|
|
3849
|
+
rootNodes: props.rootNodes,
|
|
3850
|
+
nodeChanges: props.nodeChanges,
|
|
3851
|
+
nodeToParent: props.nodeToParent,
|
|
3852
|
+
crossFieldKeys: props.crossFieldKeys,
|
|
3853
|
+
maxId: props.idAllocator.getMaxId(),
|
|
3854
|
+
revisions: [{ revision: props.revision }],
|
|
3855
|
+
});
|
|
3856
|
+
} else {
|
|
3857
|
+
const fieldChangeset = genericFieldKind.changeHandler.editor.buildChildChanges([
|
|
3858
|
+
[path.parentIndex, nodeId],
|
|
3859
|
+
]);
|
|
2946
3860
|
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
3861
|
+
const fieldChange: FieldChange = {
|
|
3862
|
+
fieldKind: genericFieldKind.identifier,
|
|
3863
|
+
change: fieldChangeset,
|
|
3864
|
+
};
|
|
3865
|
+
|
|
3866
|
+
return buildModularChangesetFromField({
|
|
3867
|
+
...props,
|
|
3868
|
+
path: { parent: path.parent, field: path.parentField },
|
|
3869
|
+
fieldChange,
|
|
3870
|
+
localCrossFieldKeys: [],
|
|
3871
|
+
childId: nodeId,
|
|
3872
|
+
});
|
|
3873
|
+
}
|
|
2954
3874
|
}
|
|
2955
3875
|
|
|
2956
3876
|
export interface FieldEditDescription {
|
|
2957
3877
|
type: "field";
|
|
2958
|
-
field:
|
|
3878
|
+
field: NormalizedFieldUpPath;
|
|
2959
3879
|
fieldKind: FieldKindIdentifier;
|
|
2960
3880
|
change: FieldChangeset;
|
|
2961
3881
|
revision: RevisionTag;
|
|
@@ -2965,6 +3885,23 @@ export interface GlobalEditDescription {
|
|
|
2965
3885
|
type: "global";
|
|
2966
3886
|
revision: RevisionTag;
|
|
2967
3887
|
builds?: ChangeAtomIdBTree<TreeChunk>;
|
|
3888
|
+
renames?: RenameDescription[];
|
|
3889
|
+
}
|
|
3890
|
+
|
|
3891
|
+
export interface RenameDescription {
|
|
3892
|
+
count: number;
|
|
3893
|
+
oldId: ChangeAtomId;
|
|
3894
|
+
newId: ChangeAtomId;
|
|
3895
|
+
detachLocation: FieldId | undefined;
|
|
3896
|
+
}
|
|
3897
|
+
|
|
3898
|
+
function renameTableFromRenameDescriptions(renames: RenameDescription[]): RootNodeTable {
|
|
3899
|
+
const table = newRootTable();
|
|
3900
|
+
for (const rename of renames) {
|
|
3901
|
+
addNodeRename(table, rename.oldId, rename.newId, rename.count, rename.detachLocation);
|
|
3902
|
+
}
|
|
3903
|
+
|
|
3904
|
+
return table;
|
|
2968
3905
|
}
|
|
2969
3906
|
|
|
2970
3907
|
export type EditDescription = FieldEditDescription | GlobalEditDescription;
|
|
@@ -2981,22 +3918,6 @@ function getRevInfoFromTaggedChanges(changes: TaggedChange<ModularChangeset>[]):
|
|
|
2981
3918
|
revInfos.push(...revisionInfoFromTaggedChange(taggedChange));
|
|
2982
3919
|
}
|
|
2983
3920
|
|
|
2984
|
-
const revisions = new Set<RevisionTag>();
|
|
2985
|
-
const rolledBackRevisions: RevisionTag[] = [];
|
|
2986
|
-
for (const info of revInfos) {
|
|
2987
|
-
revisions.add(info.revision);
|
|
2988
|
-
if (info.rollbackOf !== undefined) {
|
|
2989
|
-
rolledBackRevisions.push(info.rollbackOf);
|
|
2990
|
-
}
|
|
2991
|
-
}
|
|
2992
|
-
|
|
2993
|
-
rolledBackRevisions.reverse();
|
|
2994
|
-
for (const revision of rolledBackRevisions) {
|
|
2995
|
-
if (!revisions.has(revision)) {
|
|
2996
|
-
revInfos.push({ revision });
|
|
2997
|
-
}
|
|
2998
|
-
}
|
|
2999
|
-
|
|
3000
3921
|
return { maxId: brand(maxId), revInfos };
|
|
3001
3922
|
}
|
|
3002
3923
|
|
|
@@ -3016,25 +3937,28 @@ function revisionInfoFromTaggedChange(
|
|
|
3016
3937
|
return revInfos;
|
|
3017
3938
|
}
|
|
3018
3939
|
|
|
3019
|
-
function fieldChangeFromId(
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3940
|
+
function fieldChangeFromId(change: ModularChangeset, id: FieldId): FieldChange {
|
|
3941
|
+
const fieldId = normalizeFieldId(id, change.nodeAliases);
|
|
3942
|
+
const fieldMap = fieldMapFromNodeId(
|
|
3943
|
+
change.fieldChanges,
|
|
3944
|
+
change.nodeChanges,
|
|
3945
|
+
change.nodeAliases,
|
|
3946
|
+
fieldId.nodeId,
|
|
3947
|
+
);
|
|
3025
3948
|
return fieldMap.get(id.field) ?? fail(0xb25 /* No field exists for the given ID */);
|
|
3026
3949
|
}
|
|
3027
3950
|
|
|
3028
3951
|
function fieldMapFromNodeId(
|
|
3029
3952
|
rootFieldMap: FieldChangeMap,
|
|
3030
3953
|
nodes: ChangeAtomIdBTree<NodeChangeset>,
|
|
3954
|
+
aliases: ChangeAtomIdBTree<NodeId>,
|
|
3031
3955
|
nodeId: NodeId | undefined,
|
|
3032
3956
|
): FieldChangeMap {
|
|
3033
3957
|
if (nodeId === undefined) {
|
|
3034
3958
|
return rootFieldMap;
|
|
3035
3959
|
}
|
|
3036
3960
|
|
|
3037
|
-
const node = nodeChangeFromId(nodes, nodeId);
|
|
3961
|
+
const node = nodeChangeFromId(nodes, aliases, nodeId);
|
|
3038
3962
|
assert(node.fieldChanges !== undefined, 0x9c9 /* Expected node to have field changes */);
|
|
3039
3963
|
return node.fieldChanges;
|
|
3040
3964
|
}
|
|
@@ -3051,8 +3975,13 @@ function rebasedNodeIdFromBaseNodeId(table: RebaseTable, baseId: NodeId): NodeId
|
|
|
3051
3975
|
return getFromChangeAtomIdMap(table.baseToRebasedNodeId, baseId) ?? baseId;
|
|
3052
3976
|
}
|
|
3053
3977
|
|
|
3054
|
-
function nodeChangeFromId(
|
|
3055
|
-
|
|
3978
|
+
function nodeChangeFromId(
|
|
3979
|
+
nodes: ChangeAtomIdBTree<NodeChangeset>,
|
|
3980
|
+
aliases: ChangeAtomIdBTree<NodeId>,
|
|
3981
|
+
id: NodeId,
|
|
3982
|
+
): NodeChangeset {
|
|
3983
|
+
const normalizedId = normalizeNodeId(id, aliases);
|
|
3984
|
+
const node = getFromChangeAtomIdMap(nodes, normalizedId);
|
|
3056
3985
|
assert(node !== undefined, 0x9ca /* Unknown node ID */);
|
|
3057
3986
|
return node;
|
|
3058
3987
|
}
|
|
@@ -3062,6 +3991,10 @@ function fieldIdFromFieldIdKey([revision, localId, field]: FieldIdKey): FieldId
|
|
|
3062
3991
|
return { nodeId, field };
|
|
3063
3992
|
}
|
|
3064
3993
|
|
|
3994
|
+
function fieldIdKeyFromFieldId(fieldId: FieldId): FieldIdKey {
|
|
3995
|
+
return [fieldId.nodeId?.revision, fieldId.nodeId?.localId, fieldId.field];
|
|
3996
|
+
}
|
|
3997
|
+
|
|
3065
3998
|
function cloneNodeChangeset(nodeChangeset: NodeChangeset): NodeChangeset {
|
|
3066
3999
|
if (nodeChangeset.fieldChanges !== undefined) {
|
|
3067
4000
|
return { ...nodeChangeset, fieldChanges: new Map(nodeChangeset.fieldChanges) };
|
|
@@ -3070,6 +4003,16 @@ function cloneNodeChangeset(nodeChangeset: NodeChangeset): NodeChangeset {
|
|
|
3070
4003
|
return { ...nodeChangeset };
|
|
3071
4004
|
}
|
|
3072
4005
|
|
|
4006
|
+
function replaceNodeLocationRevision(
|
|
4007
|
+
location: NodeLocation,
|
|
4008
|
+
oldRevisions: Set<RevisionTag | undefined>,
|
|
4009
|
+
newRevision: RevisionTag | undefined,
|
|
4010
|
+
): NodeLocation {
|
|
4011
|
+
return location.field !== undefined
|
|
4012
|
+
? { field: replaceFieldIdRevision(location.field, oldRevisions, newRevision) }
|
|
4013
|
+
: { root: replaceAtomRevisions(location.root, oldRevisions, newRevision) };
|
|
4014
|
+
}
|
|
4015
|
+
|
|
3073
4016
|
function replaceFieldIdRevision(
|
|
3074
4017
|
fieldId: FieldId,
|
|
3075
4018
|
oldRevisions: Set<RevisionTag | undefined>,
|
|
@@ -3085,10 +4028,16 @@ function replaceFieldIdRevision(
|
|
|
3085
4028
|
};
|
|
3086
4029
|
}
|
|
3087
4030
|
|
|
3088
|
-
export function
|
|
3089
|
-
const
|
|
3090
|
-
|
|
3091
|
-
|
|
4031
|
+
export function getNodeParent(changeset: ModularChangeset, nodeId: NodeId): NodeLocation {
|
|
4032
|
+
const normalizedNodeId = normalizeNodeId(nodeId, changeset.nodeAliases);
|
|
4033
|
+
const location = getFromChangeAtomIdMap(changeset.nodeToParent, normalizedNodeId);
|
|
4034
|
+
assert(location !== undefined, 0x9cb /* Parent field should be defined */);
|
|
4035
|
+
|
|
4036
|
+
if (location.field !== undefined) {
|
|
4037
|
+
return { field: normalizeFieldId(location.field, changeset.nodeAliases) };
|
|
4038
|
+
}
|
|
4039
|
+
|
|
4040
|
+
return location;
|
|
3092
4041
|
}
|
|
3093
4042
|
|
|
3094
4043
|
function getFieldsForCrossFieldKey(
|
|
@@ -3101,6 +4050,30 @@ function getFieldsForCrossFieldKey(
|
|
|
3101
4050
|
.map(({ value: fieldId }) => normalizeFieldId(fieldId, changeset.nodeAliases));
|
|
3102
4051
|
}
|
|
3103
4052
|
|
|
4053
|
+
function getFirstFieldForCrossFieldKey(
|
|
4054
|
+
changeset: ModularChangeset,
|
|
4055
|
+
key: CrossFieldKey,
|
|
4056
|
+
count: number,
|
|
4057
|
+
): RangeQueryResult<FieldId | undefined> {
|
|
4058
|
+
const result = changeset.crossFieldKeys.getFirst(key, count);
|
|
4059
|
+
if (result.value === undefined) {
|
|
4060
|
+
return result;
|
|
4061
|
+
}
|
|
4062
|
+
|
|
4063
|
+
return { ...result, value: normalizeFieldId(result.value, changeset.nodeAliases) };
|
|
4064
|
+
}
|
|
4065
|
+
|
|
4066
|
+
function normalizeNodeLocation(
|
|
4067
|
+
location: NodeLocation,
|
|
4068
|
+
nodeAliases: ChangeAtomIdBTree<NodeId>,
|
|
4069
|
+
): NodeLocation {
|
|
4070
|
+
if (location.field !== undefined) {
|
|
4071
|
+
return { field: normalizeFieldId(location.field, nodeAliases) };
|
|
4072
|
+
}
|
|
4073
|
+
|
|
4074
|
+
return location;
|
|
4075
|
+
}
|
|
4076
|
+
|
|
3104
4077
|
// This is only exported for use in test utilities.
|
|
3105
4078
|
export function normalizeFieldId(
|
|
3106
4079
|
fieldId: FieldId,
|
|
@@ -3114,8 +4087,12 @@ export function normalizeFieldId(
|
|
|
3114
4087
|
/**
|
|
3115
4088
|
* @returns The canonical form of nodeId, according to nodeAliases
|
|
3116
4089
|
*/
|
|
3117
|
-
function normalizeNodeId(
|
|
4090
|
+
export function normalizeNodeId(
|
|
4091
|
+
nodeId: NodeId,
|
|
4092
|
+
nodeAliases: ChangeAtomIdBTree<NodeId>,
|
|
4093
|
+
): NodeId {
|
|
3118
4094
|
let currentId = nodeId;
|
|
4095
|
+
let cycleProbeId: NodeId | undefined = nodeId;
|
|
3119
4096
|
|
|
3120
4097
|
// eslint-disable-next-line no-constant-condition
|
|
3121
4098
|
while (true) {
|
|
@@ -3125,6 +4102,16 @@ function normalizeNodeId(nodeId: NodeId, nodeAliases: ChangeAtomIdBTree<NodeId>)
|
|
|
3125
4102
|
}
|
|
3126
4103
|
|
|
3127
4104
|
currentId = dealiased;
|
|
4105
|
+
|
|
4106
|
+
if (cycleProbeId !== undefined) {
|
|
4107
|
+
cycleProbeId = getFromChangeAtomIdMap(nodeAliases, cycleProbeId);
|
|
4108
|
+
}
|
|
4109
|
+
|
|
4110
|
+
if (cycleProbeId !== undefined) {
|
|
4111
|
+
cycleProbeId = getFromChangeAtomIdMap(nodeAliases, cycleProbeId);
|
|
4112
|
+
}
|
|
4113
|
+
|
|
4114
|
+
assert(!areEqualChangeAtomIdOpts(cycleProbeId, currentId), "Alias cycle detected");
|
|
3128
4115
|
}
|
|
3129
4116
|
}
|
|
3130
4117
|
|
|
@@ -3135,22 +4122,835 @@ function hasConflicts(change: ModularChangeset): boolean {
|
|
|
3135
4122
|
interface ModularChangesetContent {
|
|
3136
4123
|
fieldChanges: FieldChangeMap;
|
|
3137
4124
|
nodeChanges: ChangeAtomIdBTree<NodeChangeset>;
|
|
3138
|
-
nodeToParent: ChangeAtomIdBTree<
|
|
4125
|
+
nodeToParent: ChangeAtomIdBTree<NodeLocation>;
|
|
4126
|
+
rootNodes: RootNodeTable;
|
|
3139
4127
|
nodeAliases: ChangeAtomIdBTree<NodeId>;
|
|
3140
4128
|
crossFieldKeys: CrossFieldKeyTable;
|
|
3141
4129
|
}
|
|
3142
4130
|
|
|
3143
|
-
function
|
|
3144
|
-
|
|
3145
|
-
id: ChangeAtomId,
|
|
3146
|
-
): T | undefined {
|
|
3147
|
-
return map.get([id.revision, id.localId]);
|
|
4131
|
+
function areEqualFieldIds(a: FieldId, b: FieldId): boolean {
|
|
4132
|
+
return areEqualChangeAtomIdOpts(a.nodeId, b.nodeId) && a.field === b.field;
|
|
3148
4133
|
}
|
|
3149
4134
|
|
|
3150
|
-
function
|
|
3151
|
-
|
|
4135
|
+
function firstAttachIdFromDetachId(
|
|
4136
|
+
roots: RootNodeTable,
|
|
4137
|
+
detachId: ChangeAtomId,
|
|
4138
|
+
count: number,
|
|
4139
|
+
): RangeQueryResult<ChangeAtomId> {
|
|
4140
|
+
const result = roots.oldToNewId.getFirst(detachId, count);
|
|
4141
|
+
return { ...result, value: result.value ?? detachId };
|
|
3152
4142
|
}
|
|
3153
4143
|
|
|
3154
|
-
function
|
|
3155
|
-
|
|
4144
|
+
function firstDetachIdFromAttachId(
|
|
4145
|
+
roots: RootNodeTable,
|
|
4146
|
+
attachId: ChangeAtomId,
|
|
4147
|
+
count: number,
|
|
4148
|
+
): RangeQueryEntry<ChangeAtomId, ChangeAtomId> {
|
|
4149
|
+
const result = roots.newToOldId.getFirst(attachId, count);
|
|
4150
|
+
return { ...result, start: attachId, value: result.value ?? attachId };
|
|
4151
|
+
}
|
|
4152
|
+
|
|
4153
|
+
function rebaseCrossFieldKeys(
|
|
4154
|
+
sourceTable: CrossFieldKeyTable,
|
|
4155
|
+
movedDetaches: ChangeAtomIdRangeMap<boolean>,
|
|
4156
|
+
newDetachLocations: ChangeAtomIdRangeMap<FieldId>,
|
|
4157
|
+
): CrossFieldKeyTable {
|
|
4158
|
+
const rebasedTable = sourceTable.clone();
|
|
4159
|
+
for (const entry of movedDetaches.entries()) {
|
|
4160
|
+
rebasedTable.delete({ ...entry.start, target: CrossFieldTarget.Source }, entry.length);
|
|
4161
|
+
}
|
|
4162
|
+
|
|
4163
|
+
for (const entry of newDetachLocations.entries()) {
|
|
4164
|
+
rebasedTable.set(
|
|
4165
|
+
{ ...entry.start, target: CrossFieldTarget.Source },
|
|
4166
|
+
entry.length,
|
|
4167
|
+
entry.value,
|
|
4168
|
+
);
|
|
4169
|
+
}
|
|
4170
|
+
|
|
4171
|
+
return rebasedTable;
|
|
4172
|
+
}
|
|
4173
|
+
|
|
4174
|
+
export function newRootTable(): RootNodeTable {
|
|
4175
|
+
return {
|
|
4176
|
+
newToOldId: newChangeAtomIdTransform(),
|
|
4177
|
+
oldToNewId: newChangeAtomIdTransform(),
|
|
4178
|
+
nodeChanges: newTupleBTree(),
|
|
4179
|
+
detachLocations: newChangeAtomIdRangeMap(),
|
|
4180
|
+
outputDetachLocations: newChangeAtomIdRangeMap(),
|
|
4181
|
+
};
|
|
4182
|
+
}
|
|
4183
|
+
|
|
4184
|
+
function rebaseRoots(
|
|
4185
|
+
change: ModularChangeset,
|
|
4186
|
+
base: ModularChangeset,
|
|
4187
|
+
affectedBaseFields: TupleBTree<FieldIdKey, boolean>,
|
|
4188
|
+
nodesToRebase: [newChangeset: NodeId, baseChangeset: NodeId][],
|
|
4189
|
+
rebasedNodeToParent: ChangeAtomIdBTree<NodeLocation>,
|
|
4190
|
+
rebaseVersion: RebaseVersion,
|
|
4191
|
+
): RootNodeTable {
|
|
4192
|
+
const rebasedRoots = newRootTable();
|
|
4193
|
+
for (const renameEntry of change.rootNodes.oldToNewId.entries()) {
|
|
4194
|
+
rebaseRename(change.rootNodes, rebasedRoots, renameEntry, base, affectedBaseFields);
|
|
4195
|
+
}
|
|
4196
|
+
|
|
4197
|
+
for (const [detachIdKey, nodeId] of change.rootNodes.nodeChanges.entries()) {
|
|
4198
|
+
const changes = base.rootNodes.nodeChanges.get(detachIdKey);
|
|
4199
|
+
if (changes !== undefined) {
|
|
4200
|
+
nodesToRebase.push([nodeId, changes]);
|
|
4201
|
+
}
|
|
4202
|
+
|
|
4203
|
+
const detachId = makeChangeAtomId(detachIdKey[1], detachIdKey[0]);
|
|
4204
|
+
const attachId = firstAttachIdFromDetachId(base.rootNodes, detachId, 1).value;
|
|
4205
|
+
const baseAttachEntry = base.crossFieldKeys.getFirst(
|
|
4206
|
+
{ target: CrossFieldTarget.Destination, ...attachId },
|
|
4207
|
+
1,
|
|
4208
|
+
);
|
|
4209
|
+
if (baseAttachEntry.value !== undefined) {
|
|
4210
|
+
affectedBaseFields.set(fieldIdKeyFromFieldId(baseAttachEntry.value), true);
|
|
4211
|
+
rebasedNodeToParent.delete(detachIdKey);
|
|
4212
|
+
} else {
|
|
4213
|
+
const renamedDetachId = firstAttachIdFromDetachId(base.rootNodes, detachId, 1).value;
|
|
4214
|
+
const baseOutputDetachLocation = base.rootNodes.outputDetachLocations.getFirst(
|
|
4215
|
+
renamedDetachId,
|
|
4216
|
+
1,
|
|
4217
|
+
).value;
|
|
4218
|
+
|
|
4219
|
+
if (baseOutputDetachLocation !== undefined) {
|
|
4220
|
+
affectedBaseFields.set(fieldIdKeyFromFieldId(baseOutputDetachLocation), true);
|
|
4221
|
+
}
|
|
4222
|
+
|
|
4223
|
+
const detachLocation =
|
|
4224
|
+
baseOutputDetachLocation ??
|
|
4225
|
+
change.rootNodes.detachLocations.getFirst(detachId, 1).value;
|
|
4226
|
+
|
|
4227
|
+
// Note that `baseOutputDetachLocation` may contain a node ID from the base changeset.
|
|
4228
|
+
// We will replace the detach location entry with the node ID from the rebased changeset in `fixupRebasedDetachLocations`
|
|
4229
|
+
assignRootChange(
|
|
4230
|
+
rebasedRoots,
|
|
4231
|
+
rebasedNodeToParent,
|
|
4232
|
+
renamedDetachId,
|
|
4233
|
+
nodeId,
|
|
4234
|
+
detachLocation,
|
|
4235
|
+
rebaseVersion,
|
|
4236
|
+
);
|
|
4237
|
+
}
|
|
4238
|
+
}
|
|
4239
|
+
|
|
4240
|
+
for (const entry of change.rootNodes.outputDetachLocations.entries()) {
|
|
4241
|
+
rebasedRoots.outputDetachLocations.set(entry.start, entry.length, entry.value);
|
|
4242
|
+
}
|
|
4243
|
+
|
|
4244
|
+
return rebasedRoots;
|
|
4245
|
+
}
|
|
4246
|
+
|
|
4247
|
+
function rebaseRename(
|
|
4248
|
+
newRoots: RootNodeTable,
|
|
4249
|
+
rebasedRoots: RootNodeTable,
|
|
4250
|
+
renameEntry: RangeQueryEntry<ChangeAtomId, ChangeAtomId>,
|
|
4251
|
+
base: ModularChangeset,
|
|
4252
|
+
affectedBaseFields: TupleBTree<FieldIdKey, boolean>,
|
|
4253
|
+
): void {
|
|
4254
|
+
let count = renameEntry.length;
|
|
4255
|
+
const baseRenameEntry = firstAttachIdFromDetachId(base.rootNodes, renameEntry.start, count);
|
|
4256
|
+
count = baseRenameEntry.length;
|
|
4257
|
+
|
|
4258
|
+
const baseAttachEntry = base.crossFieldKeys.getFirst(
|
|
4259
|
+
{
|
|
4260
|
+
...baseRenameEntry.value,
|
|
4261
|
+
target: CrossFieldTarget.Destination,
|
|
4262
|
+
},
|
|
4263
|
+
count,
|
|
4264
|
+
);
|
|
4265
|
+
|
|
4266
|
+
count = baseAttachEntry.length;
|
|
4267
|
+
|
|
4268
|
+
if (baseAttachEntry.value !== undefined) {
|
|
4269
|
+
// This rename represents an intention to detach these nodes.
|
|
4270
|
+
// The rebased change should have a detach in the field where the base change attaches the nodes,
|
|
4271
|
+
// so we need to ensure that field is processed.
|
|
4272
|
+
affectedBaseFields.set(
|
|
4273
|
+
fieldIdKeyFromFieldId(normalizeFieldId(baseAttachEntry.value, base.nodeAliases)),
|
|
4274
|
+
true,
|
|
4275
|
+
);
|
|
4276
|
+
} else {
|
|
4277
|
+
const baseOutputDetachLocation = base.rootNodes.outputDetachLocations.getFirst(
|
|
4278
|
+
baseRenameEntry.value,
|
|
4279
|
+
1,
|
|
4280
|
+
).value;
|
|
4281
|
+
|
|
4282
|
+
if (baseOutputDetachLocation !== undefined) {
|
|
4283
|
+
affectedBaseFields.set(fieldIdKeyFromFieldId(baseOutputDetachLocation), true);
|
|
4284
|
+
}
|
|
4285
|
+
|
|
4286
|
+
const detachEntry = newRoots.detachLocations.getFirst(renameEntry.start, count);
|
|
4287
|
+
count = detachEntry.length;
|
|
4288
|
+
|
|
4289
|
+
const detachLocation = baseOutputDetachLocation ?? detachEntry.value;
|
|
4290
|
+
|
|
4291
|
+
// Note that `baseOutputDetachLocation` may contain a node ID from the base changeset.
|
|
4292
|
+
// We will replace the detach location entry with the node ID from the rebased changeset in `fixupRebasedDetachLocations`
|
|
4293
|
+
addNodeRename(
|
|
4294
|
+
rebasedRoots,
|
|
4295
|
+
baseRenameEntry.value,
|
|
4296
|
+
renameEntry.value,
|
|
4297
|
+
count,
|
|
4298
|
+
detachLocation,
|
|
4299
|
+
);
|
|
4300
|
+
}
|
|
4301
|
+
|
|
4302
|
+
const countRemaining = renameEntry.length - count;
|
|
4303
|
+
if (countRemaining > 0) {
|
|
4304
|
+
rebaseRename(
|
|
4305
|
+
newRoots,
|
|
4306
|
+
rebasedRoots,
|
|
4307
|
+
{
|
|
4308
|
+
start: offsetChangeAtomId(renameEntry.start, count),
|
|
4309
|
+
value: offsetChangeAtomId(renameEntry.value, count),
|
|
4310
|
+
length: countRemaining,
|
|
4311
|
+
},
|
|
4312
|
+
base,
|
|
4313
|
+
affectedBaseFields,
|
|
4314
|
+
);
|
|
4315
|
+
}
|
|
4316
|
+
}
|
|
4317
|
+
|
|
4318
|
+
/**
|
|
4319
|
+
* For each root detach location, replaces any node ID from the base changeset
|
|
4320
|
+
* with the corresponding ID in the new changeset.
|
|
4321
|
+
*/
|
|
4322
|
+
function fixupRebasedDetachLocations(table: RebaseTable): void {
|
|
4323
|
+
for (const {
|
|
4324
|
+
start,
|
|
4325
|
+
length,
|
|
4326
|
+
value: detachLocation,
|
|
4327
|
+
} of table.rebasedRootNodes.detachLocations.entries()) {
|
|
4328
|
+
const normalizedDetachLocation = normalizeFieldId(
|
|
4329
|
+
detachLocation,
|
|
4330
|
+
table.baseChange.nodeAliases,
|
|
4331
|
+
);
|
|
4332
|
+
|
|
4333
|
+
if (normalizedDetachLocation.nodeId !== undefined) {
|
|
4334
|
+
const rebasedNodeId = getFromChangeAtomIdMap(
|
|
4335
|
+
table.baseToRebasedNodeId,
|
|
4336
|
+
normalizedDetachLocation.nodeId,
|
|
4337
|
+
);
|
|
4338
|
+
|
|
4339
|
+
if (rebasedNodeId !== undefined) {
|
|
4340
|
+
table.rebasedRootNodes.detachLocations.set(start, length, {
|
|
4341
|
+
...normalizedDetachLocation,
|
|
4342
|
+
nodeId: rebasedNodeId,
|
|
4343
|
+
});
|
|
4344
|
+
}
|
|
4345
|
+
}
|
|
4346
|
+
}
|
|
4347
|
+
}
|
|
4348
|
+
|
|
4349
|
+
function addNodesToCompose(table: ComposeTable, id1: NodeId, id2: NodeId): void {
|
|
4350
|
+
const normalizedId1 = normalizeNodeId(id1, table.baseChange.nodeAliases);
|
|
4351
|
+
const normalizedId2 = normalizeNodeId(id2, table.newChange.nodeAliases);
|
|
4352
|
+
if (getFromChangeAtomIdMap(table.newToBaseNodeId, normalizedId2) === undefined) {
|
|
4353
|
+
setInChangeAtomIdMap(table.newToBaseNodeId, normalizedId2, normalizedId1);
|
|
4354
|
+
table.pendingCompositions.nodeIdsToCompose.push([normalizedId1, normalizedId2]);
|
|
4355
|
+
}
|
|
4356
|
+
}
|
|
4357
|
+
|
|
4358
|
+
function composeRevInfos(
|
|
4359
|
+
revisions1: readonly RevisionInfo[] | undefined,
|
|
4360
|
+
revisions2: readonly RevisionInfo[] | undefined,
|
|
4361
|
+
): RevisionInfo[] {
|
|
4362
|
+
const result: RevisionInfo[] = [...(revisions1 ?? []), ...(revisions2 ?? [])];
|
|
4363
|
+
return result;
|
|
4364
|
+
}
|
|
4365
|
+
|
|
4366
|
+
function composeCrossFieldKeyTables(
|
|
4367
|
+
table1: CrossFieldKeyTable,
|
|
4368
|
+
table2: CrossFieldKeyTable,
|
|
4369
|
+
movedCrossFieldKeys: CrossFieldKeyTable,
|
|
4370
|
+
removedCrossFieldKeys: CrossFieldRangeTable<boolean>,
|
|
4371
|
+
): CrossFieldKeyTable {
|
|
4372
|
+
const composedTable = RangeMap.union(table1, table2);
|
|
4373
|
+
for (const entry of movedCrossFieldKeys.entries()) {
|
|
4374
|
+
composedTable.set(entry.start, entry.length, entry.value);
|
|
4375
|
+
}
|
|
4376
|
+
|
|
4377
|
+
for (const entry of removedCrossFieldKeys.entries()) {
|
|
4378
|
+
composedTable.delete(entry.start, entry.length);
|
|
4379
|
+
}
|
|
4380
|
+
|
|
4381
|
+
return composedTable;
|
|
4382
|
+
}
|
|
4383
|
+
|
|
4384
|
+
function composeRootTables(
|
|
4385
|
+
change1: ModularChangeset,
|
|
4386
|
+
change2: ModularChangeset,
|
|
4387
|
+
composedNodeToParent: ChangeAtomIdBTree<NodeLocation>,
|
|
4388
|
+
movedCrossFieldKeys: CrossFieldKeyTable,
|
|
4389
|
+
removedCrossFieldKeys: CrossFieldRangeTable<boolean>,
|
|
4390
|
+
pendingCompositions: PendingCompositions,
|
|
4391
|
+
): RootNodeTable {
|
|
4392
|
+
const composedTable = cloneRootTable(change1.rootNodes);
|
|
4393
|
+
|
|
4394
|
+
for (const renameEntry of change2.rootNodes.oldToNewId.entries()) {
|
|
4395
|
+
composeRename(
|
|
4396
|
+
change1,
|
|
4397
|
+
change2,
|
|
4398
|
+
composedTable,
|
|
4399
|
+
renameEntry.start,
|
|
4400
|
+
renameEntry.value,
|
|
4401
|
+
renameEntry.length,
|
|
4402
|
+
movedCrossFieldKeys,
|
|
4403
|
+
removedCrossFieldKeys,
|
|
4404
|
+
pendingCompositions,
|
|
4405
|
+
);
|
|
4406
|
+
}
|
|
4407
|
+
|
|
4408
|
+
for (const [[revision2, id2], nodeId2] of change2.rootNodes.nodeChanges.entries()) {
|
|
4409
|
+
const detachId2 = { revision: revision2, localId: id2 };
|
|
4410
|
+
const detachId1 = firstDetachIdFromAttachId(change1.rootNodes, detachId2, 1).value;
|
|
4411
|
+
const nodeId1 = getFromChangeAtomIdMap(change1.rootNodes.nodeChanges, detachId1);
|
|
4412
|
+
|
|
4413
|
+
if (nodeId1 !== undefined) {
|
|
4414
|
+
pendingCompositions.nodeIdsToCompose.push([nodeId1, nodeId2]);
|
|
4415
|
+
} else {
|
|
4416
|
+
const fieldId = getFieldsForCrossFieldKey(
|
|
4417
|
+
change1,
|
|
4418
|
+
{ ...detachId1, target: CrossFieldTarget.Source },
|
|
4419
|
+
1,
|
|
4420
|
+
)[0];
|
|
4421
|
+
|
|
4422
|
+
if (fieldId !== undefined) {
|
|
4423
|
+
// In this case, this node is attached in the input context of change1,
|
|
4424
|
+
// and is represented in detachFieldId.
|
|
4425
|
+
pendingCompositions.affectedBaseFields.set(
|
|
4426
|
+
[fieldId.nodeId?.revision, fieldId.nodeId?.localId, fieldId.field],
|
|
4427
|
+
true,
|
|
4428
|
+
);
|
|
4429
|
+
} else {
|
|
4430
|
+
assignRootChange(
|
|
4431
|
+
composedTable,
|
|
4432
|
+
composedNodeToParent,
|
|
4433
|
+
detachId1,
|
|
4434
|
+
nodeId2,
|
|
4435
|
+
change1.rootNodes.detachLocations.getFirst(detachId1, 1).value ??
|
|
4436
|
+
change2.rootNodes.detachLocations.getFirst(detachId2, 1).value,
|
|
4437
|
+
Math.max(change1.rebaseVersion, change2.rebaseVersion) as RebaseVersion,
|
|
4438
|
+
);
|
|
4439
|
+
}
|
|
4440
|
+
}
|
|
4441
|
+
}
|
|
4442
|
+
|
|
4443
|
+
for (const outputDetachEntry of change1.rootNodes.outputDetachLocations.entries()) {
|
|
4444
|
+
composeOutputDetachLocation(
|
|
4445
|
+
outputDetachEntry.start,
|
|
4446
|
+
outputDetachEntry.length,
|
|
4447
|
+
outputDetachEntry.value,
|
|
4448
|
+
change2,
|
|
4449
|
+
composedTable,
|
|
4450
|
+
);
|
|
4451
|
+
}
|
|
4452
|
+
|
|
4453
|
+
for (const entry of change2.rootNodes.outputDetachLocations.entries()) {
|
|
4454
|
+
composedTable.outputDetachLocations.set(entry.start, entry.length, entry.value);
|
|
4455
|
+
}
|
|
4456
|
+
|
|
4457
|
+
return composedTable;
|
|
4458
|
+
}
|
|
4459
|
+
|
|
4460
|
+
function composeOutputDetachLocation(
|
|
4461
|
+
outputDetachId1: ChangeAtomId,
|
|
4462
|
+
count: number,
|
|
4463
|
+
detachLocation: FieldId,
|
|
4464
|
+
change2: ModularChangeset,
|
|
4465
|
+
composedTable: RootNodeTable,
|
|
4466
|
+
): void {
|
|
4467
|
+
let countToProcess = count;
|
|
4468
|
+
const renameEntry = firstAttachIdFromDetachId(
|
|
4469
|
+
change2.rootNodes,
|
|
4470
|
+
outputDetachId1,
|
|
4471
|
+
countToProcess,
|
|
4472
|
+
);
|
|
4473
|
+
countToProcess = renameEntry.length;
|
|
4474
|
+
|
|
4475
|
+
const attachEntry = getFirstAttachField(
|
|
4476
|
+
change2.crossFieldKeys,
|
|
4477
|
+
renameEntry.value,
|
|
4478
|
+
countToProcess,
|
|
4479
|
+
);
|
|
4480
|
+
countToProcess = attachEntry.length;
|
|
4481
|
+
|
|
4482
|
+
composedTable.outputDetachLocations.delete(outputDetachId1, countToProcess);
|
|
4483
|
+
|
|
4484
|
+
if (attachEntry.value === undefined) {
|
|
4485
|
+
// We update the key for the detach location to the renamed ID of the root in the composed output context.
|
|
4486
|
+
composedTable.outputDetachLocations.set(renameEntry.value, countToProcess, detachLocation);
|
|
4487
|
+
} else {
|
|
4488
|
+
// These nodes are attached by `change2` and thus attached in the composed output context,
|
|
4489
|
+
// so there should be no output detach location.
|
|
4490
|
+
}
|
|
4491
|
+
|
|
4492
|
+
const countRemaining = count - countToProcess;
|
|
4493
|
+
if (countRemaining > 0) {
|
|
4494
|
+
composeOutputDetachLocation(
|
|
4495
|
+
offsetChangeAtomId(outputDetachId1, countToProcess),
|
|
4496
|
+
countRemaining,
|
|
4497
|
+
detachLocation,
|
|
4498
|
+
change2,
|
|
4499
|
+
composedTable,
|
|
4500
|
+
);
|
|
4501
|
+
}
|
|
4502
|
+
}
|
|
4503
|
+
|
|
4504
|
+
function composeRename(
|
|
4505
|
+
change1: ModularChangeset,
|
|
4506
|
+
change2: ModularChangeset,
|
|
4507
|
+
mergedTable: RootNodeTable,
|
|
4508
|
+
oldId: ChangeAtomId,
|
|
4509
|
+
newId: ChangeAtomId,
|
|
4510
|
+
count: number,
|
|
4511
|
+
movedCrossFieldKeys: CrossFieldKeyTable,
|
|
4512
|
+
removedCrossFieldKeys: CrossFieldRangeTable<boolean>,
|
|
4513
|
+
pendingCompositions: PendingCompositions,
|
|
4514
|
+
): void {
|
|
4515
|
+
let countToProcess = count;
|
|
4516
|
+
const detachEntry = getFirstDetachField(change1.crossFieldKeys, oldId, countToProcess);
|
|
4517
|
+
countToProcess = detachEntry.length;
|
|
4518
|
+
|
|
4519
|
+
if (detachEntry.value !== undefined) {
|
|
4520
|
+
// `change1` detached these nodes,
|
|
4521
|
+
// so we invalidate the detach location so that the detach's ID can be replaced with the new ID.
|
|
4522
|
+
pendingCompositions.affectedBaseFields.set(fieldIdKeyFromFieldId(detachEntry.value), true);
|
|
4523
|
+
|
|
4524
|
+
if (!areEqualChangeAtomIds(oldId, newId)) {
|
|
4525
|
+
// `change1`'s detach will be replaced by `change2`'s detach, so we update the cross-field keys.
|
|
4526
|
+
removedCrossFieldKeys.set(
|
|
4527
|
+
{ ...oldId, target: CrossFieldTarget.Source },
|
|
4528
|
+
countToProcess,
|
|
4529
|
+
true,
|
|
4530
|
+
);
|
|
4531
|
+
}
|
|
4532
|
+
|
|
4533
|
+
movedCrossFieldKeys.set(
|
|
4534
|
+
{ ...newId, target: CrossFieldTarget.Source },
|
|
4535
|
+
countToProcess,
|
|
4536
|
+
detachEntry.value,
|
|
4537
|
+
);
|
|
4538
|
+
} else {
|
|
4539
|
+
// `change1` may also have a rename to `renameEntry.value`, in which case it must refer to a different node.
|
|
4540
|
+
// That node must have been attached by `change1` and detached by `change2`.
|
|
4541
|
+
// The final rename for that node will be created in `composeAttachDetach`.
|
|
4542
|
+
// We delete any such rename for now to avoid colliding with the rename currently being processed.
|
|
4543
|
+
deleteNodeRenameTo(mergedTable, newId, countToProcess);
|
|
4544
|
+
|
|
4545
|
+
// The nodes were detached before `change`, so we append this rename.
|
|
4546
|
+
appendNodeRename(
|
|
4547
|
+
mergedTable,
|
|
4548
|
+
oldId,
|
|
4549
|
+
newId,
|
|
4550
|
+
countToProcess,
|
|
4551
|
+
change1.rootNodes,
|
|
4552
|
+
change2.rootNodes.detachLocations.getFirst(oldId, countToProcess).value,
|
|
4553
|
+
);
|
|
4554
|
+
}
|
|
4555
|
+
|
|
4556
|
+
if (countToProcess < count) {
|
|
4557
|
+
composeRename(
|
|
4558
|
+
change1,
|
|
4559
|
+
change2,
|
|
4560
|
+
mergedTable,
|
|
4561
|
+
offsetChangeAtomId(oldId, countToProcess),
|
|
4562
|
+
offsetChangeAtomId(newId, countToProcess),
|
|
4563
|
+
count - countToProcess,
|
|
4564
|
+
movedCrossFieldKeys,
|
|
4565
|
+
removedCrossFieldKeys,
|
|
4566
|
+
pendingCompositions,
|
|
4567
|
+
);
|
|
4568
|
+
}
|
|
4569
|
+
}
|
|
4570
|
+
|
|
4571
|
+
export function cloneRootTable(table: RootNodeTable): RootNodeTable {
|
|
4572
|
+
return {
|
|
4573
|
+
oldToNewId: table.oldToNewId.clone(),
|
|
4574
|
+
newToOldId: table.newToOldId.clone(),
|
|
4575
|
+
nodeChanges: brand(table.nodeChanges.clone()),
|
|
4576
|
+
detachLocations: table.detachLocations.clone(),
|
|
4577
|
+
outputDetachLocations: table.outputDetachLocations.clone(),
|
|
4578
|
+
};
|
|
4579
|
+
}
|
|
4580
|
+
|
|
4581
|
+
function invertRootTable(change: ModularChangeset, isRollback: boolean): RootNodeTable {
|
|
4582
|
+
const invertedRoots: RootNodeTable = newRootTable();
|
|
4583
|
+
for (const [[revision, localId], nodeId] of change.rootNodes.nodeChanges.entries()) {
|
|
4584
|
+
const detachId: ChangeAtomId = { revision, localId };
|
|
4585
|
+
const renamedId = firstAttachIdFromDetachId(change.rootNodes, detachId, 1).value;
|
|
4586
|
+
|
|
4587
|
+
// This checks whether `change` attaches this node.
|
|
4588
|
+
// 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.
|
|
4589
|
+
if (
|
|
4590
|
+
change.crossFieldKeys.getFirst({ ...renamedId, target: CrossFieldTarget.Destination }, 1)
|
|
4591
|
+
.value === undefined
|
|
4592
|
+
) {
|
|
4593
|
+
assignRootChange(
|
|
4594
|
+
invertedRoots,
|
|
4595
|
+
undefined,
|
|
4596
|
+
renamedId,
|
|
4597
|
+
nodeId,
|
|
4598
|
+
change.rootNodes.detachLocations.getFirst(detachId, 1).value,
|
|
4599
|
+
change.rebaseVersion,
|
|
4600
|
+
);
|
|
4601
|
+
}
|
|
4602
|
+
}
|
|
4603
|
+
|
|
4604
|
+
if (isRollback) {
|
|
4605
|
+
// We only invert renames of nodes which are not attached or detached by this changeset.
|
|
4606
|
+
// When we invert an attach we will create a detach which incorporates the rename.
|
|
4607
|
+
for (const {
|
|
4608
|
+
start: oldId,
|
|
4609
|
+
value: newId,
|
|
4610
|
+
length,
|
|
4611
|
+
} of change.rootNodes.oldToNewId.entries()) {
|
|
4612
|
+
invertRename(change, invertedRoots, oldId, newId, length);
|
|
4613
|
+
}
|
|
4614
|
+
}
|
|
4615
|
+
|
|
4616
|
+
return invertedRoots;
|
|
4617
|
+
}
|
|
4618
|
+
|
|
4619
|
+
function invertRename(
|
|
4620
|
+
change: ModularChangeset,
|
|
4621
|
+
invertedRoots: RootNodeTable,
|
|
4622
|
+
oldId: ChangeAtomId,
|
|
4623
|
+
newId: ChangeAtomId,
|
|
4624
|
+
length: number,
|
|
4625
|
+
): void {
|
|
4626
|
+
for (const detachEntry of doesChangeDetachNodes(change.crossFieldKeys, newId, length)) {
|
|
4627
|
+
assert(
|
|
4628
|
+
!detachEntry.value,
|
|
4629
|
+
"A changeset should not have a rename and detach for the same node.",
|
|
4630
|
+
);
|
|
4631
|
+
}
|
|
4632
|
+
|
|
4633
|
+
let countProcessed = length;
|
|
4634
|
+
const attachEntry = getFirstAttachField(change.crossFieldKeys, newId, countProcessed);
|
|
4635
|
+
countProcessed = attachEntry.length;
|
|
4636
|
+
if (attachEntry.value === undefined) {
|
|
4637
|
+
const outputDetachEntry = change.rootNodes.outputDetachLocations.getFirst(
|
|
4638
|
+
newId,
|
|
4639
|
+
countProcessed,
|
|
4640
|
+
);
|
|
4641
|
+
countProcessed = outputDetachEntry.length;
|
|
4642
|
+
|
|
4643
|
+
const inputDetachEntry = change.rootNodes.detachLocations.getFirst(oldId, countProcessed);
|
|
4644
|
+
countProcessed = inputDetachEntry.length;
|
|
4645
|
+
|
|
4646
|
+
addNodeRename(
|
|
4647
|
+
invertedRoots,
|
|
4648
|
+
newId,
|
|
4649
|
+
oldId,
|
|
4650
|
+
countProcessed,
|
|
4651
|
+
outputDetachEntry.value ?? inputDetachEntry.value,
|
|
4652
|
+
);
|
|
4653
|
+
}
|
|
4654
|
+
|
|
4655
|
+
if (countProcessed < length) {
|
|
4656
|
+
invertRename(
|
|
4657
|
+
change,
|
|
4658
|
+
invertedRoots,
|
|
4659
|
+
offsetChangeAtomId(oldId, countProcessed),
|
|
4660
|
+
offsetChangeAtomId(newId, countProcessed),
|
|
4661
|
+
length - countProcessed,
|
|
4662
|
+
);
|
|
4663
|
+
}
|
|
4664
|
+
}
|
|
4665
|
+
|
|
4666
|
+
function doesChangeAttachNodes(
|
|
4667
|
+
table: CrossFieldKeyTable,
|
|
4668
|
+
id: ChangeAtomId,
|
|
4669
|
+
count: number,
|
|
4670
|
+
): RangeQueryResultFragment<boolean>[] {
|
|
4671
|
+
return table
|
|
4672
|
+
.getAll2({ ...id, target: CrossFieldTarget.Destination }, count)
|
|
4673
|
+
.map((entry) => ({ ...entry, value: entry.value !== undefined }));
|
|
4674
|
+
}
|
|
4675
|
+
|
|
4676
|
+
function doesChangeDetachNodes(
|
|
4677
|
+
table: CrossFieldKeyTable,
|
|
4678
|
+
id: ChangeAtomId,
|
|
4679
|
+
count: number,
|
|
4680
|
+
): RangeQueryResultFragment<boolean>[] {
|
|
4681
|
+
return table
|
|
4682
|
+
.getAll2({ ...id, target: CrossFieldTarget.Source }, count)
|
|
4683
|
+
.map((entry) => ({ ...entry, value: entry.value !== undefined }));
|
|
4684
|
+
}
|
|
4685
|
+
|
|
4686
|
+
export function getFirstDetachField(
|
|
4687
|
+
table: CrossFieldKeyTable,
|
|
4688
|
+
id: ChangeAtomId,
|
|
4689
|
+
count: number,
|
|
4690
|
+
): RangeQueryResult<FieldId | undefined> {
|
|
4691
|
+
return table.getFirst({ target: CrossFieldTarget.Source, ...id }, count);
|
|
4692
|
+
}
|
|
4693
|
+
|
|
4694
|
+
export function getFirstAttachField(
|
|
4695
|
+
table: CrossFieldKeyTable,
|
|
4696
|
+
id: ChangeAtomId,
|
|
4697
|
+
count: number,
|
|
4698
|
+
): RangeQueryResult<FieldId | undefined> {
|
|
4699
|
+
return table.getFirst({ target: CrossFieldTarget.Destination, ...id }, count);
|
|
4700
|
+
}
|
|
4701
|
+
|
|
4702
|
+
export function addNodeRename(
|
|
4703
|
+
table: RootNodeTable,
|
|
4704
|
+
oldId: ChangeAtomId,
|
|
4705
|
+
newId: ChangeAtomId,
|
|
4706
|
+
count: number,
|
|
4707
|
+
detachLocation: FieldId | undefined,
|
|
4708
|
+
): void {
|
|
4709
|
+
if (areEqualChangeAtomIds(oldId, newId)) {
|
|
4710
|
+
return;
|
|
4711
|
+
}
|
|
4712
|
+
|
|
4713
|
+
for (const entry of table.oldToNewId.getAll2(oldId, count)) {
|
|
4714
|
+
assert(
|
|
4715
|
+
entry.value === undefined ||
|
|
4716
|
+
areEqualChangeAtomIds(entry.value, offsetChangeAtomId(newId, entry.offset)),
|
|
4717
|
+
"Rename collision detected",
|
|
4718
|
+
);
|
|
4719
|
+
}
|
|
4720
|
+
|
|
4721
|
+
for (const entry of table.newToOldId.getAll2(newId, count)) {
|
|
4722
|
+
assert(
|
|
4723
|
+
entry.value === undefined ||
|
|
4724
|
+
areEqualChangeAtomIds(entry.value, offsetChangeAtomId(oldId, entry.offset)),
|
|
4725
|
+
"Rename collision detected",
|
|
4726
|
+
);
|
|
4727
|
+
}
|
|
4728
|
+
|
|
4729
|
+
table.oldToNewId.set(oldId, count, newId);
|
|
4730
|
+
table.newToOldId.set(newId, count, oldId);
|
|
4731
|
+
|
|
4732
|
+
if (detachLocation !== undefined) {
|
|
4733
|
+
table.detachLocations.set(oldId, count, detachLocation);
|
|
4734
|
+
}
|
|
4735
|
+
}
|
|
4736
|
+
|
|
4737
|
+
/**
|
|
4738
|
+
* Deletes any renames from `id`.
|
|
4739
|
+
*/
|
|
4740
|
+
function deleteNodeRenameFrom(roots: RootNodeTable, id: ChangeAtomId, count: number): void {
|
|
4741
|
+
for (const entry of roots.oldToNewId.getAll(id, count)) {
|
|
4742
|
+
deleteNodeRenameEntry(roots, entry.start, entry.value, entry.length);
|
|
4743
|
+
}
|
|
4744
|
+
}
|
|
4745
|
+
|
|
4746
|
+
/**
|
|
4747
|
+
* Deletes any renames to `id`.
|
|
4748
|
+
*/
|
|
4749
|
+
function deleteNodeRenameTo(roots: RootNodeTable, id: ChangeAtomId, count: number): void {
|
|
4750
|
+
for (const entry of roots.newToOldId.getAll(id, count)) {
|
|
4751
|
+
deleteNodeRenameEntry(roots, entry.value, entry.start, entry.length);
|
|
4752
|
+
}
|
|
4753
|
+
}
|
|
4754
|
+
|
|
4755
|
+
function appendNodeRename(
|
|
4756
|
+
composedTable: RootNodeTable,
|
|
4757
|
+
oldId: ChangeAtomId,
|
|
4758
|
+
newId: ChangeAtomId,
|
|
4759
|
+
count: number,
|
|
4760
|
+
change1Table: RootNodeTable,
|
|
4761
|
+
detachLocation: FieldId | undefined,
|
|
4762
|
+
): void {
|
|
4763
|
+
let countToProcess = count;
|
|
4764
|
+
const rename1Entry = change1Table.newToOldId.getFirst(oldId, countToProcess);
|
|
4765
|
+
countToProcess = rename1Entry.length;
|
|
4766
|
+
|
|
4767
|
+
if (rename1Entry.value !== undefined) {
|
|
4768
|
+
deleteNodeRenameFrom(composedTable, rename1Entry.value, countToProcess);
|
|
4769
|
+
}
|
|
4770
|
+
|
|
4771
|
+
addNodeRename(
|
|
4772
|
+
composedTable,
|
|
4773
|
+
rename1Entry.value ?? oldId,
|
|
4774
|
+
newId,
|
|
4775
|
+
countToProcess,
|
|
4776
|
+
detachLocation,
|
|
4777
|
+
);
|
|
4778
|
+
|
|
4779
|
+
tryRemoveDetachLocation(composedTable, newId, countToProcess);
|
|
4780
|
+
|
|
4781
|
+
if (countToProcess < count) {
|
|
4782
|
+
const countRemaining = count - countToProcess;
|
|
4783
|
+
appendNodeRename(
|
|
4784
|
+
composedTable,
|
|
4785
|
+
offsetChangeAtomId(oldId, countToProcess),
|
|
4786
|
+
offsetChangeAtomId(newId, countToProcess),
|
|
4787
|
+
countRemaining,
|
|
4788
|
+
change1Table,
|
|
4789
|
+
detachLocation,
|
|
4790
|
+
);
|
|
4791
|
+
}
|
|
4792
|
+
}
|
|
4793
|
+
|
|
4794
|
+
function tryRemoveDetachLocation(
|
|
4795
|
+
roots: RootNodeTable,
|
|
4796
|
+
rootId: ChangeAtomId,
|
|
4797
|
+
count: number,
|
|
4798
|
+
): void {
|
|
4799
|
+
let countProcessed = count;
|
|
4800
|
+
const renameEntry = roots.oldToNewId.getFirst(rootId, countProcessed);
|
|
4801
|
+
countProcessed = renameEntry.length;
|
|
4802
|
+
|
|
4803
|
+
const outputDetachEntry = roots.outputDetachLocations.getFirst(rootId, countProcessed);
|
|
4804
|
+
countProcessed = outputDetachEntry.length;
|
|
4805
|
+
|
|
4806
|
+
const nodeChangeEntry = rangeQueryChangeAtomIdMap(roots.nodeChanges, rootId, countProcessed);
|
|
4807
|
+
countProcessed = nodeChangeEntry.length;
|
|
4808
|
+
|
|
4809
|
+
if (
|
|
4810
|
+
nodeChangeEntry.value === undefined &&
|
|
4811
|
+
renameEntry.value === undefined &&
|
|
4812
|
+
outputDetachEntry.value === undefined
|
|
4813
|
+
) {
|
|
4814
|
+
roots.detachLocations.delete(rootId, countProcessed);
|
|
4815
|
+
}
|
|
4816
|
+
|
|
4817
|
+
const countRemaining = count - countProcessed;
|
|
4818
|
+
if (countRemaining > 0) {
|
|
4819
|
+
tryRemoveDetachLocation(roots, offsetChangeAtomId(rootId, countProcessed), countRemaining);
|
|
4820
|
+
}
|
|
4821
|
+
}
|
|
4822
|
+
|
|
4823
|
+
/**
|
|
4824
|
+
* Deletes the entry renaming the ID range of length `count` from `oldId` to `newId`.
|
|
4825
|
+
* This function assumes that such an entry exists.
|
|
4826
|
+
*/
|
|
4827
|
+
function deleteNodeRenameEntry(
|
|
4828
|
+
roots: RootNodeTable,
|
|
4829
|
+
oldId: ChangeAtomId,
|
|
4830
|
+
newId: ChangeAtomId,
|
|
4831
|
+
count: number,
|
|
4832
|
+
): void {
|
|
4833
|
+
roots.oldToNewId.delete(oldId, count);
|
|
4834
|
+
roots.newToOldId.delete(newId, count);
|
|
4835
|
+
}
|
|
4836
|
+
|
|
4837
|
+
function replaceRootTableRevision(
|
|
4838
|
+
table: RootNodeTable,
|
|
4839
|
+
oldRevisions: Set<RevisionTag | undefined>,
|
|
4840
|
+
newRevision: RevisionTag | undefined,
|
|
4841
|
+
nodeAliases: ChangeAtomIdBTree<NodeId>,
|
|
4842
|
+
): RootNodeTable {
|
|
4843
|
+
const oldToNewId = table.oldToNewId.mapEntries(
|
|
4844
|
+
(id) => replaceAtomRevisions(id, oldRevisions, newRevision),
|
|
4845
|
+
(id) => replaceAtomRevisions(id, oldRevisions, newRevision),
|
|
4846
|
+
);
|
|
4847
|
+
|
|
4848
|
+
const newToOldId = table.newToOldId.mapEntries(
|
|
4849
|
+
(id) => replaceAtomRevisions(id, oldRevisions, newRevision),
|
|
4850
|
+
(id) => replaceAtomRevisions(id, oldRevisions, newRevision),
|
|
4851
|
+
);
|
|
4852
|
+
|
|
4853
|
+
const nodeChanges: ChangeAtomIdBTree<NodeId> = newTupleBTree(
|
|
4854
|
+
[...table.nodeChanges.entries()].map(([[revision, id], nodeId]) => [
|
|
4855
|
+
[oldRevisions.has(revision) ? newRevision : revision, id],
|
|
4856
|
+
replaceAtomRevisions(normalizeNodeId(nodeId, nodeAliases), oldRevisions, newRevision),
|
|
4857
|
+
]),
|
|
4858
|
+
);
|
|
4859
|
+
|
|
4860
|
+
const detachLocations = table.detachLocations.mapEntries(
|
|
4861
|
+
(id) => replaceAtomRevisions(id, oldRevisions, newRevision),
|
|
4862
|
+
(fieldId) =>
|
|
4863
|
+
replaceFieldIdRevision(
|
|
4864
|
+
normalizeFieldId(fieldId, nodeAliases),
|
|
4865
|
+
oldRevisions,
|
|
4866
|
+
newRevision,
|
|
4867
|
+
),
|
|
4868
|
+
);
|
|
4869
|
+
|
|
4870
|
+
const outputDetachLocations = table.outputDetachLocations.mapEntries(
|
|
4871
|
+
(id) => replaceAtomRevisions(id, oldRevisions, newRevision),
|
|
4872
|
+
(fieldId) =>
|
|
4873
|
+
replaceFieldIdRevision(
|
|
4874
|
+
normalizeFieldId(fieldId, nodeAliases),
|
|
4875
|
+
oldRevisions,
|
|
4876
|
+
newRevision,
|
|
4877
|
+
),
|
|
4878
|
+
);
|
|
4879
|
+
|
|
4880
|
+
return { oldToNewId, newToOldId, nodeChanges, detachLocations, outputDetachLocations };
|
|
4881
|
+
}
|
|
4882
|
+
|
|
4883
|
+
function newDetachedEntryMap(): ChangeAtomIdRangeMap<DetachedNodeEntry> {
|
|
4884
|
+
return new RangeMap(offsetChangeAtomId, subtractChangeAtomIds, offsetDetachedNodeEntry);
|
|
4885
|
+
}
|
|
4886
|
+
|
|
4887
|
+
function offsetDetachedNodeEntry(entry: DetachedNodeEntry, count: number): DetachedNodeEntry {
|
|
4888
|
+
assert(
|
|
4889
|
+
count <= 1 || entry.nodeChange === undefined,
|
|
4890
|
+
"Cannot split an entry with a node change",
|
|
4891
|
+
);
|
|
4892
|
+
|
|
4893
|
+
return entry.detachId !== undefined
|
|
4894
|
+
? { ...entry, detachId: offsetChangeAtomId(entry.detachId, count) }
|
|
4895
|
+
: entry;
|
|
4896
|
+
}
|
|
4897
|
+
|
|
4898
|
+
function getFieldsWithRootMoves(
|
|
4899
|
+
roots: RootNodeTable,
|
|
4900
|
+
nodeAliases: ChangeAtomIdBTree<NodeId>,
|
|
4901
|
+
): TupleBTree<FieldIdKey, boolean> {
|
|
4902
|
+
const fields: TupleBTree<FieldIdKey, boolean> = newTupleBTree();
|
|
4903
|
+
for (const { start: rootId, value: fieldId, length } of roots.detachLocations.entries()) {
|
|
4904
|
+
let isRootMoved = false;
|
|
4905
|
+
for (const renameEntry of roots.oldToNewId.getAll2(rootId, length)) {
|
|
4906
|
+
if (renameEntry.value !== undefined) {
|
|
4907
|
+
isRootMoved = true;
|
|
4908
|
+
}
|
|
4909
|
+
}
|
|
4910
|
+
|
|
4911
|
+
for (const outputDetachEntry of roots.outputDetachLocations.getAll2(rootId, length)) {
|
|
4912
|
+
if (outputDetachEntry.value !== undefined) {
|
|
4913
|
+
isRootMoved = true;
|
|
4914
|
+
}
|
|
4915
|
+
}
|
|
4916
|
+
|
|
4917
|
+
if (isRootMoved) {
|
|
4918
|
+
fields.set(fieldIdKeyFromFieldId(normalizeFieldId(fieldId, nodeAliases)), true);
|
|
4919
|
+
}
|
|
4920
|
+
}
|
|
4921
|
+
|
|
4922
|
+
return fields;
|
|
4923
|
+
}
|
|
4924
|
+
|
|
4925
|
+
function getFieldToRootChanges(
|
|
4926
|
+
roots: RootNodeTable,
|
|
4927
|
+
nodeAliases: ChangeAtomIdBTree<NodeId>,
|
|
4928
|
+
): TupleBTree<FieldIdKey, ChangeAtomId[]> {
|
|
4929
|
+
const fields: TupleBTree<FieldIdKey, ChangeAtomId[]> = newTupleBTree();
|
|
4930
|
+
for (const rootIdKey of roots.nodeChanges.keys()) {
|
|
4931
|
+
const rootId: ChangeAtomId = { revision: rootIdKey[0], localId: rootIdKey[1] };
|
|
4932
|
+
const detachLocation = roots.detachLocations.getFirst(rootId, 1).value;
|
|
4933
|
+
if (detachLocation !== undefined) {
|
|
4934
|
+
const fieldIdKey = fieldIdKeyFromFieldId(normalizeFieldId(detachLocation, nodeAliases));
|
|
4935
|
+
let rootsInField = fields.get(fieldIdKey);
|
|
4936
|
+
if (rootsInField === undefined) {
|
|
4937
|
+
rootsInField = [];
|
|
4938
|
+
fields.set(fieldIdKey, rootsInField);
|
|
4939
|
+
}
|
|
4940
|
+
|
|
4941
|
+
rootsInField.push(rootId);
|
|
4942
|
+
}
|
|
4943
|
+
}
|
|
4944
|
+
|
|
4945
|
+
return fields;
|
|
4946
|
+
}
|
|
4947
|
+
|
|
4948
|
+
function muteRootChanges(roots: RootNodeTable): RootNodeTable {
|
|
4949
|
+
return {
|
|
4950
|
+
oldToNewId: newChangeAtomIdTransform(),
|
|
4951
|
+
newToOldId: newChangeAtomIdTransform(),
|
|
4952
|
+
nodeChanges: brand(roots.nodeChanges.clone()),
|
|
4953
|
+
detachLocations: roots.detachLocations.clone(),
|
|
4954
|
+
outputDetachLocations: newChangeAtomIdRangeMap(),
|
|
4955
|
+
};
|
|
3156
4956
|
}
|