@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.
Files changed (374) hide show
  1. package/.vscode/settings.json +1 -0
  2. package/CHANGELOG.md +48 -0
  3. package/api-report/tree.alpha.api.md +48 -31
  4. package/api-report/tree.beta.api.md +38 -0
  5. package/api-report/tree.legacy.beta.api.md +38 -0
  6. package/dist/core/change-family/changeFamily.d.ts +3 -10
  7. package/dist/core/change-family/changeFamily.d.ts.map +1 -1
  8. package/dist/core/change-family/changeFamily.js.map +1 -1
  9. package/dist/core/rebase/types.d.ts +2 -2
  10. package/dist/core/rebase/types.js.map +1 -1
  11. package/dist/core/schema-stored/storedSchemaRepository.d.ts +2 -2
  12. package/dist/core/schema-stored/storedSchemaRepository.js.map +1 -1
  13. package/dist/entrypoints/alpha.d.ts +1 -1
  14. package/dist/entrypoints/alpha.d.ts.map +1 -1
  15. package/dist/entrypoints/alpha.js.map +1 -1
  16. package/dist/entrypoints/beta.d.ts +1 -1
  17. package/dist/entrypoints/beta.d.ts.map +1 -1
  18. package/dist/entrypoints/beta.js.map +1 -1
  19. package/dist/entrypoints/legacy.d.ts +1 -1
  20. package/dist/entrypoints/legacy.d.ts.map +1 -1
  21. package/dist/entrypoints/legacy.js.map +1 -1
  22. package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts +19 -14
  23. package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts.map +1 -1
  24. package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.js +13 -32
  25. package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.js.map +1 -1
  26. package/dist/feature-libraries/chunked-forest/codec/codecs.d.ts +85 -28
  27. package/dist/feature-libraries/chunked-forest/codec/codecs.d.ts.map +1 -1
  28. package/dist/feature-libraries/chunked-forest/codec/codecs.js +83 -9
  29. package/dist/feature-libraries/chunked-forest/codec/codecs.js.map +1 -1
  30. package/dist/feature-libraries/chunked-forest/codec/compressedEncode.d.ts +4 -2
  31. package/dist/feature-libraries/chunked-forest/codec/compressedEncode.d.ts.map +1 -1
  32. package/dist/feature-libraries/chunked-forest/codec/compressedEncode.js +11 -0
  33. package/dist/feature-libraries/chunked-forest/codec/compressedEncode.js.map +1 -1
  34. package/dist/feature-libraries/chunked-forest/codec/index.d.ts +1 -1
  35. package/dist/feature-libraries/chunked-forest/codec/index.d.ts.map +1 -1
  36. package/dist/feature-libraries/chunked-forest/codec/index.js +2 -1
  37. package/dist/feature-libraries/chunked-forest/codec/index.js.map +1 -1
  38. package/dist/feature-libraries/chunked-forest/codec/nodeEncoder.d.ts +1 -1
  39. package/dist/feature-libraries/chunked-forest/codec/nodeEncoder.d.ts.map +1 -1
  40. package/dist/feature-libraries/chunked-forest/codec/nodeEncoder.js +3 -15
  41. package/dist/feature-libraries/chunked-forest/codec/nodeEncoder.js.map +1 -1
  42. package/dist/feature-libraries/chunked-forest/index.d.ts +1 -1
  43. package/dist/feature-libraries/chunked-forest/index.d.ts.map +1 -1
  44. package/dist/feature-libraries/chunked-forest/index.js +2 -1
  45. package/dist/feature-libraries/chunked-forest/index.js.map +1 -1
  46. package/dist/feature-libraries/forest-summary/codec.d.ts +3 -3
  47. package/dist/feature-libraries/forest-summary/codec.d.ts.map +1 -1
  48. package/dist/feature-libraries/forest-summary/codec.js.map +1 -1
  49. package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts +3 -2
  50. package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
  51. package/dist/feature-libraries/forest-summary/forestSummarizer.js +4 -6
  52. package/dist/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
  53. package/dist/feature-libraries/index.d.ts +1 -1
  54. package/dist/feature-libraries/index.d.ts.map +1 -1
  55. package/dist/feature-libraries/index.js +2 -1
  56. package/dist/feature-libraries/index.js.map +1 -1
  57. package/dist/feature-libraries/modular-schema/modularChangeCodecV1.d.ts.map +1 -1
  58. package/dist/feature-libraries/modular-schema/modularChangeCodecV1.js +9 -9
  59. package/dist/feature-libraries/modular-schema/modularChangeCodecV1.js.map +1 -1
  60. package/dist/index.d.ts +2 -2
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +2 -1
  63. package/dist/index.js.map +1 -1
  64. package/dist/packageVersion.d.ts +1 -1
  65. package/dist/packageVersion.js +1 -1
  66. package/dist/packageVersion.js.map +1 -1
  67. package/dist/shared-tree/independentView.d.ts.map +1 -1
  68. package/dist/shared-tree/independentView.js +4 -7
  69. package/dist/shared-tree/independentView.js.map +1 -1
  70. package/dist/shared-tree/index.d.ts +1 -1
  71. package/dist/shared-tree/index.d.ts.map +1 -1
  72. package/dist/shared-tree/index.js.map +1 -1
  73. package/dist/shared-tree/schematizingTreeView.d.ts +5 -5
  74. package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
  75. package/dist/shared-tree/schematizingTreeView.js.map +1 -1
  76. package/dist/shared-tree/sharedTree.d.ts +5 -0
  77. package/dist/shared-tree/sharedTree.d.ts.map +1 -1
  78. package/dist/shared-tree/sharedTree.js +7 -4
  79. package/dist/shared-tree/sharedTree.js.map +1 -1
  80. package/dist/shared-tree/transactionPostProcessor.d.ts +28 -0
  81. package/dist/shared-tree/transactionPostProcessor.d.ts.map +1 -0
  82. package/dist/shared-tree/transactionPostProcessor.js +28 -0
  83. package/dist/shared-tree/transactionPostProcessor.js.map +1 -0
  84. package/dist/shared-tree/treeAlpha.js +3 -3
  85. package/dist/shared-tree/treeAlpha.js.map +1 -1
  86. package/dist/shared-tree/treeCheckout.d.ts +16 -12
  87. package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
  88. package/dist/shared-tree/treeCheckout.js +18 -9
  89. package/dist/shared-tree/treeCheckout.js.map +1 -1
  90. package/dist/shared-tree/unhydratedTreeContext.d.ts +5 -5
  91. package/dist/shared-tree/unhydratedTreeContext.d.ts.map +1 -1
  92. package/dist/shared-tree/unhydratedTreeContext.js.map +1 -1
  93. package/dist/shared-tree-core/editManagerCodecs.d.ts +3 -2
  94. package/dist/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
  95. package/dist/shared-tree-core/editManagerCodecs.js.map +1 -1
  96. package/dist/shared-tree-core/editManagerCodecsCommons.d.ts +3 -9
  97. package/dist/shared-tree-core/editManagerCodecsCommons.d.ts.map +1 -1
  98. package/dist/shared-tree-core/editManagerCodecsCommons.js +2 -4
  99. package/dist/shared-tree-core/editManagerCodecsCommons.js.map +1 -1
  100. package/dist/shared-tree-core/editManagerCodecsV1toV4.d.ts +3 -3
  101. package/dist/shared-tree-core/editManagerCodecsV1toV4.d.ts.map +1 -1
  102. package/dist/shared-tree-core/editManagerCodecsV1toV4.js.map +1 -1
  103. package/dist/shared-tree-core/editManagerCodecsVSharedBranches.d.ts +3 -3
  104. package/dist/shared-tree-core/editManagerCodecsVSharedBranches.d.ts.map +1 -1
  105. package/dist/shared-tree-core/editManagerCodecsVSharedBranches.js.map +1 -1
  106. package/dist/shared-tree-core/editManagerSummarizer.d.ts +5 -9
  107. package/dist/shared-tree-core/editManagerSummarizer.d.ts.map +1 -1
  108. package/dist/shared-tree-core/editManagerSummarizer.js +5 -10
  109. package/dist/shared-tree-core/editManagerSummarizer.js.map +1 -1
  110. package/dist/shared-tree-core/index.d.ts +1 -1
  111. package/dist/shared-tree-core/index.d.ts.map +1 -1
  112. package/dist/shared-tree-core/index.js +3 -2
  113. package/dist/shared-tree-core/index.js.map +1 -1
  114. package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
  115. package/dist/shared-tree-core/sharedTreeCore.js +3 -1
  116. package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
  117. package/dist/shared-tree-core/transaction.d.ts +84 -9
  118. package/dist/shared-tree-core/transaction.d.ts.map +1 -1
  119. package/dist/shared-tree-core/transaction.js +74 -7
  120. package/dist/shared-tree-core/transaction.js.map +1 -1
  121. package/dist/simple-tree/api/index.d.ts +1 -1
  122. package/dist/simple-tree/api/index.d.ts.map +1 -1
  123. package/dist/simple-tree/api/index.js.map +1 -1
  124. package/dist/simple-tree/api/schemaCreationUtilities.d.ts +3 -3
  125. package/dist/simple-tree/api/schemaCreationUtilities.js +3 -3
  126. package/dist/simple-tree/api/schemaCreationUtilities.js.map +1 -1
  127. package/dist/simple-tree/api/schemaFactory.d.ts +1 -1
  128. package/dist/simple-tree/api/schemaFactory.js +2 -2
  129. package/dist/simple-tree/api/schemaFactory.js.map +1 -1
  130. package/dist/simple-tree/api/snapshotCompatibilityChecker.d.ts +2 -2
  131. package/dist/simple-tree/api/snapshotCompatibilityChecker.js +2 -2
  132. package/dist/simple-tree/api/snapshotCompatibilityChecker.js.map +1 -1
  133. package/dist/simple-tree/api/transactionTypes.d.ts +91 -28
  134. package/dist/simple-tree/api/transactionTypes.d.ts.map +1 -1
  135. package/dist/simple-tree/api/transactionTypes.js.map +1 -1
  136. package/dist/simple-tree/api/tree.d.ts +86 -22
  137. package/dist/simple-tree/api/tree.d.ts.map +1 -1
  138. package/dist/simple-tree/api/tree.js.map +1 -1
  139. package/dist/simple-tree/api/treeBeta.d.ts.map +1 -1
  140. package/dist/simple-tree/api/treeBeta.js.map +1 -1
  141. package/dist/simple-tree/core/treeNodeSchema.d.ts +7 -7
  142. package/dist/simple-tree/core/treeNodeSchema.js.map +1 -1
  143. package/dist/simple-tree/index.d.ts +1 -1
  144. package/dist/simple-tree/index.d.ts.map +1 -1
  145. package/dist/simple-tree/index.js.map +1 -1
  146. package/dist/text/index.d.ts +1 -0
  147. package/dist/text/index.d.ts.map +1 -1
  148. package/dist/text/index.js +3 -1
  149. package/dist/text/index.js.map +1 -1
  150. package/dist/text/textDomainFormatted.d.ts +69 -758
  151. package/dist/text/textDomainFormatted.d.ts.map +1 -1
  152. package/dist/text/textDomainFormatted.js +275 -322
  153. package/dist/text/textDomainFormatted.js.map +1 -1
  154. package/dist/text/textDomainFormattedDefault.d.ts +273 -0
  155. package/dist/text/textDomainFormattedDefault.d.ts.map +1 -0
  156. package/dist/text/textDomainFormattedDefault.js +94 -0
  157. package/dist/text/textDomainFormattedDefault.js.map +1 -0
  158. package/dist/util/compressedIds.d.ts +118 -0
  159. package/dist/util/compressedIds.d.ts.map +1 -0
  160. package/dist/util/compressedIds.js +133 -0
  161. package/dist/util/compressedIds.js.map +1 -0
  162. package/dist/util/index.d.ts +1 -0
  163. package/dist/util/index.d.ts.map +1 -1
  164. package/dist/util/index.js +9 -1
  165. package/dist/util/index.js.map +1 -1
  166. package/lib/core/change-family/changeFamily.d.ts +3 -10
  167. package/lib/core/change-family/changeFamily.d.ts.map +1 -1
  168. package/lib/core/change-family/changeFamily.js.map +1 -1
  169. package/lib/core/rebase/types.d.ts +2 -2
  170. package/lib/core/rebase/types.js.map +1 -1
  171. package/lib/core/schema-stored/storedSchemaRepository.d.ts +2 -2
  172. package/lib/core/schema-stored/storedSchemaRepository.js.map +1 -1
  173. package/lib/entrypoints/alpha.d.ts +1 -1
  174. package/lib/entrypoints/alpha.d.ts.map +1 -1
  175. package/lib/entrypoints/alpha.js.map +1 -1
  176. package/lib/entrypoints/beta.d.ts +1 -1
  177. package/lib/entrypoints/beta.d.ts.map +1 -1
  178. package/lib/entrypoints/beta.js.map +1 -1
  179. package/lib/entrypoints/legacy.d.ts +1 -1
  180. package/lib/entrypoints/legacy.d.ts.map +1 -1
  181. package/lib/entrypoints/legacy.js.map +1 -1
  182. package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts +19 -14
  183. package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts.map +1 -1
  184. package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.js +14 -33
  185. package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.js.map +1 -1
  186. package/lib/feature-libraries/chunked-forest/codec/codecs.d.ts +85 -28
  187. package/lib/feature-libraries/chunked-forest/codec/codecs.d.ts.map +1 -1
  188. package/lib/feature-libraries/chunked-forest/codec/codecs.js +82 -9
  189. package/lib/feature-libraries/chunked-forest/codec/codecs.js.map +1 -1
  190. package/lib/feature-libraries/chunked-forest/codec/compressedEncode.d.ts +4 -2
  191. package/lib/feature-libraries/chunked-forest/codec/compressedEncode.d.ts.map +1 -1
  192. package/lib/feature-libraries/chunked-forest/codec/compressedEncode.js +12 -1
  193. package/lib/feature-libraries/chunked-forest/codec/compressedEncode.js.map +1 -1
  194. package/lib/feature-libraries/chunked-forest/codec/index.d.ts +1 -1
  195. package/lib/feature-libraries/chunked-forest/codec/index.d.ts.map +1 -1
  196. package/lib/feature-libraries/chunked-forest/codec/index.js +1 -1
  197. package/lib/feature-libraries/chunked-forest/codec/index.js.map +1 -1
  198. package/lib/feature-libraries/chunked-forest/codec/nodeEncoder.d.ts +1 -1
  199. package/lib/feature-libraries/chunked-forest/codec/nodeEncoder.d.ts.map +1 -1
  200. package/lib/feature-libraries/chunked-forest/codec/nodeEncoder.js +3 -15
  201. package/lib/feature-libraries/chunked-forest/codec/nodeEncoder.js.map +1 -1
  202. package/lib/feature-libraries/chunked-forest/index.d.ts +1 -1
  203. package/lib/feature-libraries/chunked-forest/index.d.ts.map +1 -1
  204. package/lib/feature-libraries/chunked-forest/index.js +1 -1
  205. package/lib/feature-libraries/chunked-forest/index.js.map +1 -1
  206. package/lib/feature-libraries/forest-summary/codec.d.ts +3 -3
  207. package/lib/feature-libraries/forest-summary/codec.d.ts.map +1 -1
  208. package/lib/feature-libraries/forest-summary/codec.js.map +1 -1
  209. package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts +3 -2
  210. package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
  211. package/lib/feature-libraries/forest-summary/forestSummarizer.js +4 -6
  212. package/lib/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
  213. package/lib/feature-libraries/index.d.ts +1 -1
  214. package/lib/feature-libraries/index.d.ts.map +1 -1
  215. package/lib/feature-libraries/index.js +1 -1
  216. package/lib/feature-libraries/index.js.map +1 -1
  217. package/lib/feature-libraries/modular-schema/modularChangeCodecV1.d.ts.map +1 -1
  218. package/lib/feature-libraries/modular-schema/modularChangeCodecV1.js +10 -10
  219. package/lib/feature-libraries/modular-schema/modularChangeCodecV1.js.map +1 -1
  220. package/lib/index.d.ts +2 -2
  221. package/lib/index.d.ts.map +1 -1
  222. package/lib/index.js +1 -1
  223. package/lib/index.js.map +1 -1
  224. package/lib/packageVersion.d.ts +1 -1
  225. package/lib/packageVersion.js +1 -1
  226. package/lib/packageVersion.js.map +1 -1
  227. package/lib/shared-tree/independentView.d.ts.map +1 -1
  228. package/lib/shared-tree/independentView.js +5 -8
  229. package/lib/shared-tree/independentView.js.map +1 -1
  230. package/lib/shared-tree/index.d.ts +1 -1
  231. package/lib/shared-tree/index.d.ts.map +1 -1
  232. package/lib/shared-tree/index.js.map +1 -1
  233. package/lib/shared-tree/schematizingTreeView.d.ts +5 -5
  234. package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
  235. package/lib/shared-tree/schematizingTreeView.js.map +1 -1
  236. package/lib/shared-tree/sharedTree.d.ts +5 -0
  237. package/lib/shared-tree/sharedTree.d.ts.map +1 -1
  238. package/lib/shared-tree/sharedTree.js +8 -5
  239. package/lib/shared-tree/sharedTree.js.map +1 -1
  240. package/lib/shared-tree/transactionPostProcessor.d.ts +28 -0
  241. package/lib/shared-tree/transactionPostProcessor.d.ts.map +1 -0
  242. package/lib/shared-tree/transactionPostProcessor.js +23 -0
  243. package/lib/shared-tree/transactionPostProcessor.js.map +1 -0
  244. package/lib/shared-tree/treeAlpha.js +3 -3
  245. package/lib/shared-tree/treeAlpha.js.map +1 -1
  246. package/lib/shared-tree/treeCheckout.d.ts +16 -12
  247. package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
  248. package/lib/shared-tree/treeCheckout.js +18 -9
  249. package/lib/shared-tree/treeCheckout.js.map +1 -1
  250. package/lib/shared-tree/unhydratedTreeContext.d.ts +5 -5
  251. package/lib/shared-tree/unhydratedTreeContext.d.ts.map +1 -1
  252. package/lib/shared-tree/unhydratedTreeContext.js.map +1 -1
  253. package/lib/shared-tree-core/editManagerCodecs.d.ts +3 -2
  254. package/lib/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
  255. package/lib/shared-tree-core/editManagerCodecs.js.map +1 -1
  256. package/lib/shared-tree-core/editManagerCodecsCommons.d.ts +3 -9
  257. package/lib/shared-tree-core/editManagerCodecsCommons.d.ts.map +1 -1
  258. package/lib/shared-tree-core/editManagerCodecsCommons.js +3 -5
  259. package/lib/shared-tree-core/editManagerCodecsCommons.js.map +1 -1
  260. package/lib/shared-tree-core/editManagerCodecsV1toV4.d.ts +3 -3
  261. package/lib/shared-tree-core/editManagerCodecsV1toV4.d.ts.map +1 -1
  262. package/lib/shared-tree-core/editManagerCodecsV1toV4.js.map +1 -1
  263. package/lib/shared-tree-core/editManagerCodecsVSharedBranches.d.ts +3 -3
  264. package/lib/shared-tree-core/editManagerCodecsVSharedBranches.d.ts.map +1 -1
  265. package/lib/shared-tree-core/editManagerCodecsVSharedBranches.js.map +1 -1
  266. package/lib/shared-tree-core/editManagerSummarizer.d.ts +5 -9
  267. package/lib/shared-tree-core/editManagerSummarizer.d.ts.map +1 -1
  268. package/lib/shared-tree-core/editManagerSummarizer.js +5 -10
  269. package/lib/shared-tree-core/editManagerSummarizer.js.map +1 -1
  270. package/lib/shared-tree-core/index.d.ts +1 -1
  271. package/lib/shared-tree-core/index.d.ts.map +1 -1
  272. package/lib/shared-tree-core/index.js +1 -1
  273. package/lib/shared-tree-core/index.js.map +1 -1
  274. package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
  275. package/lib/shared-tree-core/sharedTreeCore.js +3 -1
  276. package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
  277. package/lib/shared-tree-core/transaction.d.ts +84 -9
  278. package/lib/shared-tree-core/transaction.d.ts.map +1 -1
  279. package/lib/shared-tree-core/transaction.js +73 -6
  280. package/lib/shared-tree-core/transaction.js.map +1 -1
  281. package/lib/simple-tree/api/index.d.ts +1 -1
  282. package/lib/simple-tree/api/index.d.ts.map +1 -1
  283. package/lib/simple-tree/api/index.js.map +1 -1
  284. package/lib/simple-tree/api/schemaCreationUtilities.d.ts +3 -3
  285. package/lib/simple-tree/api/schemaCreationUtilities.js +3 -3
  286. package/lib/simple-tree/api/schemaCreationUtilities.js.map +1 -1
  287. package/lib/simple-tree/api/schemaFactory.d.ts +1 -1
  288. package/lib/simple-tree/api/schemaFactory.js +2 -2
  289. package/lib/simple-tree/api/schemaFactory.js.map +1 -1
  290. package/lib/simple-tree/api/snapshotCompatibilityChecker.d.ts +2 -2
  291. package/lib/simple-tree/api/snapshotCompatibilityChecker.js +2 -2
  292. package/lib/simple-tree/api/snapshotCompatibilityChecker.js.map +1 -1
  293. package/lib/simple-tree/api/transactionTypes.d.ts +91 -28
  294. package/lib/simple-tree/api/transactionTypes.d.ts.map +1 -1
  295. package/lib/simple-tree/api/transactionTypes.js.map +1 -1
  296. package/lib/simple-tree/api/tree.d.ts +86 -22
  297. package/lib/simple-tree/api/tree.d.ts.map +1 -1
  298. package/lib/simple-tree/api/tree.js.map +1 -1
  299. package/lib/simple-tree/api/treeBeta.d.ts.map +1 -1
  300. package/lib/simple-tree/api/treeBeta.js.map +1 -1
  301. package/lib/simple-tree/core/treeNodeSchema.d.ts +7 -7
  302. package/lib/simple-tree/core/treeNodeSchema.js.map +1 -1
  303. package/lib/simple-tree/index.d.ts +1 -1
  304. package/lib/simple-tree/index.d.ts.map +1 -1
  305. package/lib/simple-tree/index.js.map +1 -1
  306. package/lib/text/index.d.ts +1 -0
  307. package/lib/text/index.d.ts.map +1 -1
  308. package/lib/text/index.js +1 -0
  309. package/lib/text/index.js.map +1 -1
  310. package/lib/text/textDomainFormatted.d.ts +69 -758
  311. package/lib/text/textDomainFormatted.d.ts.map +1 -1
  312. package/lib/text/textDomainFormatted.js +277 -324
  313. package/lib/text/textDomainFormatted.js.map +1 -1
  314. package/lib/text/textDomainFormattedDefault.d.ts +273 -0
  315. package/lib/text/textDomainFormattedDefault.d.ts.map +1 -0
  316. package/lib/text/textDomainFormattedDefault.js +91 -0
  317. package/lib/text/textDomainFormattedDefault.js.map +1 -0
  318. package/lib/util/compressedIds.d.ts +118 -0
  319. package/lib/util/compressedIds.d.ts.map +1 -0
  320. package/lib/util/compressedIds.js +124 -0
  321. package/lib/util/compressedIds.js.map +1 -0
  322. package/lib/util/index.d.ts +1 -0
  323. package/lib/util/index.d.ts.map +1 -1
  324. package/lib/util/index.js +1 -0
  325. package/lib/util/index.js.map +1 -1
  326. package/package.json +23 -23
  327. package/src/core/change-family/changeFamily.ts +3 -12
  328. package/src/core/rebase/types.ts +2 -2
  329. package/src/core/schema-stored/storedSchemaRepository.ts +2 -2
  330. package/src/entrypoints/alpha.ts +12 -8
  331. package/src/entrypoints/beta.ts +8 -0
  332. package/src/entrypoints/legacy.ts +8 -0
  333. package/src/feature-libraries/chunked-forest/codec/chunkDecoding.ts +35 -64
  334. package/src/feature-libraries/chunked-forest/codec/codecs.ts +138 -42
  335. package/src/feature-libraries/chunked-forest/codec/compressedEncode.ts +32 -4
  336. package/src/feature-libraries/chunked-forest/codec/index.ts +1 -0
  337. package/src/feature-libraries/chunked-forest/codec/nodeEncoder.ts +7 -19
  338. package/src/feature-libraries/chunked-forest/index.ts +3 -0
  339. package/src/feature-libraries/forest-summary/codec.ts +5 -3
  340. package/src/feature-libraries/forest-summary/forestSummarizer.ts +4 -5
  341. package/src/feature-libraries/index.ts +3 -0
  342. package/src/feature-libraries/modular-schema/modularChangeCodecV1.ts +13 -9
  343. package/src/index.ts +13 -8
  344. package/src/packageVersion.ts +1 -1
  345. package/src/shared-tree/independentView.ts +5 -10
  346. package/src/shared-tree/index.ts +1 -0
  347. package/src/shared-tree/schematizingTreeView.ts +25 -25
  348. package/src/shared-tree/sharedTree.ts +16 -4
  349. package/src/shared-tree/transactionPostProcessor.ts +40 -0
  350. package/src/shared-tree/treeAlpha.ts +3 -3
  351. package/src/shared-tree/treeCheckout.ts +61 -44
  352. package/src/shared-tree/unhydratedTreeContext.ts +18 -15
  353. package/src/shared-tree-core/editManagerCodecs.ts +3 -2
  354. package/src/shared-tree-core/editManagerCodecsCommons.ts +10 -14
  355. package/src/shared-tree-core/editManagerCodecsV1toV4.ts +3 -2
  356. package/src/shared-tree-core/editManagerCodecsVSharedBranches.ts +3 -2
  357. package/src/shared-tree-core/editManagerSummarizer.ts +5 -9
  358. package/src/shared-tree-core/index.ts +8 -5
  359. package/src/shared-tree-core/sharedTreeCore.ts +3 -2
  360. package/src/shared-tree-core/transaction.ts +148 -18
  361. package/src/simple-tree/api/index.ts +13 -9
  362. package/src/simple-tree/api/schemaCreationUtilities.ts +3 -3
  363. package/src/simple-tree/api/schemaFactory.ts +2 -2
  364. package/src/simple-tree/api/snapshotCompatibilityChecker.ts +2 -2
  365. package/src/simple-tree/api/transactionTypes.ts +111 -39
  366. package/src/simple-tree/api/tree.ts +141 -47
  367. package/src/simple-tree/api/treeBeta.ts +2 -0
  368. package/src/simple-tree/core/treeNodeSchema.ts +7 -7
  369. package/src/simple-tree/index.ts +12 -8
  370. package/src/text/index.ts +1 -0
  371. package/src/text/textDomainFormatted.ts +520 -415
  372. package/src/text/textDomainFormattedDefault.ts +150 -0
  373. package/src/util/compressedIds.ts +216 -0
  374. 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
- SessionId,
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
- // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Referenced by doc comments
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
- * See {@link FieldBatchEncodingContext.healUnresolvableIdentifiersOnDecode}.
68
+ * Compressor which can decompress session-space identifiers from {@link resolveEncodedId} as needed.
73
69
  */
74
- healUnresolvableIdentifiersOnDecode?: boolean;
70
+ readonly idCompressor: Pick<IIdCompressor, "decompress">;
75
71
  /**
76
- * See {@link FieldBatchEncodingContext.sharedObjectId}.
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
- sharedObjectId?: string;
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
- if (typeof streamValue === "string") {
285
- return streamValue;
286
- }
287
- const idCompressor = idDecodingContext.idCompressor;
288
- // OpSpaceCompressedIds are negative, and require a session-id to compute their value.
289
- // Due to a bug, we have some special casing for them (see below).
290
- if (
291
- idDecodingContext.isSummary === true &&
292
- !isFinalId(streamValue as OpSpaceCompressedId)
293
- ) {
294
- if (
295
- idDecodingContext.healUnresolvableIdentifiersOnDecode === true &&
296
- idDecodingContext.sharedObjectId !== undefined
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 { IIdCompressor, SessionId } from "@fluidframework/id-compressor";
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 { brandedNumberType, type Brand } from "../../../util/index.js";
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
- * An encoder / decoder for encoding and decoding of incremental fields.
107
- * This will be defined if incremental encoding is supported and enabled.
122
+ * Encoder for incremental fields. Defined when incremental encoding is
123
+ * supported and enabled.
108
124
  */
109
- readonly incrementalEncoderDecoder?: IncrementalEncoderDecoder;
125
+ readonly incrementalEncoder?: IncrementalEncoder;
110
126
  /**
111
- * `true` when encoding to or decoding from a summary blob. `false` for
112
- * op-stream encode/decode paths and for utility encoders that are not
113
- * tied to a persisted document. Healing behavior is gated on this flag.
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
- * If `true`, when an op-space compressed ID encountered while decoding
118
- * cannot be resolved by the local id-compressor (e.g. the attach-summary
119
- * blob's originator session state was stripped), a deterministic stable
120
- * UUID derived from `sharedObjectId` is returned instead of throwing.
121
- * @remarks
122
- * Off by default. Used only to recover documents whose attach summary was
123
- * written with non-finalized op-space IDs before the encode-side fix
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
- readonly healUnresolvableIdentifiersOnDecode?: boolean;
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
- * The SharedTree's shared-object id, used as input to the deterministic
130
- * UUID derivation when `healUnresolvableIdentifiersOnDecode` triggers. Required
131
- * for that path; ignored otherwise.
132
- * @remarks
133
- * This allows us to ensure that multiple attaches,
134
- * in the same or different documents, with the same session offsets, get different UUIDs.
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
- readonly sharedObjectId?: string;
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.incrementalEncoderDecoder;
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: FieldBatchEncodingContext,
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 { getOrCreate } from "../../../util/index.js";
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 implements NodeEncodeBuilder, FieldEncodeBuilder {
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
- public readonly idCompressor: IIdCompressor,
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, () =>
@@ -13,6 +13,7 @@ export type { FieldBatch } from "./fieldBatch.js";
13
13
  export {
14
14
  type FieldBatchCodec,
15
15
  fieldBatchCodecBuilder,
16
+ FieldBatchDecodingContext,
16
17
  type FieldBatchEncodingContext,
17
18
  type IncrementalEncoderDecoder,
18
19
  type IncrementalEncoder,
@@ -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 type {
28
- EncodedChunkShape,
29
- EncodedFieldShape,
30
- EncodedValueShape,
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 === 0) {
72
+ if (this.value === SpecialField.Identifier) {
73
73
  assert(typeof cursor.value === "string", 0x9aa /* identifier must be type string */);
74
- if (isStableId(cursor.value)) {
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: FieldBatchEncodingContext): FieldSet => {
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
- incrementalEncoderDecoder:
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(encoded.trees, {
354
- encodeType: chunkCompressionStrategy,
355
- originatorId: context.originatorId,
356
- idCompressor: context.idCompressor,
357
- isSummary: context.isSummary,
358
- healUnresolvableIdentifiersOnDecode: context.healUnresolvableIdentifiersOnDecode,
359
- sharedObjectId: context.sharedObjectId,
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(), {