@fluidframework/tree 2.110.0 → 2.111.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/settings.json +1 -0
- package/CHANGELOG.md +48 -0
- package/api-report/tree.alpha.api.md +48 -31
- package/api-report/tree.beta.api.md +38 -0
- package/api-report/tree.legacy.beta.api.md +38 -0
- package/dist/core/change-family/changeFamily.d.ts +3 -10
- package/dist/core/change-family/changeFamily.d.ts.map +1 -1
- package/dist/core/change-family/changeFamily.js.map +1 -1
- package/dist/core/rebase/types.d.ts +2 -2
- package/dist/core/rebase/types.js.map +1 -1
- package/dist/core/schema-stored/storedSchemaRepository.d.ts +2 -2
- package/dist/core/schema-stored/storedSchemaRepository.js.map +1 -1
- package/dist/entrypoints/alpha.d.ts +1 -1
- package/dist/entrypoints/alpha.d.ts.map +1 -1
- package/dist/entrypoints/alpha.js.map +1 -1
- package/dist/entrypoints/beta.d.ts +1 -1
- package/dist/entrypoints/beta.d.ts.map +1 -1
- package/dist/entrypoints/beta.js.map +1 -1
- package/dist/entrypoints/legacy.d.ts +1 -1
- package/dist/entrypoints/legacy.d.ts.map +1 -1
- package/dist/entrypoints/legacy.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts +19 -14
- package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.js +13 -32
- package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/codecs.d.ts +85 -28
- package/dist/feature-libraries/chunked-forest/codec/codecs.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/codecs.js +83 -9
- package/dist/feature-libraries/chunked-forest/codec/codecs.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/compressedEncode.d.ts +4 -2
- package/dist/feature-libraries/chunked-forest/codec/compressedEncode.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/compressedEncode.js +11 -0
- package/dist/feature-libraries/chunked-forest/codec/compressedEncode.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/index.d.ts +1 -1
- package/dist/feature-libraries/chunked-forest/codec/index.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/index.js +2 -1
- package/dist/feature-libraries/chunked-forest/codec/index.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/nodeEncoder.d.ts +1 -1
- package/dist/feature-libraries/chunked-forest/codec/nodeEncoder.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/codec/nodeEncoder.js +3 -15
- package/dist/feature-libraries/chunked-forest/codec/nodeEncoder.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/index.d.ts +1 -1
- package/dist/feature-libraries/chunked-forest/index.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/index.js +2 -1
- package/dist/feature-libraries/chunked-forest/index.js.map +1 -1
- package/dist/feature-libraries/forest-summary/codec.d.ts +3 -3
- package/dist/feature-libraries/forest-summary/codec.d.ts.map +1 -1
- package/dist/feature-libraries/forest-summary/codec.js.map +1 -1
- package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts +3 -2
- package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
- package/dist/feature-libraries/forest-summary/forestSummarizer.js +4 -6
- package/dist/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
- package/dist/feature-libraries/index.d.ts +1 -1
- package/dist/feature-libraries/index.d.ts.map +1 -1
- package/dist/feature-libraries/index.js +2 -1
- package/dist/feature-libraries/index.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecV1.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecV1.js +9 -9
- package/dist/feature-libraries/modular-schema/modularChangeCodecV1.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/shared-tree/independentView.d.ts.map +1 -1
- package/dist/shared-tree/independentView.js +4 -7
- package/dist/shared-tree/independentView.js.map +1 -1
- package/dist/shared-tree/index.d.ts +1 -1
- package/dist/shared-tree/index.d.ts.map +1 -1
- package/dist/shared-tree/index.js.map +1 -1
- package/dist/shared-tree/schematizingTreeView.d.ts +5 -5
- package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/dist/shared-tree/schematizingTreeView.js.map +1 -1
- package/dist/shared-tree/sharedTree.d.ts +5 -0
- package/dist/shared-tree/sharedTree.d.ts.map +1 -1
- package/dist/shared-tree/sharedTree.js +7 -4
- package/dist/shared-tree/sharedTree.js.map +1 -1
- package/dist/shared-tree/transactionPostProcessor.d.ts +28 -0
- package/dist/shared-tree/transactionPostProcessor.d.ts.map +1 -0
- package/dist/shared-tree/transactionPostProcessor.js +28 -0
- package/dist/shared-tree/transactionPostProcessor.js.map +1 -0
- package/dist/shared-tree/treeAlpha.js +3 -3
- package/dist/shared-tree/treeAlpha.js.map +1 -1
- package/dist/shared-tree/treeCheckout.d.ts +16 -12
- package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
- package/dist/shared-tree/treeCheckout.js +18 -9
- package/dist/shared-tree/treeCheckout.js.map +1 -1
- package/dist/shared-tree/unhydratedTreeContext.d.ts +5 -5
- package/dist/shared-tree/unhydratedTreeContext.d.ts.map +1 -1
- package/dist/shared-tree/unhydratedTreeContext.js.map +1 -1
- package/dist/shared-tree-core/editManagerCodecs.d.ts +3 -2
- package/dist/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerCodecs.js.map +1 -1
- package/dist/shared-tree-core/editManagerCodecsCommons.d.ts +3 -9
- package/dist/shared-tree-core/editManagerCodecsCommons.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerCodecsCommons.js +2 -4
- package/dist/shared-tree-core/editManagerCodecsCommons.js.map +1 -1
- package/dist/shared-tree-core/editManagerCodecsV1toV4.d.ts +3 -3
- package/dist/shared-tree-core/editManagerCodecsV1toV4.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerCodecsV1toV4.js.map +1 -1
- package/dist/shared-tree-core/editManagerCodecsVSharedBranches.d.ts +3 -3
- package/dist/shared-tree-core/editManagerCodecsVSharedBranches.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerCodecsVSharedBranches.js.map +1 -1
- package/dist/shared-tree-core/editManagerSummarizer.d.ts +5 -9
- package/dist/shared-tree-core/editManagerSummarizer.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerSummarizer.js +5 -10
- package/dist/shared-tree-core/editManagerSummarizer.js.map +1 -1
- package/dist/shared-tree-core/index.d.ts +1 -1
- package/dist/shared-tree-core/index.d.ts.map +1 -1
- package/dist/shared-tree-core/index.js +3 -2
- package/dist/shared-tree-core/index.js.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.js +3 -1
- package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/dist/shared-tree-core/transaction.d.ts +84 -9
- package/dist/shared-tree-core/transaction.d.ts.map +1 -1
- package/dist/shared-tree-core/transaction.js +74 -7
- package/dist/shared-tree-core/transaction.js.map +1 -1
- package/dist/simple-tree/api/index.d.ts +1 -1
- package/dist/simple-tree/api/index.d.ts.map +1 -1
- package/dist/simple-tree/api/index.js.map +1 -1
- package/dist/simple-tree/api/schemaCreationUtilities.d.ts +3 -3
- package/dist/simple-tree/api/schemaCreationUtilities.js +3 -3
- package/dist/simple-tree/api/schemaCreationUtilities.js.map +1 -1
- package/dist/simple-tree/api/schemaFactory.d.ts +1 -1
- package/dist/simple-tree/api/schemaFactory.js +2 -2
- package/dist/simple-tree/api/schemaFactory.js.map +1 -1
- package/dist/simple-tree/api/snapshotCompatibilityChecker.d.ts +2 -2
- package/dist/simple-tree/api/snapshotCompatibilityChecker.js +2 -2
- package/dist/simple-tree/api/snapshotCompatibilityChecker.js.map +1 -1
- package/dist/simple-tree/api/transactionTypes.d.ts +91 -28
- 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 +86 -22
- 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/treeBeta.d.ts.map +1 -1
- package/dist/simple-tree/api/treeBeta.js.map +1 -1
- package/dist/simple-tree/core/treeNodeSchema.d.ts +7 -7
- package/dist/simple-tree/core/treeNodeSchema.js.map +1 -1
- package/dist/simple-tree/index.d.ts +1 -1
- package/dist/simple-tree/index.d.ts.map +1 -1
- package/dist/simple-tree/index.js.map +1 -1
- package/dist/text/index.d.ts +1 -0
- package/dist/text/index.d.ts.map +1 -1
- package/dist/text/index.js +3 -1
- package/dist/text/index.js.map +1 -1
- package/dist/text/textDomainFormatted.d.ts +69 -758
- package/dist/text/textDomainFormatted.d.ts.map +1 -1
- package/dist/text/textDomainFormatted.js +275 -322
- package/dist/text/textDomainFormatted.js.map +1 -1
- package/dist/text/textDomainFormattedDefault.d.ts +273 -0
- package/dist/text/textDomainFormattedDefault.d.ts.map +1 -0
- package/dist/text/textDomainFormattedDefault.js +94 -0
- package/dist/text/textDomainFormattedDefault.js.map +1 -0
- package/dist/util/compressedIds.d.ts +118 -0
- package/dist/util/compressedIds.d.ts.map +1 -0
- package/dist/util/compressedIds.js +133 -0
- package/dist/util/compressedIds.js.map +1 -0
- package/dist/util/index.d.ts +1 -0
- package/dist/util/index.d.ts.map +1 -1
- package/dist/util/index.js +9 -1
- package/dist/util/index.js.map +1 -1
- package/lib/core/change-family/changeFamily.d.ts +3 -10
- package/lib/core/change-family/changeFamily.d.ts.map +1 -1
- package/lib/core/change-family/changeFamily.js.map +1 -1
- package/lib/core/rebase/types.d.ts +2 -2
- package/lib/core/rebase/types.js.map +1 -1
- package/lib/core/schema-stored/storedSchemaRepository.d.ts +2 -2
- package/lib/core/schema-stored/storedSchemaRepository.js.map +1 -1
- package/lib/entrypoints/alpha.d.ts +1 -1
- package/lib/entrypoints/alpha.d.ts.map +1 -1
- package/lib/entrypoints/alpha.js.map +1 -1
- package/lib/entrypoints/beta.d.ts +1 -1
- package/lib/entrypoints/beta.d.ts.map +1 -1
- package/lib/entrypoints/beta.js.map +1 -1
- package/lib/entrypoints/legacy.d.ts +1 -1
- package/lib/entrypoints/legacy.d.ts.map +1 -1
- package/lib/entrypoints/legacy.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts +19 -14
- package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.js +14 -33
- package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/codecs.d.ts +85 -28
- package/lib/feature-libraries/chunked-forest/codec/codecs.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/codecs.js +82 -9
- package/lib/feature-libraries/chunked-forest/codec/codecs.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/compressedEncode.d.ts +4 -2
- package/lib/feature-libraries/chunked-forest/codec/compressedEncode.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/compressedEncode.js +12 -1
- package/lib/feature-libraries/chunked-forest/codec/compressedEncode.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/index.d.ts +1 -1
- package/lib/feature-libraries/chunked-forest/codec/index.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/index.js +1 -1
- package/lib/feature-libraries/chunked-forest/codec/index.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/nodeEncoder.d.ts +1 -1
- package/lib/feature-libraries/chunked-forest/codec/nodeEncoder.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/codec/nodeEncoder.js +3 -15
- package/lib/feature-libraries/chunked-forest/codec/nodeEncoder.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/index.d.ts +1 -1
- package/lib/feature-libraries/chunked-forest/index.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/index.js +1 -1
- package/lib/feature-libraries/chunked-forest/index.js.map +1 -1
- package/lib/feature-libraries/forest-summary/codec.d.ts +3 -3
- package/lib/feature-libraries/forest-summary/codec.d.ts.map +1 -1
- package/lib/feature-libraries/forest-summary/codec.js.map +1 -1
- package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts +3 -2
- package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
- package/lib/feature-libraries/forest-summary/forestSummarizer.js +4 -6
- package/lib/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
- package/lib/feature-libraries/index.d.ts +1 -1
- package/lib/feature-libraries/index.d.ts.map +1 -1
- package/lib/feature-libraries/index.js +1 -1
- package/lib/feature-libraries/index.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecV1.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecV1.js +10 -10
- package/lib/feature-libraries/modular-schema/modularChangeCodecV1.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/shared-tree/independentView.d.ts.map +1 -1
- package/lib/shared-tree/independentView.js +5 -8
- package/lib/shared-tree/independentView.js.map +1 -1
- package/lib/shared-tree/index.d.ts +1 -1
- package/lib/shared-tree/index.d.ts.map +1 -1
- package/lib/shared-tree/index.js.map +1 -1
- package/lib/shared-tree/schematizingTreeView.d.ts +5 -5
- package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/lib/shared-tree/schematizingTreeView.js.map +1 -1
- package/lib/shared-tree/sharedTree.d.ts +5 -0
- package/lib/shared-tree/sharedTree.d.ts.map +1 -1
- package/lib/shared-tree/sharedTree.js +8 -5
- package/lib/shared-tree/sharedTree.js.map +1 -1
- package/lib/shared-tree/transactionPostProcessor.d.ts +28 -0
- package/lib/shared-tree/transactionPostProcessor.d.ts.map +1 -0
- package/lib/shared-tree/transactionPostProcessor.js +23 -0
- package/lib/shared-tree/transactionPostProcessor.js.map +1 -0
- package/lib/shared-tree/treeAlpha.js +3 -3
- package/lib/shared-tree/treeAlpha.js.map +1 -1
- package/lib/shared-tree/treeCheckout.d.ts +16 -12
- package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
- package/lib/shared-tree/treeCheckout.js +18 -9
- package/lib/shared-tree/treeCheckout.js.map +1 -1
- package/lib/shared-tree/unhydratedTreeContext.d.ts +5 -5
- package/lib/shared-tree/unhydratedTreeContext.d.ts.map +1 -1
- package/lib/shared-tree/unhydratedTreeContext.js.map +1 -1
- package/lib/shared-tree-core/editManagerCodecs.d.ts +3 -2
- package/lib/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerCodecs.js.map +1 -1
- package/lib/shared-tree-core/editManagerCodecsCommons.d.ts +3 -9
- package/lib/shared-tree-core/editManagerCodecsCommons.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerCodecsCommons.js +3 -5
- package/lib/shared-tree-core/editManagerCodecsCommons.js.map +1 -1
- package/lib/shared-tree-core/editManagerCodecsV1toV4.d.ts +3 -3
- package/lib/shared-tree-core/editManagerCodecsV1toV4.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerCodecsV1toV4.js.map +1 -1
- package/lib/shared-tree-core/editManagerCodecsVSharedBranches.d.ts +3 -3
- package/lib/shared-tree-core/editManagerCodecsVSharedBranches.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerCodecsVSharedBranches.js.map +1 -1
- package/lib/shared-tree-core/editManagerSummarizer.d.ts +5 -9
- package/lib/shared-tree-core/editManagerSummarizer.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerSummarizer.js +5 -10
- package/lib/shared-tree-core/editManagerSummarizer.js.map +1 -1
- package/lib/shared-tree-core/index.d.ts +1 -1
- package/lib/shared-tree-core/index.d.ts.map +1 -1
- package/lib/shared-tree-core/index.js +1 -1
- package/lib/shared-tree-core/index.js.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.js +3 -1
- package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/lib/shared-tree-core/transaction.d.ts +84 -9
- package/lib/shared-tree-core/transaction.d.ts.map +1 -1
- package/lib/shared-tree-core/transaction.js +73 -6
- package/lib/shared-tree-core/transaction.js.map +1 -1
- package/lib/simple-tree/api/index.d.ts +1 -1
- package/lib/simple-tree/api/index.d.ts.map +1 -1
- package/lib/simple-tree/api/index.js.map +1 -1
- package/lib/simple-tree/api/schemaCreationUtilities.d.ts +3 -3
- package/lib/simple-tree/api/schemaCreationUtilities.js +3 -3
- package/lib/simple-tree/api/schemaCreationUtilities.js.map +1 -1
- package/lib/simple-tree/api/schemaFactory.d.ts +1 -1
- package/lib/simple-tree/api/schemaFactory.js +2 -2
- package/lib/simple-tree/api/schemaFactory.js.map +1 -1
- package/lib/simple-tree/api/snapshotCompatibilityChecker.d.ts +2 -2
- package/lib/simple-tree/api/snapshotCompatibilityChecker.js +2 -2
- package/lib/simple-tree/api/snapshotCompatibilityChecker.js.map +1 -1
- package/lib/simple-tree/api/transactionTypes.d.ts +91 -28
- 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 +86 -22
- 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/treeBeta.d.ts.map +1 -1
- package/lib/simple-tree/api/treeBeta.js.map +1 -1
- package/lib/simple-tree/core/treeNodeSchema.d.ts +7 -7
- package/lib/simple-tree/core/treeNodeSchema.js.map +1 -1
- package/lib/simple-tree/index.d.ts +1 -1
- package/lib/simple-tree/index.d.ts.map +1 -1
- package/lib/simple-tree/index.js.map +1 -1
- package/lib/text/index.d.ts +1 -0
- package/lib/text/index.d.ts.map +1 -1
- package/lib/text/index.js +1 -0
- package/lib/text/index.js.map +1 -1
- package/lib/text/textDomainFormatted.d.ts +69 -758
- package/lib/text/textDomainFormatted.d.ts.map +1 -1
- package/lib/text/textDomainFormatted.js +277 -324
- package/lib/text/textDomainFormatted.js.map +1 -1
- package/lib/text/textDomainFormattedDefault.d.ts +273 -0
- package/lib/text/textDomainFormattedDefault.d.ts.map +1 -0
- package/lib/text/textDomainFormattedDefault.js +91 -0
- package/lib/text/textDomainFormattedDefault.js.map +1 -0
- package/lib/util/compressedIds.d.ts +118 -0
- package/lib/util/compressedIds.d.ts.map +1 -0
- package/lib/util/compressedIds.js +124 -0
- package/lib/util/compressedIds.js.map +1 -0
- package/lib/util/index.d.ts +1 -0
- package/lib/util/index.d.ts.map +1 -1
- package/lib/util/index.js +1 -0
- package/lib/util/index.js.map +1 -1
- package/package.json +23 -23
- package/src/core/change-family/changeFamily.ts +3 -12
- package/src/core/rebase/types.ts +2 -2
- package/src/core/schema-stored/storedSchemaRepository.ts +2 -2
- package/src/entrypoints/alpha.ts +12 -8
- package/src/entrypoints/beta.ts +8 -0
- package/src/entrypoints/legacy.ts +8 -0
- package/src/feature-libraries/chunked-forest/codec/chunkDecoding.ts +35 -64
- package/src/feature-libraries/chunked-forest/codec/codecs.ts +138 -42
- package/src/feature-libraries/chunked-forest/codec/compressedEncode.ts +32 -4
- package/src/feature-libraries/chunked-forest/codec/index.ts +1 -0
- package/src/feature-libraries/chunked-forest/codec/nodeEncoder.ts +7 -19
- package/src/feature-libraries/chunked-forest/index.ts +3 -0
- package/src/feature-libraries/forest-summary/codec.ts +5 -3
- package/src/feature-libraries/forest-summary/forestSummarizer.ts +4 -5
- package/src/feature-libraries/index.ts +3 -0
- package/src/feature-libraries/modular-schema/modularChangeCodecV1.ts +13 -9
- package/src/index.ts +13 -8
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/independentView.ts +5 -10
- package/src/shared-tree/index.ts +1 -0
- package/src/shared-tree/schematizingTreeView.ts +25 -25
- package/src/shared-tree/sharedTree.ts +16 -4
- package/src/shared-tree/transactionPostProcessor.ts +40 -0
- package/src/shared-tree/treeAlpha.ts +3 -3
- package/src/shared-tree/treeCheckout.ts +61 -44
- package/src/shared-tree/unhydratedTreeContext.ts +18 -15
- package/src/shared-tree-core/editManagerCodecs.ts +3 -2
- package/src/shared-tree-core/editManagerCodecsCommons.ts +10 -14
- package/src/shared-tree-core/editManagerCodecsV1toV4.ts +3 -2
- package/src/shared-tree-core/editManagerCodecsVSharedBranches.ts +3 -2
- package/src/shared-tree-core/editManagerSummarizer.ts +5 -9
- package/src/shared-tree-core/index.ts +8 -5
- package/src/shared-tree-core/sharedTreeCore.ts +3 -2
- package/src/shared-tree-core/transaction.ts +148 -18
- package/src/simple-tree/api/index.ts +13 -9
- package/src/simple-tree/api/schemaCreationUtilities.ts +3 -3
- package/src/simple-tree/api/schemaFactory.ts +2 -2
- package/src/simple-tree/api/snapshotCompatibilityChecker.ts +2 -2
- package/src/simple-tree/api/transactionTypes.ts +111 -39
- package/src/simple-tree/api/tree.ts +141 -47
- package/src/simple-tree/api/treeBeta.ts +2 -0
- package/src/simple-tree/core/treeNodeSchema.ts +7 -7
- package/src/simple-tree/index.ts +12 -8
- package/src/text/index.ts +1 -0
- package/src/text/textDomainFormatted.ts +520 -415
- package/src/text/textDomainFormattedDefault.ts +150 -0
- package/src/util/compressedIds.ts +216 -0
- package/src/util/index.ts +15 -0
|
@@ -7,10 +7,8 @@ import { assert, unreachableCase, oob } from "@fluidframework/core-utils/interna
|
|
|
7
7
|
import type {
|
|
8
8
|
IIdCompressor,
|
|
9
9
|
OpSpaceCompressedId,
|
|
10
|
-
|
|
10
|
+
SessionSpaceCompressedId,
|
|
11
11
|
} from "@fluidframework/id-compressor";
|
|
12
|
-
import { isFinalId } from "@fluidframework/id-compressor/internal";
|
|
13
|
-
import { v5 as uuidV5 } from "uuid";
|
|
14
12
|
|
|
15
13
|
import { DiscriminatedUnionDispatcher } from "../../../codec/index.js";
|
|
16
14
|
import type {
|
|
@@ -19,7 +17,7 @@ import type {
|
|
|
19
17
|
Value,
|
|
20
18
|
TreeChunk,
|
|
21
19
|
} from "../../../core/index.js";
|
|
22
|
-
import { assertValidIndex, brand } from "../../../util/index.js";
|
|
20
|
+
import { assertValidIndex, brand, decompressIdentifierIfNeeded } from "../../../util/index.js";
|
|
23
21
|
import { BasicChunk } from "../basicChunk.js";
|
|
24
22
|
import { emptyChunk } from "../emptyChunk.js";
|
|
25
23
|
import { SequenceChunk } from "../sequenceChunk.js";
|
|
@@ -39,8 +37,7 @@ import {
|
|
|
39
37
|
decode as genericDecode,
|
|
40
38
|
readStreamIdentifier,
|
|
41
39
|
} from "./chunkDecodingGeneric.js";
|
|
42
|
-
|
|
43
|
-
import type { FieldBatchEncodingContext, IncrementalDecoder } from "./codecs.js";
|
|
40
|
+
import type { IncrementalDecoder } from "./codecs.js";
|
|
44
41
|
import {
|
|
45
42
|
type EncodedAnyShape,
|
|
46
43
|
type EncodedChunkShape,
|
|
@@ -58,32 +55,31 @@ import {
|
|
|
58
55
|
supportsIncrementalEncoding,
|
|
59
56
|
} from "./format/index.js";
|
|
60
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Context for decoding identifiers.
|
|
60
|
+
* @remarks
|
|
61
|
+
* See {@link FieldBatchDecodingContext} for the production implementation of this.
|
|
62
|
+
*
|
|
63
|
+
* This intentionally avoids exposing anything which depends on the underlying id-compressor's session ID to avoid confusion with the session ID of the compressor which encoded the data.
|
|
64
|
+
* If the session ID of the encoder which encoded the data is known, that information is baked into `resolveEncodedId`.
|
|
65
|
+
*/
|
|
61
66
|
export interface IdDecodingContext {
|
|
62
|
-
idCompressor: IIdCompressor;
|
|
63
|
-
/**
|
|
64
|
-
* The creator of any local Ids to be decoded.
|
|
65
|
-
*/
|
|
66
|
-
originatorId: SessionId;
|
|
67
|
-
/**
|
|
68
|
-
* {@inheritdoc FieldBatchEncodingContext.isSummary}
|
|
69
|
-
*/
|
|
70
|
-
isSummary: boolean;
|
|
71
67
|
/**
|
|
72
|
-
*
|
|
68
|
+
* Compressor which can decompress session-space identifiers from {@link resolveEncodedId} as needed.
|
|
73
69
|
*/
|
|
74
|
-
|
|
70
|
+
readonly idCompressor: Pick<IIdCompressor, "decompress">;
|
|
75
71
|
/**
|
|
76
|
-
*
|
|
72
|
+
* Resolves an encoded op-space identifier to either a session-space ID
|
|
73
|
+
* (which {@link idCompressor} can decompress if needed)
|
|
74
|
+
* or a string (which passes through unchanged).
|
|
75
|
+
* @remarks
|
|
76
|
+
* In contexts where non-final identifiers can't be supported (where no originator session is available),
|
|
77
|
+
* if a non-final identifier is encountered, this may throw or perform a data healing workaround.
|
|
78
|
+
* See {@link FieldBatchDecodingContext.forOp} and {@link FieldBatchDecodingContext.forSummary} for details.
|
|
77
79
|
*/
|
|
78
|
-
|
|
80
|
+
readonly resolveEncodedId: (id: OpSpaceCompressedId) => SessionSpaceCompressedId | string;
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
/**
|
|
82
|
-
* Random v4 UUID generated as a namespace for the "heal an unresolvable identifier into a stable UUID"
|
|
83
|
-
* path in {@link readValue}. This scheme requires consensus across all clients to function.
|
|
84
|
-
*/
|
|
85
|
-
const healingNamespace = "f8a89df3-6882-400f-b913-4c1f6f0157bd";
|
|
86
|
-
|
|
87
83
|
/**
|
|
88
84
|
* Decode `chunk` into a TreeChunk.
|
|
89
85
|
*/
|
|
@@ -281,45 +277,20 @@ export function readValue(
|
|
|
281
277
|
typeof streamValue === "number" || typeof streamValue === "string",
|
|
282
278
|
0x997 /* identifier must be string or number. */,
|
|
283
279
|
);
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
//
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
// Documents written before the encode-side fix for non-finalized identifier
|
|
299
|
-
// values can persist negative op-space IDs that are no
|
|
300
|
-
// longer resolvable once the originating session's local state has been stripped.
|
|
301
|
-
// When loading such a summary with the heal-on-decode option on, synthesize a deterministic
|
|
302
|
-
// stable UUID so all readers of the same blob agree on the resulting value.
|
|
303
|
-
//
|
|
304
|
-
// The heal path is intentionally restricted to summary loads — an
|
|
305
|
-
// unresolvable ID encountered while applying an op should still surface as
|
|
306
|
-
// an error, since it indicates a real bug rather than a recoverable state.
|
|
307
|
-
return uuidV5(
|
|
308
|
-
`${idDecodingContext.sharedObjectId}|${streamValue}`,
|
|
309
|
-
healingNamespace,
|
|
310
|
-
);
|
|
311
|
-
}
|
|
312
|
-
// See `SharedTreeOptionsBeta.healUnresolvableIdentifiersOnDecode` for details on this error.
|
|
313
|
-
throw new Error(
|
|
314
|
-
"Summary could not be loaded due incorrectly encoded identifier. See SharedTreeOptionsBeta.healUnresolvableIdentifiersOnDecode for mitigation.",
|
|
315
|
-
);
|
|
316
|
-
}
|
|
317
|
-
return idCompressor.decompress(
|
|
318
|
-
idCompressor.normalizeToSessionSpace(
|
|
319
|
-
streamValue as OpSpaceCompressedId,
|
|
320
|
-
idDecodingContext.originatorId,
|
|
321
|
-
),
|
|
322
|
-
);
|
|
280
|
+
// Strings (StableId UUIDs, heal-synthesized v5 UUIDs, or arbitrary user
|
|
281
|
+
// identifier strings) are already in the stored form and pass through.
|
|
282
|
+
// Op-space compressed ids are resolved by the caller-supplied
|
|
283
|
+
// `resolveEncodedId`, which encapsulates the originator lookup, finalized-id
|
|
284
|
+
// normalization, and (for the forest summarizer's heal path) UUIDv5 synthesis.
|
|
285
|
+
const sessionIdOrString: SessionSpaceCompressedId | string =
|
|
286
|
+
typeof streamValue === "string"
|
|
287
|
+
? streamValue
|
|
288
|
+
: idDecodingContext.resolveEncodedId(streamValue as OpSpaceCompressedId);
|
|
289
|
+
// Performance:
|
|
290
|
+
// Currently, we just fully expand the identifier here rather than keeping it in the SessionSpaceCompressedId format.
|
|
291
|
+
// Avoiding this expansion, and keeping the in memory format using SessionSpaceCompressedId would be a good optimization for the future.
|
|
292
|
+
// Keeping this optimization possible is why `resolveEncodedId` doesn't simply return a string.
|
|
293
|
+
return decompressIdentifierIfNeeded(sessionIdOrString, idDecodingContext.idCompressor);
|
|
323
294
|
} else {
|
|
324
295
|
// EncodedCounter case:
|
|
325
296
|
unreachableCase(shape, "decoding values as deltas is not yet supported");
|
|
@@ -4,7 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { assert, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
7
|
-
import type {
|
|
7
|
+
import type {
|
|
8
|
+
IIdCompressor,
|
|
9
|
+
OpSpaceCompressedId,
|
|
10
|
+
SessionId,
|
|
11
|
+
SessionSpaceCompressedId,
|
|
12
|
+
} from "@fluidframework/id-compressor";
|
|
8
13
|
import { lowestMinVersionForCollab } from "@fluidframework/runtime-utils/internal";
|
|
9
14
|
import type { TSchema } from "@sinclair/typebox";
|
|
10
15
|
|
|
@@ -22,10 +27,15 @@ import {
|
|
|
22
27
|
type StoredSchemaCollection,
|
|
23
28
|
type TreeChunk,
|
|
24
29
|
} from "../../../core/index.js";
|
|
25
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
brandedNumberType,
|
|
32
|
+
forceDecodeEncodedIdWithoutSession,
|
|
33
|
+
type Brand,
|
|
34
|
+
type IdentifierHealingConfig,
|
|
35
|
+
} from "../../../util/index.js";
|
|
26
36
|
import { TreeCompressionStrategy } from "../../treeCompressionUtils.js";
|
|
27
37
|
|
|
28
|
-
import { decode } from "./chunkDecoding.js";
|
|
38
|
+
import { decode, type IdDecodingContext } from "./chunkDecoding.js";
|
|
29
39
|
import type { FieldBatch } from "./fieldBatch.js";
|
|
30
40
|
import {
|
|
31
41
|
EncodedFieldBatchV1,
|
|
@@ -97,44 +107,139 @@ export interface IncrementalDecoder {
|
|
|
97
107
|
*/
|
|
98
108
|
export interface IncrementalEncoderDecoder extends IncrementalEncoder, IncrementalDecoder {}
|
|
99
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Encode-side context for {@link FieldBatchCodec}.
|
|
112
|
+
*
|
|
113
|
+
* Carries only the data the encoder actually consumes. Originator-session
|
|
114
|
+
* lookup, heal flags, and the incremental *decoder* live on
|
|
115
|
+
* {@link FieldBatchDecodingContext}.
|
|
116
|
+
*/
|
|
100
117
|
export interface FieldBatchEncodingContext {
|
|
101
118
|
readonly encodeType: TreeCompressionStrategy;
|
|
102
119
|
readonly idCompressor: IIdCompressor;
|
|
103
|
-
readonly originatorId: SessionId;
|
|
104
120
|
readonly schema?: SchemaAndPolicy;
|
|
105
121
|
/**
|
|
106
|
-
*
|
|
107
|
-
*
|
|
122
|
+
* Encoder for incremental fields. Defined when incremental encoding is
|
|
123
|
+
* supported and enabled.
|
|
108
124
|
*/
|
|
109
|
-
readonly
|
|
125
|
+
readonly incrementalEncoder?: IncrementalEncoder;
|
|
110
126
|
/**
|
|
111
|
-
* `true` when encoding to
|
|
112
|
-
*
|
|
113
|
-
*
|
|
127
|
+
* `true` when encoding to a summary blob. `false` for op-stream encode
|
|
128
|
+
* paths and for utility encoders that aren't tied to a persisted document.
|
|
129
|
+
*
|
|
130
|
+
* @remarks
|
|
131
|
+
* Used by the node encoder to decide whether non-finalized op-space ids
|
|
132
|
+
* can be written into the batch (they can't, for summaries).
|
|
114
133
|
*/
|
|
115
134
|
readonly isSummary: boolean;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Decode-side context for {@link FieldBatchCodec}.
|
|
139
|
+
*
|
|
140
|
+
* Carries the per-call `resolveEncodedId` function that encapsulates the
|
|
141
|
+
* originator-session lookup and (for the forest-summarizer's legacy heal path)
|
|
142
|
+
* the deterministic UUIDv5 synthesis. Heal and originator-session flags live
|
|
143
|
+
* inside that function, not on this context.
|
|
144
|
+
*
|
|
145
|
+
* Constructed via one of the two named static factories — {@link forOp} or
|
|
146
|
+
* {@link forSummary} — depending on the call site's semantics. The constructor
|
|
147
|
+
* is private; there is no general-purpose builder, because the choice between
|
|
148
|
+
* op-style and summary-style decoding is load-bearing (different invariants
|
|
149
|
+
* apply, and bugs in this area are typically the result of conflating them).
|
|
150
|
+
*/
|
|
151
|
+
export class FieldBatchDecodingContext implements IdDecodingContext {
|
|
152
|
+
private constructor(
|
|
153
|
+
/**
|
|
154
|
+
* Used internally to prevent the use of this decoder in incremental chunks if it has a session id (which would be wrong in those chunks).
|
|
155
|
+
*/
|
|
156
|
+
private readonly hasOriginatorSessionId: boolean,
|
|
157
|
+
|
|
158
|
+
public readonly idCompressor: Pick<IIdCompressor, "decompress">,
|
|
159
|
+
|
|
160
|
+
public readonly resolveEncodedId: (
|
|
161
|
+
id: OpSpaceCompressedId,
|
|
162
|
+
) => SessionSpaceCompressedId | string,
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Decoder for incremental fields. Defined when the encoded batch contains
|
|
166
|
+
* incremental chunks. Only populated on summary-style contexts; op-style
|
|
167
|
+
* contexts always have this undefined.
|
|
168
|
+
*/
|
|
169
|
+
public readonly incrementalDecoder?: IncrementalDecoder,
|
|
170
|
+
) {}
|
|
171
|
+
|
|
116
172
|
/**
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
* shipped. Only takes effect when `isSummary` is also `true`.
|
|
125
|
-
* See {@link SharedTreeOptionsBeta.healUnresolvableIdentifiersOnDecode}.
|
|
173
|
+
* Construct a decode context for an op.
|
|
174
|
+
*
|
|
175
|
+
* The originator is the session that produced the encoded form (carried
|
|
176
|
+
* alongside the op envelope by the caller). Heal-on-decode is *not*
|
|
177
|
+
* available — an unresolvable id during op decode indicates a real bug,
|
|
178
|
+
* not a recoverable state, so the resolver throws rather than synthesizing
|
|
179
|
+
* a UUID. Incremental decoding is not used for ops.
|
|
126
180
|
*/
|
|
127
|
-
|
|
181
|
+
public static forOp(opts: {
|
|
182
|
+
readonly idCompressor: IIdCompressor;
|
|
183
|
+
readonly originatorId: SessionId;
|
|
184
|
+
}): FieldBatchDecodingContext {
|
|
185
|
+
const { idCompressor, originatorId } = opts;
|
|
186
|
+
return new FieldBatchDecodingContext(true, idCompressor, (id) =>
|
|
187
|
+
idCompressor.normalizeToSessionSpace(id, originatorId),
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
128
191
|
/**
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* @
|
|
133
|
-
*
|
|
134
|
-
*
|
|
192
|
+
* Construct a decode context for a summary blob.
|
|
193
|
+
*
|
|
194
|
+
* Summaries must contain only ids resolvable without an originator — either
|
|
195
|
+
* finalized op-space ids, or (when {@link IdentifierHealingConfig} is supplied
|
|
196
|
+
* via `healing`) non-final ids that get healed into deterministic UUIDv5
|
|
197
|
+
* strings. Incremental decoding is attached via {@link withIncrementalDecoder}.
|
|
198
|
+
*
|
|
199
|
+
* @privateRemarks
|
|
200
|
+
* In the future (if adding a summary format which includes the session id),
|
|
201
|
+
* this could allow providing an originator ID to allow for op-space compressed identifiers in attach summaries.
|
|
202
|
+
* Non-attach summaries should only have finalized compressed identifiers (due to only being made by summary clients which never allocate identifiers since they never edit).
|
|
203
|
+
* Since only non-attach summaries can be incremental, incremental summaries should never have non finalized identifiers.
|
|
204
|
+
* `withIncrementalDecoder` has logic to guard against cases which expect session-relative identifiers in incremental chunks,
|
|
205
|
+
* as does the encoding-side assert in the {@link EncoderContext}.
|
|
135
206
|
*/
|
|
136
|
-
|
|
207
|
+
public static forSummary(opts: {
|
|
208
|
+
readonly idCompressor: IIdCompressor;
|
|
209
|
+
readonly healing?: IdentifierHealingConfig;
|
|
210
|
+
}): FieldBatchDecodingContext {
|
|
211
|
+
const { idCompressor, healing } = opts;
|
|
212
|
+
return new FieldBatchDecodingContext(false, idCompressor, (id) =>
|
|
213
|
+
forceDecodeEncodedIdWithoutSession(id, idCompressor, healing),
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Returns a copy of this context with `incrementalDecoder` swapped in. Used by
|
|
219
|
+
* the forest summarizer to attach the per-call incremental builder to a base
|
|
220
|
+
* decode context.
|
|
221
|
+
*/
|
|
222
|
+
public withIncrementalDecoder(
|
|
223
|
+
incrementalDecoder: IncrementalDecoder,
|
|
224
|
+
): FieldBatchDecodingContext {
|
|
225
|
+
// As different incremental chunks may come from different sessions,
|
|
226
|
+
// for now we simply enforce that we do not provide an originator session ID
|
|
227
|
+
// when we might be dealing with incremental chunks.
|
|
228
|
+
// This mitigates the risk of using incorrect originator session ID identifiers in incremental chunks.
|
|
229
|
+
// See also private remarks on forSummary.
|
|
230
|
+
assert(
|
|
231
|
+
!this.hasOriginatorSessionId,
|
|
232
|
+
0xd0c /* withIncrementalDecoder can only be called on contexts without an originator session ID */,
|
|
233
|
+
);
|
|
234
|
+
return new FieldBatchDecodingContext(
|
|
235
|
+
false,
|
|
236
|
+
this.idCompressor,
|
|
237
|
+
this.resolveEncodedId,
|
|
238
|
+
incrementalDecoder,
|
|
239
|
+
);
|
|
240
|
+
}
|
|
137
241
|
}
|
|
242
|
+
|
|
138
243
|
/**
|
|
139
244
|
* @remarks
|
|
140
245
|
* Fields in this batch currently don't have field schema for the root, which limits optimizations.
|
|
@@ -142,7 +247,8 @@ export interface FieldBatchEncodingContext {
|
|
|
142
247
|
export type FieldBatchCodec = VersionDispatchingCodec<
|
|
143
248
|
FieldBatch,
|
|
144
249
|
FieldBatchEncodingContext,
|
|
145
|
-
FieldBatchFormatVersion
|
|
250
|
+
FieldBatchFormatVersion,
|
|
251
|
+
FieldBatchDecodingContext
|
|
146
252
|
>;
|
|
147
253
|
|
|
148
254
|
/**
|
|
@@ -160,7 +266,7 @@ function makeFieldBatchCodecForVersion(
|
|
|
160
266
|
isSummary: boolean,
|
|
161
267
|
) => EncodedFieldBatchV1OrV2,
|
|
162
268
|
encodedFieldBatchType: TSchema,
|
|
163
|
-
): CodecAndSchema<FieldBatch, FieldBatchEncodingContext> {
|
|
269
|
+
): CodecAndSchema<FieldBatch, FieldBatchEncodingContext, FieldBatchDecodingContext> {
|
|
164
270
|
return {
|
|
165
271
|
encode: (
|
|
166
272
|
data: FieldBatch,
|
|
@@ -185,7 +291,7 @@ function makeFieldBatchCodecForVersion(
|
|
|
185
291
|
0xca0 /* Unsupported FieldBatchFormatVersion for incremental encoding; must be v2 or higher */,
|
|
186
292
|
);
|
|
187
293
|
// Incremental encoding is only supported for CompressedIncremental.
|
|
188
|
-
incrementalEncoder = context.
|
|
294
|
+
incrementalEncoder = context.incrementalEncoder;
|
|
189
295
|
}
|
|
190
296
|
// fallthrough
|
|
191
297
|
case TreeCompressionStrategy.Compressed: {
|
|
@@ -216,20 +322,10 @@ function makeFieldBatchCodecForVersion(
|
|
|
216
322
|
},
|
|
217
323
|
decode: (
|
|
218
324
|
data: EncodedFieldBatchV1OrV2,
|
|
219
|
-
context:
|
|
325
|
+
context: FieldBatchDecodingContext,
|
|
220
326
|
): FieldBatch => {
|
|
221
327
|
// TODO: consider checking data is in schema.
|
|
222
|
-
return decode(
|
|
223
|
-
data,
|
|
224
|
-
{
|
|
225
|
-
idCompressor: context.idCompressor,
|
|
226
|
-
originatorId: context.originatorId,
|
|
227
|
-
isSummary: context.isSummary,
|
|
228
|
-
healUnresolvableIdentifiersOnDecode: context.healUnresolvableIdentifiersOnDecode,
|
|
229
|
-
sharedObjectId: context.sharedObjectId,
|
|
230
|
-
},
|
|
231
|
-
context.incrementalEncoderDecoder,
|
|
232
|
-
).map((chunk) => chunk.cursor());
|
|
328
|
+
return decode(data, context, context.incrementalDecoder).map((chunk) => chunk.cursor());
|
|
233
329
|
},
|
|
234
330
|
schema: encodedFieldBatchType,
|
|
235
331
|
};
|
|
@@ -18,7 +18,13 @@ import {
|
|
|
18
18
|
type Value,
|
|
19
19
|
forEachNode,
|
|
20
20
|
} from "../../../core/index.js";
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
EncodedIdType,
|
|
23
|
+
encodePossiblyCompressedId,
|
|
24
|
+
getOrCreate,
|
|
25
|
+
type EncodedId,
|
|
26
|
+
type IdEncodingContext,
|
|
27
|
+
} from "../../../util/index.js";
|
|
22
28
|
|
|
23
29
|
import type { Counter, DeduplicationTable } from "./chunkCodecUtilities.js";
|
|
24
30
|
import {
|
|
@@ -520,7 +526,9 @@ export function encodeValue(
|
|
|
520
526
|
* - Singletons defined in a static scope.
|
|
521
527
|
* - Cached in this object for future reuse such that all equivalent Shapes are deduplicated.
|
|
522
528
|
*/
|
|
523
|
-
export class EncoderContext
|
|
529
|
+
export class EncoderContext
|
|
530
|
+
implements NodeEncodeBuilder, FieldEncodeBuilder, IdEncodingContext
|
|
531
|
+
{
|
|
524
532
|
private readonly nodeEncodersFromSchema: Map<TreeNodeSchemaIdentifier, NodeEncoder> =
|
|
525
533
|
new Map();
|
|
526
534
|
private readonly nestedArrayEncoders: Map<NodeEncoder, NestedArrayEncoder> = new Map();
|
|
@@ -528,7 +536,7 @@ export class EncoderContext implements NodeEncodeBuilder, FieldEncodeBuilder {
|
|
|
528
536
|
private readonly nodeEncoderFromPolicy: NodeEncoderPolicy,
|
|
529
537
|
private readonly fieldEncoderFromPolicy: FieldEncoderPolicy,
|
|
530
538
|
public readonly fieldShapes: ReadonlyMap<FieldKindIdentifier, FieldKindData>,
|
|
531
|
-
|
|
539
|
+
private readonly idCompressor: IIdCompressor,
|
|
532
540
|
/**
|
|
533
541
|
* To be used to encode incremental chunks, if any.
|
|
534
542
|
* @remarks
|
|
@@ -540,7 +548,27 @@ export class EncoderContext implements NodeEncodeBuilder, FieldEncodeBuilder {
|
|
|
540
548
|
* See {@link FieldBatchEncodingContext.isSummary}.
|
|
541
549
|
*/
|
|
542
550
|
public readonly isSummary: boolean,
|
|
543
|
-
) {
|
|
551
|
+
) {
|
|
552
|
+
// Currently we never include originator-dependent identifiers in summaries
|
|
553
|
+
// (there was a bug which violated this for attach-summaries: it has been fixed, see `IdentifierHealingConfig`).
|
|
554
|
+
// If that ever changes (to allow better compressed attach summaries), we need to take special care with incremental summaries.
|
|
555
|
+
// This assert guards against data corruption leaking in via missing session information in incremental summaries,
|
|
556
|
+
// protecting from bugs of potential future optimizations to attach summaries applied to non-attach summaries.
|
|
557
|
+
// Incremental summaries should have no need for originator-dependent identifiers,
|
|
558
|
+
// as they can't be attach summaries which are the only ones which should ever have non-final ids.
|
|
559
|
+
assert(
|
|
560
|
+
isSummary || incrementalEncoder === undefined,
|
|
561
|
+
0xd0d /* incrementalEncoder cannot be used when encoding originator-dependent identifiers */,
|
|
562
|
+
);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
public encodePossiblyCompressedId(id: string): string | EncodedId<EncodedIdType> {
|
|
566
|
+
return encodePossiblyCompressedId(
|
|
567
|
+
id,
|
|
568
|
+
this.idCompressor,
|
|
569
|
+
this.isSummary ? EncodedIdType.Originatorless : EncodedIdType.OriginatorDependent,
|
|
570
|
+
);
|
|
571
|
+
}
|
|
544
572
|
|
|
545
573
|
public nodeEncoderFromSchema(schemaName: TreeNodeSchemaIdentifier): NodeEncoder {
|
|
546
574
|
return getOrCreate(this.nodeEncodersFromSchema, schemaName, () =>
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { assert, fail } from "@fluidframework/core-utils/internal";
|
|
7
|
-
import { isFinalId, isStableId } from "@fluidframework/id-compressor/internal";
|
|
8
7
|
|
|
9
8
|
import {
|
|
10
9
|
type FieldKey,
|
|
@@ -24,10 +23,11 @@ import {
|
|
|
24
23
|
type NodeEncoder,
|
|
25
24
|
encodeValue,
|
|
26
25
|
} from "./compressedEncode.js";
|
|
27
|
-
import
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
import {
|
|
27
|
+
SpecialField,
|
|
28
|
+
type EncodedChunkShape,
|
|
29
|
+
type EncodedFieldShape,
|
|
30
|
+
type EncodedValueShape,
|
|
31
31
|
} from "./format/index.js";
|
|
32
32
|
|
|
33
33
|
/**
|
|
@@ -69,21 +69,9 @@ export class NodeShapeBasedEncoder extends Shape<EncodedChunkShape> implements N
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
private getValueToEncode(cursor: ITreeCursorSynchronous, context: EncoderContext): Value {
|
|
72
|
-
if (this.value ===
|
|
72
|
+
if (this.value === SpecialField.Identifier) {
|
|
73
73
|
assert(typeof cursor.value === "string", 0x9aa /* identifier must be type string */);
|
|
74
|
-
|
|
75
|
-
const sessionSpaceCompressedId = context.idCompressor.tryRecompress(cursor.value);
|
|
76
|
-
if (sessionSpaceCompressedId !== undefined) {
|
|
77
|
-
const opSpaceId = context.idCompressor.normalizeToOpSpace(sessionSpaceCompressedId);
|
|
78
|
-
// Summaries can only contain finalized op-space ids unless they also include the originator's session id somewhere.
|
|
79
|
-
// This is not the case for forest summaries at the time of writing, so non-finalized ids are instead written using
|
|
80
|
-
// their long form (by falling through to the original cursor value).
|
|
81
|
-
// A scenario where such ids can appear in the summary is in the attach summary of a tree being attached to an already-attached container.
|
|
82
|
-
if (!context.isSummary || isFinalId(opSpaceId)) {
|
|
83
|
-
return opSpaceId;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
74
|
+
return context.encodePossiblyCompressedId(cursor.value);
|
|
87
75
|
}
|
|
88
76
|
return cursor.value;
|
|
89
77
|
}
|
|
@@ -20,7 +20,10 @@ export {
|
|
|
20
20
|
type FieldBatch,
|
|
21
21
|
type FieldBatchCodec,
|
|
22
22
|
fieldBatchCodecBuilder,
|
|
23
|
+
FieldBatchDecodingContext,
|
|
23
24
|
type FieldBatchEncodingContext,
|
|
25
|
+
type IncrementalDecoder,
|
|
26
|
+
type IncrementalEncoder,
|
|
24
27
|
type IncrementalEncoderDecoder,
|
|
25
28
|
type ChunkReferenceId,
|
|
26
29
|
type IncrementalEncodingPolicy,
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
import type { FieldKey, ITreeCursorSynchronous } from "../../core/index.js";
|
|
17
17
|
import {
|
|
18
18
|
fieldBatchCodecBuilder,
|
|
19
|
+
type FieldBatchDecodingContext,
|
|
19
20
|
type FieldBatchEncodingContext,
|
|
20
21
|
} from "../chunked-forest/index.js";
|
|
21
22
|
|
|
@@ -28,13 +29,14 @@ export type FieldSet = ReadonlyMap<FieldKey, ITreeCursorSynchronous>;
|
|
|
28
29
|
export type ForestCodec = VersionDispatchingCodec<
|
|
29
30
|
FieldSet,
|
|
30
31
|
FieldBatchEncodingContext,
|
|
31
|
-
ForestFormatVersion
|
|
32
|
+
ForestFormatVersion,
|
|
33
|
+
FieldBatchDecodingContext
|
|
32
34
|
>;
|
|
33
35
|
|
|
34
36
|
function makeForestSummarizerCodec(
|
|
35
37
|
options: CodecWriteOptions,
|
|
36
38
|
version: ForestFormatVersion,
|
|
37
|
-
): CodecAndSchema<FieldSet, FieldBatchEncodingContext> {
|
|
39
|
+
): CodecAndSchema<FieldSet, FieldBatchEncodingContext, FieldBatchDecodingContext> {
|
|
38
40
|
// Performance: Since multiple places (including multiple versions of this codec) use the field batch codec,
|
|
39
41
|
// we may end up with multiple copies of it, including compiling its format validation multiple times.
|
|
40
42
|
// This is not ideal, but is not too bad as it is a small fixed number of copies and thus should not be too expensive.
|
|
@@ -55,7 +57,7 @@ function makeForestSummarizerCodec(
|
|
|
55
57
|
version,
|
|
56
58
|
};
|
|
57
59
|
},
|
|
58
|
-
decode: (data: FormatCommon, context:
|
|
60
|
+
decode: (data: FormatCommon, context: FieldBatchDecodingContext): FieldSet => {
|
|
59
61
|
const out: Map<FieldKey, ITreeCursorSynchronous> = new Map();
|
|
60
62
|
const fields = fieldBatchCodec.decode(data.fields, context);
|
|
61
63
|
assert(data.keys.length === fields.length, 0x891 /* mismatched lengths */);
|
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
import { chunkFieldSingle, defaultChunkPolicy } from "../chunked-forest/chunkTree.js";
|
|
42
42
|
import {
|
|
43
43
|
defaultIncrementalEncodingPolicy,
|
|
44
|
+
type FieldBatchDecodingContext,
|
|
44
45
|
type FieldBatchEncodingContext,
|
|
45
46
|
type IncrementalEncodingPolicy,
|
|
46
47
|
} from "../chunked-forest/index.js";
|
|
@@ -80,6 +81,7 @@ export class ForestSummarizer
|
|
|
80
81
|
private readonly forest: IEditableForest,
|
|
81
82
|
private readonly revisionTagCodec: RevisionTagCodec,
|
|
82
83
|
private readonly encoderContext: FieldBatchEncodingContext,
|
|
84
|
+
private readonly decoderContext: FieldBatchDecodingContext,
|
|
83
85
|
options: CodecWriteOptions,
|
|
84
86
|
private readonly idCompressor: IIdCompressor,
|
|
85
87
|
initialSequenceNumber: number,
|
|
@@ -160,7 +162,7 @@ export class ForestSummarizer
|
|
|
160
162
|
});
|
|
161
163
|
const encoderContext: FieldBatchEncodingContext = {
|
|
162
164
|
...this.encoderContext,
|
|
163
|
-
|
|
165
|
+
incrementalEncoder:
|
|
164
166
|
incrementalSummaryBehavior === ForestIncrementalSummaryBehavior.Incremental
|
|
165
167
|
? this.incrementalSummaryBuilder
|
|
166
168
|
: undefined,
|
|
@@ -212,10 +214,7 @@ export class ForestSummarizer
|
|
|
212
214
|
parse,
|
|
213
215
|
// TODO: this type cast assumes there are no handles, which should probably be enforced at runtime or the need for this cast should be removed altogether.
|
|
214
216
|
)) as JsonCompatibleReadOnly,
|
|
215
|
-
|
|
216
|
-
...this.encoderContext,
|
|
217
|
-
incrementalEncoderDecoder: this.incrementalSummaryBuilder,
|
|
218
|
-
},
|
|
217
|
+
this.decoderContext.withIncrementalDecoder(this.incrementalSummaryBuilder),
|
|
219
218
|
);
|
|
220
219
|
const allocator = idAllocatorFromMaxId();
|
|
221
220
|
const fieldChanges: [FieldKey, DeltaFieldChanges][] = [];
|
|
@@ -109,11 +109,14 @@ export {
|
|
|
109
109
|
FieldBatchFormatVersion,
|
|
110
110
|
makeTreeChunker,
|
|
111
111
|
fieldBatchCodecBuilder,
|
|
112
|
+
FieldBatchDecodingContext,
|
|
112
113
|
type FieldBatchEncodingContext,
|
|
113
114
|
emptyChunk,
|
|
114
115
|
combineChunks,
|
|
115
116
|
type IncrementalEncodingPolicy,
|
|
116
117
|
defaultIncrementalEncodingPolicy,
|
|
118
|
+
type IncrementalDecoder,
|
|
119
|
+
type IncrementalEncoder,
|
|
117
120
|
} from "./chunked-forest/index.js";
|
|
118
121
|
|
|
119
122
|
export {
|
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
import { newChangeAtomIdBTree, type ChangeAtomIdBTree } from "../changeAtomIdBTree.js";
|
|
36
36
|
import {
|
|
37
37
|
type FieldBatchCodec,
|
|
38
|
+
FieldBatchDecodingContext,
|
|
38
39
|
type TreeChunk,
|
|
39
40
|
chunkFieldSingle,
|
|
40
41
|
defaultChunkPolicy,
|
|
@@ -328,7 +329,6 @@ export function encodeDetachedNodes(
|
|
|
328
329
|
trees: fieldsCodec.encode(treesToEncode, {
|
|
329
330
|
encodeType: chunkCompressionStrategy,
|
|
330
331
|
schema: context.schema,
|
|
331
|
-
originatorId: context.originatorId,
|
|
332
332
|
idCompressor: context.idCompressor,
|
|
333
333
|
isSummary: context.isSummary,
|
|
334
334
|
}),
|
|
@@ -350,14 +350,18 @@ export function decodeDetachedNodes(
|
|
|
350
350
|
return undefined;
|
|
351
351
|
}
|
|
352
352
|
|
|
353
|
-
const chunks = fieldsCodec.decode(
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
353
|
+
const chunks = fieldsCodec.decode(
|
|
354
|
+
encoded.trees,
|
|
355
|
+
context.isSummary
|
|
356
|
+
? FieldBatchDecodingContext.forSummary({
|
|
357
|
+
idCompressor: context.idCompressor,
|
|
358
|
+
healing: context.healing,
|
|
359
|
+
})
|
|
360
|
+
: FieldBatchDecodingContext.forOp({
|
|
361
|
+
idCompressor: context.idCompressor,
|
|
362
|
+
originatorId: context.originatorId,
|
|
363
|
+
}),
|
|
364
|
+
);
|
|
361
365
|
const getChunk = (index: number): TreeChunk => {
|
|
362
366
|
assert(index < chunks.length, 0x898 /* out of bounds index for build chunk */);
|
|
363
367
|
return chunkFieldSingle(chunks[index] ?? oob(), {
|