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