@fluidframework/tree 2.101.1 → 2.103.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 (609) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/api-report/tree.alpha.api.md +19 -0
  3. package/dist/codec/codec.d.ts +22 -53
  4. package/dist/codec/codec.d.ts.map +1 -1
  5. package/dist/codec/codec.js +7 -44
  6. package/dist/codec/codec.js.map +1 -1
  7. package/dist/codec/index.d.ts +1 -1
  8. package/dist/codec/index.d.ts.map +1 -1
  9. package/dist/codec/index.js +2 -2
  10. package/dist/codec/index.js.map +1 -1
  11. package/dist/codec/versioned/codec.d.ts +56 -28
  12. package/dist/codec/versioned/codec.d.ts.map +1 -1
  13. package/dist/codec/versioned/codec.js +29 -12
  14. package/dist/codec/versioned/codec.js.map +1 -1
  15. package/dist/codec/versioned/format.d.ts +5 -4
  16. package/dist/codec/versioned/format.d.ts.map +1 -1
  17. package/dist/codec/versioned/format.js +26 -3
  18. package/dist/codec/versioned/format.js.map +1 -1
  19. package/dist/codec/versioned/index.d.ts +1 -1
  20. package/dist/codec/versioned/index.d.ts.map +1 -1
  21. package/dist/codec/versioned/index.js +2 -2
  22. package/dist/codec/versioned/index.js.map +1 -1
  23. package/dist/core/rebase/types.d.ts +4 -3
  24. package/dist/core/rebase/types.d.ts.map +1 -1
  25. package/dist/core/rebase/types.js +27 -4
  26. package/dist/core/rebase/types.js.map +1 -1
  27. package/dist/core/schema-stored/formatV1.d.ts +16 -15
  28. package/dist/core/schema-stored/formatV1.d.ts.map +1 -1
  29. package/dist/core/schema-stored/formatV1.js +31 -8
  30. package/dist/core/schema-stored/formatV1.js.map +1 -1
  31. package/dist/core/schema-stored/formatV2.d.ts +29 -28
  32. package/dist/core/schema-stored/formatV2.d.ts.map +1 -1
  33. package/dist/core/schema-stored/formatV2.js +33 -10
  34. package/dist/core/schema-stored/formatV2.js.map +1 -1
  35. package/dist/core/tree/deltaUtil.d.ts +2 -2
  36. package/dist/core/tree/deltaUtil.js +2 -2
  37. package/dist/core/tree/deltaUtil.js.map +1 -1
  38. package/dist/core/tree/detachedFieldIndexCodecV1.d.ts.map +1 -1
  39. package/dist/core/tree/detachedFieldIndexCodecV1.js +3 -2
  40. package/dist/core/tree/detachedFieldIndexCodecV1.js.map +1 -1
  41. package/dist/core/tree/detachedFieldIndexCodecV2.d.ts.map +1 -1
  42. package/dist/core/tree/detachedFieldIndexCodecV2.js +4 -2
  43. package/dist/core/tree/detachedFieldIndexCodecV2.js.map +1 -1
  44. package/dist/core/tree/detachedFieldIndexCodecs.d.ts +3 -3
  45. package/dist/core/tree/detachedFieldIndexCodecs.d.ts.map +1 -1
  46. package/dist/core/tree/detachedFieldIndexCodecs.js +1 -1
  47. package/dist/core/tree/detachedFieldIndexCodecs.js.map +1 -1
  48. package/dist/core/tree/detachedFieldIndexFormatCommon.d.ts +11 -10
  49. package/dist/core/tree/detachedFieldIndexFormatCommon.d.ts.map +1 -1
  50. package/dist/core/tree/detachedFieldIndexFormatCommon.js +33 -10
  51. package/dist/core/tree/detachedFieldIndexFormatCommon.js.map +1 -1
  52. package/dist/core/tree/detachedFieldIndexFormatV2.d.ts +7 -6
  53. package/dist/core/tree/detachedFieldIndexFormatV2.d.ts.map +1 -1
  54. package/dist/core/tree/detachedFieldIndexFormatV2.js +25 -2
  55. package/dist/core/tree/detachedFieldIndexFormatV2.js.map +1 -1
  56. package/dist/core/tree/persistedTreeTextFormat.d.ts +19 -18
  57. package/dist/core/tree/persistedTreeTextFormat.d.ts.map +1 -1
  58. package/dist/core/tree/persistedTreeTextFormat.js +33 -10
  59. package/dist/core/tree/persistedTreeTextFormat.js.map +1 -1
  60. package/dist/feature-libraries/chunked-forest/chunkTree.d.ts +38 -1
  61. package/dist/feature-libraries/chunked-forest/chunkTree.d.ts.map +1 -1
  62. package/dist/feature-libraries/chunked-forest/chunkTree.js +63 -5
  63. package/dist/feature-libraries/chunked-forest/chunkTree.js.map +1 -1
  64. package/dist/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
  65. package/dist/feature-libraries/chunked-forest/chunkedForest.js +18 -4
  66. package/dist/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
  67. package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts +34 -2
  68. package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts.map +1 -1
  69. package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.js +106 -3
  70. package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.js.map +1 -1
  71. package/dist/feature-libraries/chunked-forest/codec/codecs.d.ts +5 -5
  72. package/dist/feature-libraries/chunked-forest/codec/codecs.d.ts.map +1 -1
  73. package/dist/feature-libraries/chunked-forest/codec/codecs.js +2 -2
  74. package/dist/feature-libraries/chunked-forest/codec/codecs.js.map +1 -1
  75. package/dist/feature-libraries/chunked-forest/codec/compressedEncode.d.ts +7 -7
  76. package/dist/feature-libraries/chunked-forest/codec/compressedEncode.d.ts.map +1 -1
  77. package/dist/feature-libraries/chunked-forest/codec/compressedEncode.js.map +1 -1
  78. package/dist/feature-libraries/chunked-forest/codec/format/formatGeneric.d.ts +13 -12
  79. package/dist/feature-libraries/chunked-forest/codec/format/formatGeneric.d.ts.map +1 -1
  80. package/dist/feature-libraries/chunked-forest/codec/format/formatGeneric.js +36 -13
  81. package/dist/feature-libraries/chunked-forest/codec/format/formatGeneric.js.map +1 -1
  82. package/dist/feature-libraries/chunked-forest/codec/format/formatV1.d.ts +36 -35
  83. package/dist/feature-libraries/chunked-forest/codec/format/formatV1.d.ts.map +1 -1
  84. package/dist/feature-libraries/chunked-forest/codec/format/formatV1.js +41 -18
  85. package/dist/feature-libraries/chunked-forest/codec/format/formatV1.js.map +1 -1
  86. package/dist/feature-libraries/chunked-forest/codec/format/formatV2.d.ts +35 -14
  87. package/dist/feature-libraries/chunked-forest/codec/format/formatV2.d.ts.map +1 -1
  88. package/dist/feature-libraries/chunked-forest/codec/format/formatV2.js +35 -6
  89. package/dist/feature-libraries/chunked-forest/codec/format/formatV2.js.map +1 -1
  90. package/dist/feature-libraries/chunked-forest/codec/format/formatVText.d.ts +106 -0
  91. package/dist/feature-libraries/chunked-forest/codec/format/formatVText.d.ts.map +1 -0
  92. package/dist/feature-libraries/chunked-forest/codec/format/formatVText.js +67 -0
  93. package/dist/feature-libraries/chunked-forest/codec/format/formatVText.js.map +1 -0
  94. package/dist/feature-libraries/chunked-forest/codec/format/index.d.ts +2 -1
  95. package/dist/feature-libraries/chunked-forest/codec/format/index.d.ts.map +1 -1
  96. package/dist/feature-libraries/chunked-forest/codec/format/index.js +5 -1
  97. package/dist/feature-libraries/chunked-forest/codec/format/index.js.map +1 -1
  98. package/dist/feature-libraries/chunked-forest/codec/format/versions.d.ts +38 -4
  99. package/dist/feature-libraries/chunked-forest/codec/format/versions.d.ts.map +1 -1
  100. package/dist/feature-libraries/chunked-forest/codec/format/versions.js +7 -1
  101. package/dist/feature-libraries/chunked-forest/codec/format/versions.js.map +1 -1
  102. package/dist/feature-libraries/chunked-forest/codec/nodeEncoder.d.ts +7 -7
  103. package/dist/feature-libraries/chunked-forest/codec/nodeEncoder.d.ts.map +1 -1
  104. package/dist/feature-libraries/chunked-forest/codec/nodeEncoder.js +1 -2
  105. package/dist/feature-libraries/chunked-forest/codec/nodeEncoder.js.map +1 -1
  106. package/dist/feature-libraries/chunked-forest/uniformChunk.d.ts +66 -14
  107. package/dist/feature-libraries/chunked-forest/uniformChunk.d.ts.map +1 -1
  108. package/dist/feature-libraries/chunked-forest/uniformChunk.js +101 -36
  109. package/dist/feature-libraries/chunked-forest/uniformChunk.js.map +1 -1
  110. package/dist/feature-libraries/default-schema/defaultEditBuilder.d.ts.map +1 -1
  111. package/dist/feature-libraries/default-schema/defaultEditBuilder.js +36 -14
  112. package/dist/feature-libraries/default-schema/defaultEditBuilder.js.map +1 -1
  113. package/dist/feature-libraries/forest-summary/codec.d.ts +5 -4
  114. package/dist/feature-libraries/forest-summary/codec.d.ts.map +1 -1
  115. package/dist/feature-libraries/forest-summary/codec.js +2 -2
  116. package/dist/feature-libraries/forest-summary/codec.js.map +1 -1
  117. package/dist/feature-libraries/forest-summary/formatCommon.d.ts +6 -5
  118. package/dist/feature-libraries/forest-summary/formatCommon.d.ts.map +1 -1
  119. package/dist/feature-libraries/forest-summary/formatCommon.js +26 -3
  120. package/dist/feature-libraries/forest-summary/formatCommon.js.map +1 -1
  121. package/dist/feature-libraries/modular-schema/genericFieldKindFormat.d.ts +4 -3
  122. package/dist/feature-libraries/modular-schema/genericFieldKindFormat.d.ts.map +1 -1
  123. package/dist/feature-libraries/modular-schema/genericFieldKindFormat.js +26 -3
  124. package/dist/feature-libraries/modular-schema/genericFieldKindFormat.js.map +1 -1
  125. package/dist/feature-libraries/modular-schema/modularChangeFormatV1.d.ts +45 -44
  126. package/dist/feature-libraries/modular-schema/modularChangeFormatV1.d.ts.map +1 -1
  127. package/dist/feature-libraries/modular-schema/modularChangeFormatV1.js +48 -25
  128. package/dist/feature-libraries/modular-schema/modularChangeFormatV1.js.map +1 -1
  129. package/dist/feature-libraries/modular-schema/modularChangeFormatV2.d.ts +23 -22
  130. package/dist/feature-libraries/modular-schema/modularChangeFormatV2.d.ts.map +1 -1
  131. package/dist/feature-libraries/modular-schema/modularChangeFormatV2.js +29 -6
  132. package/dist/feature-libraries/modular-schema/modularChangeFormatV2.js.map +1 -1
  133. package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts +1 -1
  134. package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
  135. package/dist/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
  136. package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV1.d.ts +9 -8
  137. package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV1.d.ts.map +1 -1
  138. package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV1.js +31 -8
  139. package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV1.js.map +1 -1
  140. package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV2.d.ts +14 -13
  141. package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV2.d.ts.map +1 -1
  142. package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV2.js +34 -11
  143. package/dist/feature-libraries/optional-field/optionalFieldChangeFormatV2.js.map +1 -1
  144. package/dist/feature-libraries/schema-edits/schemaChangeFormat.d.ts +5 -4
  145. package/dist/feature-libraries/schema-edits/schemaChangeFormat.d.ts.map +1 -1
  146. package/dist/feature-libraries/schema-edits/schemaChangeFormat.js +25 -2
  147. package/dist/feature-libraries/schema-edits/schemaChangeFormat.js.map +1 -1
  148. package/dist/feature-libraries/schema-index/codec.d.ts +2 -2
  149. package/dist/feature-libraries/schema-index/codec.d.ts.map +1 -1
  150. package/dist/feature-libraries/schema-index/codec.js +1 -1
  151. package/dist/feature-libraries/schema-index/codec.js.map +1 -1
  152. package/dist/feature-libraries/schema-index/formatV1.d.ts +15 -14
  153. package/dist/feature-libraries/schema-index/formatV1.d.ts.map +1 -1
  154. package/dist/feature-libraries/schema-index/formatV1.js +27 -4
  155. package/dist/feature-libraries/schema-index/formatV1.js.map +1 -1
  156. package/dist/feature-libraries/schema-index/formatV2.d.ts +20 -19
  157. package/dist/feature-libraries/schema-index/formatV2.d.ts.map +1 -1
  158. package/dist/feature-libraries/schema-index/formatV2.js +27 -4
  159. package/dist/feature-libraries/schema-index/formatV2.js.map +1 -1
  160. package/dist/feature-libraries/sequence-field/compose.d.ts.map +1 -1
  161. package/dist/feature-libraries/sequence-field/compose.js +1 -3
  162. package/dist/feature-libraries/sequence-field/compose.js.map +1 -1
  163. package/dist/feature-libraries/sequence-field/formatV1.d.ts +283 -282
  164. package/dist/feature-libraries/sequence-field/formatV1.d.ts.map +1 -1
  165. package/dist/feature-libraries/sequence-field/formatV1.js +63 -40
  166. package/dist/feature-libraries/sequence-field/formatV1.js.map +1 -1
  167. package/dist/feature-libraries/sequence-field/formatV2.d.ts +180 -179
  168. package/dist/feature-libraries/sequence-field/formatV2.d.ts.map +1 -1
  169. package/dist/feature-libraries/sequence-field/formatV2.js +55 -32
  170. package/dist/feature-libraries/sequence-field/formatV2.js.map +1 -1
  171. package/dist/feature-libraries/sequence-field/formatV3.d.ts +126 -125
  172. package/dist/feature-libraries/sequence-field/formatV3.d.ts.map +1 -1
  173. package/dist/feature-libraries/sequence-field/formatV3.js +27 -4
  174. package/dist/feature-libraries/sequence-field/formatV3.js.map +1 -1
  175. package/dist/index.d.ts +1 -1
  176. package/dist/index.d.ts.map +1 -1
  177. package/dist/index.js +3 -1
  178. package/dist/index.js.map +1 -1
  179. package/dist/packageVersion.d.ts +1 -1
  180. package/dist/packageVersion.js +1 -1
  181. package/dist/packageVersion.js.map +1 -1
  182. package/dist/shared-tree/isAuditableFromOutcome.d.ts +20 -0
  183. package/dist/shared-tree/isAuditableFromOutcome.d.ts.map +1 -0
  184. package/dist/shared-tree/isAuditableFromOutcome.js +36 -0
  185. package/dist/shared-tree/isAuditableFromOutcome.js.map +1 -0
  186. package/dist/shared-tree/sharedTree.d.ts +2 -2
  187. package/dist/shared-tree/sharedTree.d.ts.map +1 -1
  188. package/dist/shared-tree/sharedTree.js.map +1 -1
  189. package/dist/shared-tree/sharedTreeChangeFormat.d.ts +8 -7
  190. package/dist/shared-tree/sharedTreeChangeFormat.d.ts.map +1 -1
  191. package/dist/shared-tree/sharedTreeChangeFormat.js +28 -5
  192. package/dist/shared-tree/sharedTreeChangeFormat.js.map +1 -1
  193. package/dist/shared-tree/treeCheckout.d.ts +5 -3
  194. package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
  195. package/dist/shared-tree/treeCheckout.js +37 -8
  196. package/dist/shared-tree/treeCheckout.js.map +1 -1
  197. package/dist/shared-tree-core/editManager.d.ts +2 -2
  198. package/dist/shared-tree-core/editManager.d.ts.map +1 -1
  199. package/dist/shared-tree-core/editManager.js.map +1 -1
  200. package/dist/shared-tree-core/editManagerCodecs.d.ts +3 -3
  201. package/dist/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
  202. package/dist/shared-tree-core/editManagerCodecs.js +2 -2
  203. package/dist/shared-tree-core/editManagerCodecs.js.map +1 -1
  204. package/dist/shared-tree-core/editManagerFormatCommons.d.ts +35 -34
  205. package/dist/shared-tree-core/editManagerFormatCommons.d.ts.map +1 -1
  206. package/dist/shared-tree-core/editManagerFormatCommons.js +39 -16
  207. package/dist/shared-tree-core/editManagerFormatCommons.js.map +1 -1
  208. package/dist/shared-tree-core/editManagerFormatV1toV4.d.ts +15 -15
  209. package/dist/shared-tree-core/editManagerFormatV1toV4.d.ts.map +1 -1
  210. package/dist/shared-tree-core/editManagerFormatV1toV4.js +33 -10
  211. package/dist/shared-tree-core/editManagerFormatV1toV4.js.map +1 -1
  212. package/dist/shared-tree-core/editManagerFormatVSharedBranches.d.ts +40 -40
  213. package/dist/shared-tree-core/editManagerFormatVSharedBranches.d.ts.map +1 -1
  214. package/dist/shared-tree-core/editManagerFormatVSharedBranches.js +27 -4
  215. package/dist/shared-tree-core/editManagerFormatVSharedBranches.js.map +1 -1
  216. package/dist/shared-tree-core/messageCodecVSharedBranches.d.ts.map +1 -1
  217. package/dist/shared-tree-core/messageCodecVSharedBranches.js +25 -2
  218. package/dist/shared-tree-core/messageCodecVSharedBranches.js.map +1 -1
  219. package/dist/shared-tree-core/messageCodecs.d.ts +3 -3
  220. package/dist/shared-tree-core/messageCodecs.d.ts.map +1 -1
  221. package/dist/shared-tree-core/messageCodecs.js +2 -2
  222. package/dist/shared-tree-core/messageCodecs.js.map +1 -1
  223. package/dist/shared-tree-core/messageFormatV1ToV4.d.ts +5 -5
  224. package/dist/shared-tree-core/messageFormatV1ToV4.d.ts.map +1 -1
  225. package/dist/shared-tree-core/messageFormatV1ToV4.js +31 -8
  226. package/dist/shared-tree-core/messageFormatV1ToV4.js.map +1 -1
  227. package/dist/shared-tree-core/messageFormatVSharedBranches.d.ts +7 -7
  228. package/dist/shared-tree-core/messageFormatVSharedBranches.d.ts.map +1 -1
  229. package/dist/shared-tree-core/messageFormatVSharedBranches.js +29 -6
  230. package/dist/shared-tree-core/messageFormatVSharedBranches.js.map +1 -1
  231. package/dist/simple-tree/core/treeNodeKernel.d.ts +5 -0
  232. package/dist/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
  233. package/dist/simple-tree/core/treeNodeKernel.js +62 -24
  234. package/dist/simple-tree/core/treeNodeKernel.js.map +1 -1
  235. package/dist/simple-tree/simpleSchemaFormatV1.d.ts +121 -120
  236. package/dist/simple-tree/simpleSchemaFormatV1.d.ts.map +1 -1
  237. package/dist/simple-tree/simpleSchemaFormatV1.js +54 -31
  238. package/dist/simple-tree/simpleSchemaFormatV1.js.map +1 -1
  239. package/dist/text/codePointUtils.d.ts +48 -0
  240. package/dist/text/codePointUtils.d.ts.map +1 -0
  241. package/dist/text/codePointUtils.js +80 -0
  242. package/dist/text/codePointUtils.js.map +1 -0
  243. package/dist/text/index.d.ts +1 -0
  244. package/dist/text/index.d.ts.map +1 -1
  245. package/dist/text/index.js +4 -1
  246. package/dist/text/index.js.map +1 -1
  247. package/dist/text/textDomain.d.ts +93 -1
  248. package/dist/text/textDomain.d.ts.map +1 -1
  249. package/dist/text/textDomain.js +65 -8
  250. package/dist/text/textDomain.js.map +1 -1
  251. package/dist/text/textDomainFormatted.d.ts +24 -6
  252. package/dist/text/textDomainFormatted.d.ts.map +1 -1
  253. package/dist/text/textDomainFormatted.js +29 -1
  254. package/dist/text/textDomainFormatted.js.map +1 -1
  255. package/dist/treeFactory.d.ts.map +1 -1
  256. package/dist/treeFactory.js +9 -7
  257. package/dist/treeFactory.js.map +1 -1
  258. package/dist/util/breakable.d.ts +7 -1
  259. package/dist/util/breakable.d.ts.map +1 -1
  260. package/dist/util/breakable.js +18 -4
  261. package/dist/util/breakable.js.map +1 -1
  262. package/dist/util/typeboxBrand.d.ts +1 -1
  263. package/dist/util/typeboxBrand.d.ts.map +1 -1
  264. package/dist/util/typeboxBrand.js +26 -3
  265. package/dist/util/typeboxBrand.js.map +1 -1
  266. package/dist/util/utils.d.ts +2 -2
  267. package/dist/util/utils.d.ts.map +1 -1
  268. package/dist/util/utils.js +25 -2
  269. package/dist/util/utils.js.map +1 -1
  270. package/eslint.config.mts +44 -0
  271. package/lib/codec/codec.d.ts +22 -53
  272. package/lib/codec/codec.d.ts.map +1 -1
  273. package/lib/codec/codec.js +7 -44
  274. package/lib/codec/codec.js.map +1 -1
  275. package/lib/codec/index.d.ts +1 -1
  276. package/lib/codec/index.d.ts.map +1 -1
  277. package/lib/codec/index.js +1 -1
  278. package/lib/codec/index.js.map +1 -1
  279. package/lib/codec/versioned/codec.d.ts +56 -28
  280. package/lib/codec/versioned/codec.d.ts.map +1 -1
  281. package/lib/codec/versioned/codec.js +27 -10
  282. package/lib/codec/versioned/codec.js.map +1 -1
  283. package/lib/codec/versioned/format.d.ts +5 -4
  284. package/lib/codec/versioned/format.d.ts.map +1 -1
  285. package/lib/codec/versioned/format.js +1 -1
  286. package/lib/codec/versioned/format.js.map +1 -1
  287. package/lib/codec/versioned/index.d.ts +1 -1
  288. package/lib/codec/versioned/index.d.ts.map +1 -1
  289. package/lib/codec/versioned/index.js +1 -1
  290. package/lib/codec/versioned/index.js.map +1 -1
  291. package/lib/core/rebase/types.d.ts +4 -3
  292. package/lib/core/rebase/types.d.ts.map +1 -1
  293. package/lib/core/rebase/types.js +1 -1
  294. package/lib/core/rebase/types.js.map +1 -1
  295. package/lib/core/schema-stored/formatV1.d.ts +16 -15
  296. package/lib/core/schema-stored/formatV1.d.ts.map +1 -1
  297. package/lib/core/schema-stored/formatV1.js +1 -1
  298. package/lib/core/schema-stored/formatV1.js.map +1 -1
  299. package/lib/core/schema-stored/formatV2.d.ts +29 -28
  300. package/lib/core/schema-stored/formatV2.d.ts.map +1 -1
  301. package/lib/core/schema-stored/formatV2.js +1 -1
  302. package/lib/core/schema-stored/formatV2.js.map +1 -1
  303. package/lib/core/tree/deltaUtil.d.ts +2 -2
  304. package/lib/core/tree/deltaUtil.js +2 -2
  305. package/lib/core/tree/deltaUtil.js.map +1 -1
  306. package/lib/core/tree/detachedFieldIndexCodecV1.d.ts.map +1 -1
  307. package/lib/core/tree/detachedFieldIndexCodecV1.js +3 -2
  308. package/lib/core/tree/detachedFieldIndexCodecV1.js.map +1 -1
  309. package/lib/core/tree/detachedFieldIndexCodecV2.d.ts.map +1 -1
  310. package/lib/core/tree/detachedFieldIndexCodecV2.js +5 -3
  311. package/lib/core/tree/detachedFieldIndexCodecV2.js.map +1 -1
  312. package/lib/core/tree/detachedFieldIndexCodecs.d.ts +3 -3
  313. package/lib/core/tree/detachedFieldIndexCodecs.d.ts.map +1 -1
  314. package/lib/core/tree/detachedFieldIndexCodecs.js +2 -2
  315. package/lib/core/tree/detachedFieldIndexCodecs.js.map +1 -1
  316. package/lib/core/tree/detachedFieldIndexFormatCommon.d.ts +11 -10
  317. package/lib/core/tree/detachedFieldIndexFormatCommon.d.ts.map +1 -1
  318. package/lib/core/tree/detachedFieldIndexFormatCommon.js +1 -1
  319. package/lib/core/tree/detachedFieldIndexFormatCommon.js.map +1 -1
  320. package/lib/core/tree/detachedFieldIndexFormatV2.d.ts +7 -6
  321. package/lib/core/tree/detachedFieldIndexFormatV2.d.ts.map +1 -1
  322. package/lib/core/tree/detachedFieldIndexFormatV2.js +1 -1
  323. package/lib/core/tree/detachedFieldIndexFormatV2.js.map +1 -1
  324. package/lib/core/tree/persistedTreeTextFormat.d.ts +19 -18
  325. package/lib/core/tree/persistedTreeTextFormat.d.ts.map +1 -1
  326. package/lib/core/tree/persistedTreeTextFormat.js +1 -1
  327. package/lib/core/tree/persistedTreeTextFormat.js.map +1 -1
  328. package/lib/feature-libraries/chunked-forest/chunkTree.d.ts +38 -1
  329. package/lib/feature-libraries/chunked-forest/chunkTree.d.ts.map +1 -1
  330. package/lib/feature-libraries/chunked-forest/chunkTree.js +62 -5
  331. package/lib/feature-libraries/chunked-forest/chunkTree.js.map +1 -1
  332. package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
  333. package/lib/feature-libraries/chunked-forest/chunkedForest.js +20 -6
  334. package/lib/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
  335. package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts +34 -2
  336. package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts.map +1 -1
  337. package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.js +102 -2
  338. package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.js.map +1 -1
  339. package/lib/feature-libraries/chunked-forest/codec/codecs.d.ts +5 -5
  340. package/lib/feature-libraries/chunked-forest/codec/codecs.d.ts.map +1 -1
  341. package/lib/feature-libraries/chunked-forest/codec/codecs.js +3 -3
  342. package/lib/feature-libraries/chunked-forest/codec/codecs.js.map +1 -1
  343. package/lib/feature-libraries/chunked-forest/codec/compressedEncode.d.ts +7 -7
  344. package/lib/feature-libraries/chunked-forest/codec/compressedEncode.d.ts.map +1 -1
  345. package/lib/feature-libraries/chunked-forest/codec/compressedEncode.js.map +1 -1
  346. package/lib/feature-libraries/chunked-forest/codec/format/formatGeneric.d.ts +13 -12
  347. package/lib/feature-libraries/chunked-forest/codec/format/formatGeneric.d.ts.map +1 -1
  348. package/lib/feature-libraries/chunked-forest/codec/format/formatGeneric.js +1 -1
  349. package/lib/feature-libraries/chunked-forest/codec/format/formatGeneric.js.map +1 -1
  350. package/lib/feature-libraries/chunked-forest/codec/format/formatV1.d.ts +36 -35
  351. package/lib/feature-libraries/chunked-forest/codec/format/formatV1.d.ts.map +1 -1
  352. package/lib/feature-libraries/chunked-forest/codec/format/formatV1.js +1 -1
  353. package/lib/feature-libraries/chunked-forest/codec/format/formatV1.js.map +1 -1
  354. package/lib/feature-libraries/chunked-forest/codec/format/formatV2.d.ts +35 -14
  355. package/lib/feature-libraries/chunked-forest/codec/format/formatV2.d.ts.map +1 -1
  356. package/lib/feature-libraries/chunked-forest/codec/format/formatV2.js +9 -3
  357. package/lib/feature-libraries/chunked-forest/codec/format/formatV2.js.map +1 -1
  358. package/lib/feature-libraries/chunked-forest/codec/format/formatVText.d.ts +106 -0
  359. package/lib/feature-libraries/chunked-forest/codec/format/formatVText.d.ts.map +1 -0
  360. package/lib/feature-libraries/chunked-forest/codec/format/formatVText.js +41 -0
  361. package/lib/feature-libraries/chunked-forest/codec/format/formatVText.js.map +1 -0
  362. package/lib/feature-libraries/chunked-forest/codec/format/index.d.ts +2 -1
  363. package/lib/feature-libraries/chunked-forest/codec/format/index.d.ts.map +1 -1
  364. package/lib/feature-libraries/chunked-forest/codec/format/index.js +2 -1
  365. package/lib/feature-libraries/chunked-forest/codec/format/index.js.map +1 -1
  366. package/lib/feature-libraries/chunked-forest/codec/format/versions.d.ts +38 -4
  367. package/lib/feature-libraries/chunked-forest/codec/format/versions.d.ts.map +1 -1
  368. package/lib/feature-libraries/chunked-forest/codec/format/versions.js +6 -0
  369. package/lib/feature-libraries/chunked-forest/codec/format/versions.js.map +1 -1
  370. package/lib/feature-libraries/chunked-forest/codec/nodeEncoder.d.ts +7 -7
  371. package/lib/feature-libraries/chunked-forest/codec/nodeEncoder.d.ts.map +1 -1
  372. package/lib/feature-libraries/chunked-forest/codec/nodeEncoder.js +2 -3
  373. package/lib/feature-libraries/chunked-forest/codec/nodeEncoder.js.map +1 -1
  374. package/lib/feature-libraries/chunked-forest/uniformChunk.d.ts +66 -14
  375. package/lib/feature-libraries/chunked-forest/uniformChunk.d.ts.map +1 -1
  376. package/lib/feature-libraries/chunked-forest/uniformChunk.js +101 -36
  377. package/lib/feature-libraries/chunked-forest/uniformChunk.js.map +1 -1
  378. package/lib/feature-libraries/default-schema/defaultEditBuilder.d.ts.map +1 -1
  379. package/lib/feature-libraries/default-schema/defaultEditBuilder.js +36 -14
  380. package/lib/feature-libraries/default-schema/defaultEditBuilder.js.map +1 -1
  381. package/lib/feature-libraries/forest-summary/codec.d.ts +5 -4
  382. package/lib/feature-libraries/forest-summary/codec.d.ts.map +1 -1
  383. package/lib/feature-libraries/forest-summary/codec.js +3 -3
  384. package/lib/feature-libraries/forest-summary/codec.js.map +1 -1
  385. package/lib/feature-libraries/forest-summary/formatCommon.d.ts +6 -5
  386. package/lib/feature-libraries/forest-summary/formatCommon.d.ts.map +1 -1
  387. package/lib/feature-libraries/forest-summary/formatCommon.js +1 -1
  388. package/lib/feature-libraries/forest-summary/formatCommon.js.map +1 -1
  389. package/lib/feature-libraries/modular-schema/genericFieldKindFormat.d.ts +4 -3
  390. package/lib/feature-libraries/modular-schema/genericFieldKindFormat.d.ts.map +1 -1
  391. package/lib/feature-libraries/modular-schema/genericFieldKindFormat.js +1 -1
  392. package/lib/feature-libraries/modular-schema/genericFieldKindFormat.js.map +1 -1
  393. package/lib/feature-libraries/modular-schema/modularChangeFormatV1.d.ts +45 -44
  394. package/lib/feature-libraries/modular-schema/modularChangeFormatV1.d.ts.map +1 -1
  395. package/lib/feature-libraries/modular-schema/modularChangeFormatV1.js +1 -1
  396. package/lib/feature-libraries/modular-schema/modularChangeFormatV1.js.map +1 -1
  397. package/lib/feature-libraries/modular-schema/modularChangeFormatV2.d.ts +23 -22
  398. package/lib/feature-libraries/modular-schema/modularChangeFormatV2.d.ts.map +1 -1
  399. package/lib/feature-libraries/modular-schema/modularChangeFormatV2.js +1 -1
  400. package/lib/feature-libraries/modular-schema/modularChangeFormatV2.js.map +1 -1
  401. package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts +1 -1
  402. package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
  403. package/lib/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
  404. package/lib/feature-libraries/optional-field/optionalFieldChangeFormatV1.d.ts +9 -8
  405. package/lib/feature-libraries/optional-field/optionalFieldChangeFormatV1.d.ts.map +1 -1
  406. package/lib/feature-libraries/optional-field/optionalFieldChangeFormatV1.js +1 -1
  407. package/lib/feature-libraries/optional-field/optionalFieldChangeFormatV1.js.map +1 -1
  408. package/lib/feature-libraries/optional-field/optionalFieldChangeFormatV2.d.ts +14 -13
  409. package/lib/feature-libraries/optional-field/optionalFieldChangeFormatV2.d.ts.map +1 -1
  410. package/lib/feature-libraries/optional-field/optionalFieldChangeFormatV2.js +1 -1
  411. package/lib/feature-libraries/optional-field/optionalFieldChangeFormatV2.js.map +1 -1
  412. package/lib/feature-libraries/schema-edits/schemaChangeFormat.d.ts +5 -4
  413. package/lib/feature-libraries/schema-edits/schemaChangeFormat.d.ts.map +1 -1
  414. package/lib/feature-libraries/schema-edits/schemaChangeFormat.js +1 -1
  415. package/lib/feature-libraries/schema-edits/schemaChangeFormat.js.map +1 -1
  416. package/lib/feature-libraries/schema-index/codec.d.ts +2 -2
  417. package/lib/feature-libraries/schema-index/codec.d.ts.map +1 -1
  418. package/lib/feature-libraries/schema-index/codec.js +2 -2
  419. package/lib/feature-libraries/schema-index/codec.js.map +1 -1
  420. package/lib/feature-libraries/schema-index/formatV1.d.ts +15 -14
  421. package/lib/feature-libraries/schema-index/formatV1.d.ts.map +1 -1
  422. package/lib/feature-libraries/schema-index/formatV1.js +1 -1
  423. package/lib/feature-libraries/schema-index/formatV1.js.map +1 -1
  424. package/lib/feature-libraries/schema-index/formatV2.d.ts +20 -19
  425. package/lib/feature-libraries/schema-index/formatV2.d.ts.map +1 -1
  426. package/lib/feature-libraries/schema-index/formatV2.js +1 -1
  427. package/lib/feature-libraries/schema-index/formatV2.js.map +1 -1
  428. package/lib/feature-libraries/sequence-field/compose.d.ts.map +1 -1
  429. package/lib/feature-libraries/sequence-field/compose.js +1 -3
  430. package/lib/feature-libraries/sequence-field/compose.js.map +1 -1
  431. package/lib/feature-libraries/sequence-field/formatV1.d.ts +283 -282
  432. package/lib/feature-libraries/sequence-field/formatV1.d.ts.map +1 -1
  433. package/lib/feature-libraries/sequence-field/formatV1.js +1 -1
  434. package/lib/feature-libraries/sequence-field/formatV1.js.map +1 -1
  435. package/lib/feature-libraries/sequence-field/formatV2.d.ts +180 -179
  436. package/lib/feature-libraries/sequence-field/formatV2.d.ts.map +1 -1
  437. package/lib/feature-libraries/sequence-field/formatV2.js +1 -1
  438. package/lib/feature-libraries/sequence-field/formatV2.js.map +1 -1
  439. package/lib/feature-libraries/sequence-field/formatV3.d.ts +126 -125
  440. package/lib/feature-libraries/sequence-field/formatV3.d.ts.map +1 -1
  441. package/lib/feature-libraries/sequence-field/formatV3.js +1 -1
  442. package/lib/feature-libraries/sequence-field/formatV3.js.map +1 -1
  443. package/lib/index.d.ts +1 -1
  444. package/lib/index.d.ts.map +1 -1
  445. package/lib/index.js +1 -1
  446. package/lib/index.js.map +1 -1
  447. package/lib/packageVersion.d.ts +1 -1
  448. package/lib/packageVersion.js +1 -1
  449. package/lib/packageVersion.js.map +1 -1
  450. package/lib/shared-tree/isAuditableFromOutcome.d.ts +20 -0
  451. package/lib/shared-tree/isAuditableFromOutcome.d.ts.map +1 -0
  452. package/lib/shared-tree/isAuditableFromOutcome.js +32 -0
  453. package/lib/shared-tree/isAuditableFromOutcome.js.map +1 -0
  454. package/lib/shared-tree/sharedTree.d.ts +2 -2
  455. package/lib/shared-tree/sharedTree.d.ts.map +1 -1
  456. package/lib/shared-tree/sharedTree.js +1 -1
  457. package/lib/shared-tree/sharedTree.js.map +1 -1
  458. package/lib/shared-tree/sharedTreeChangeFormat.d.ts +8 -7
  459. package/lib/shared-tree/sharedTreeChangeFormat.d.ts.map +1 -1
  460. package/lib/shared-tree/sharedTreeChangeFormat.js +1 -1
  461. package/lib/shared-tree/sharedTreeChangeFormat.js.map +1 -1
  462. package/lib/shared-tree/treeCheckout.d.ts +5 -3
  463. package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
  464. package/lib/shared-tree/treeCheckout.js +38 -9
  465. package/lib/shared-tree/treeCheckout.js.map +1 -1
  466. package/lib/shared-tree-core/editManager.d.ts +2 -2
  467. package/lib/shared-tree-core/editManager.d.ts.map +1 -1
  468. package/lib/shared-tree-core/editManager.js.map +1 -1
  469. package/lib/shared-tree-core/editManagerCodecs.d.ts +3 -3
  470. package/lib/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
  471. package/lib/shared-tree-core/editManagerCodecs.js +3 -3
  472. package/lib/shared-tree-core/editManagerCodecs.js.map +1 -1
  473. package/lib/shared-tree-core/editManagerFormatCommons.d.ts +35 -34
  474. package/lib/shared-tree-core/editManagerFormatCommons.d.ts.map +1 -1
  475. package/lib/shared-tree-core/editManagerFormatCommons.js +1 -1
  476. package/lib/shared-tree-core/editManagerFormatCommons.js.map +1 -1
  477. package/lib/shared-tree-core/editManagerFormatV1toV4.d.ts +15 -15
  478. package/lib/shared-tree-core/editManagerFormatV1toV4.d.ts.map +1 -1
  479. package/lib/shared-tree-core/editManagerFormatV1toV4.js +1 -1
  480. package/lib/shared-tree-core/editManagerFormatV1toV4.js.map +1 -1
  481. package/lib/shared-tree-core/editManagerFormatVSharedBranches.d.ts +40 -40
  482. package/lib/shared-tree-core/editManagerFormatVSharedBranches.d.ts.map +1 -1
  483. package/lib/shared-tree-core/editManagerFormatVSharedBranches.js +1 -1
  484. package/lib/shared-tree-core/editManagerFormatVSharedBranches.js.map +1 -1
  485. package/lib/shared-tree-core/messageCodecVSharedBranches.d.ts.map +1 -1
  486. package/lib/shared-tree-core/messageCodecVSharedBranches.js +1 -1
  487. package/lib/shared-tree-core/messageCodecVSharedBranches.js.map +1 -1
  488. package/lib/shared-tree-core/messageCodecs.d.ts +3 -3
  489. package/lib/shared-tree-core/messageCodecs.d.ts.map +1 -1
  490. package/lib/shared-tree-core/messageCodecs.js +3 -3
  491. package/lib/shared-tree-core/messageCodecs.js.map +1 -1
  492. package/lib/shared-tree-core/messageFormatV1ToV4.d.ts +5 -5
  493. package/lib/shared-tree-core/messageFormatV1ToV4.d.ts.map +1 -1
  494. package/lib/shared-tree-core/messageFormatV1ToV4.js +1 -1
  495. package/lib/shared-tree-core/messageFormatV1ToV4.js.map +1 -1
  496. package/lib/shared-tree-core/messageFormatVSharedBranches.d.ts +7 -7
  497. package/lib/shared-tree-core/messageFormatVSharedBranches.d.ts.map +1 -1
  498. package/lib/shared-tree-core/messageFormatVSharedBranches.js +1 -1
  499. package/lib/shared-tree-core/messageFormatVSharedBranches.js.map +1 -1
  500. package/lib/simple-tree/core/treeNodeKernel.d.ts +5 -0
  501. package/lib/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
  502. package/lib/simple-tree/core/treeNodeKernel.js +60 -23
  503. package/lib/simple-tree/core/treeNodeKernel.js.map +1 -1
  504. package/lib/simple-tree/simpleSchemaFormatV1.d.ts +121 -120
  505. package/lib/simple-tree/simpleSchemaFormatV1.d.ts.map +1 -1
  506. package/lib/simple-tree/simpleSchemaFormatV1.js +1 -1
  507. package/lib/simple-tree/simpleSchemaFormatV1.js.map +1 -1
  508. package/lib/text/codePointUtils.d.ts +48 -0
  509. package/lib/text/codePointUtils.d.ts.map +1 -0
  510. package/lib/text/codePointUtils.js +75 -0
  511. package/lib/text/codePointUtils.js.map +1 -0
  512. package/lib/text/index.d.ts +1 -0
  513. package/lib/text/index.d.ts.map +1 -1
  514. package/lib/text/index.js +1 -0
  515. package/lib/text/index.js.map +1 -1
  516. package/lib/text/textDomain.d.ts +93 -1
  517. package/lib/text/textDomain.d.ts.map +1 -1
  518. package/lib/text/textDomain.js +56 -0
  519. package/lib/text/textDomain.js.map +1 -1
  520. package/lib/text/textDomainFormatted.d.ts +24 -6
  521. package/lib/text/textDomainFormatted.d.ts.map +1 -1
  522. package/lib/text/textDomainFormatted.js +30 -2
  523. package/lib/text/textDomainFormatted.js.map +1 -1
  524. package/lib/treeFactory.d.ts.map +1 -1
  525. package/lib/treeFactory.js +2 -0
  526. package/lib/treeFactory.js.map +1 -1
  527. package/lib/util/breakable.d.ts +7 -1
  528. package/lib/util/breakable.d.ts.map +1 -1
  529. package/lib/util/breakable.js +18 -4
  530. package/lib/util/breakable.js.map +1 -1
  531. package/lib/util/typeboxBrand.d.ts +1 -1
  532. package/lib/util/typeboxBrand.d.ts.map +1 -1
  533. package/lib/util/typeboxBrand.js +1 -1
  534. package/lib/util/typeboxBrand.js.map +1 -1
  535. package/lib/util/utils.d.ts +2 -2
  536. package/lib/util/utils.d.ts.map +1 -1
  537. package/lib/util/utils.js +1 -1
  538. package/lib/util/utils.js.map +1 -1
  539. package/package.json +24 -24
  540. package/src/codec/codec.ts +82 -73
  541. package/src/codec/index.ts +2 -1
  542. package/src/codec/versioned/codec.ts +173 -73
  543. package/src/codec/versioned/format.ts +2 -1
  544. package/src/codec/versioned/index.ts +2 -1
  545. package/src/core/rebase/types.ts +1 -1
  546. package/src/core/schema-stored/formatV1.ts +2 -1
  547. package/src/core/schema-stored/formatV2.ts +2 -1
  548. package/src/core/tree/deltaUtil.ts +2 -2
  549. package/src/core/tree/detachedFieldIndexCodecV1.ts +3 -2
  550. package/src/core/tree/detachedFieldIndexCodecV2.ts +5 -3
  551. package/src/core/tree/detachedFieldIndexCodecs.ts +2 -2
  552. package/src/core/tree/detachedFieldIndexFormatCommon.ts +2 -1
  553. package/src/core/tree/detachedFieldIndexFormatV2.ts +2 -1
  554. package/src/core/tree/persistedTreeTextFormat.ts +2 -1
  555. package/src/feature-libraries/chunked-forest/chunkTree.ts +88 -3
  556. package/src/feature-libraries/chunked-forest/chunkedForest.ts +27 -7
  557. package/src/feature-libraries/chunked-forest/codec/chunkDecoding.ts +143 -7
  558. package/src/feature-libraries/chunked-forest/codec/codecs.ts +30 -28
  559. package/src/feature-libraries/chunked-forest/codec/compressedEncode.ts +7 -7
  560. package/src/feature-libraries/chunked-forest/codec/format/formatGeneric.ts +2 -1
  561. package/src/feature-libraries/chunked-forest/codec/format/formatV1.ts +2 -1
  562. package/src/feature-libraries/chunked-forest/codec/format/formatV2.ts +13 -8
  563. package/src/feature-libraries/chunked-forest/codec/format/formatVText.ts +84 -0
  564. package/src/feature-libraries/chunked-forest/codec/format/index.ts +6 -1
  565. package/src/feature-libraries/chunked-forest/codec/format/versions.ts +25 -4
  566. package/src/feature-libraries/chunked-forest/codec/nodeEncoder.ts +14 -18
  567. package/src/feature-libraries/chunked-forest/uniformChunk.ts +131 -44
  568. package/src/feature-libraries/default-schema/defaultEditBuilder.ts +36 -14
  569. package/src/feature-libraries/forest-summary/codec.ts +9 -4
  570. package/src/feature-libraries/forest-summary/formatCommon.ts +2 -1
  571. package/src/feature-libraries/modular-schema/genericFieldKindFormat.ts +2 -1
  572. package/src/feature-libraries/modular-schema/modularChangeFormatV1.ts +2 -1
  573. package/src/feature-libraries/modular-schema/modularChangeFormatV2.ts +2 -1
  574. package/src/feature-libraries/modular-schema/modularChangeTypes.ts +1 -1
  575. package/src/feature-libraries/optional-field/optionalFieldChangeFormatV1.ts +2 -1
  576. package/src/feature-libraries/optional-field/optionalFieldChangeFormatV2.ts +2 -1
  577. package/src/feature-libraries/schema-edits/schemaChangeFormat.ts +2 -1
  578. package/src/feature-libraries/schema-index/codec.ts +2 -5
  579. package/src/feature-libraries/schema-index/formatV1.ts +2 -1
  580. package/src/feature-libraries/schema-index/formatV2.ts +2 -1
  581. package/src/feature-libraries/sequence-field/compose.ts +1 -4
  582. package/src/feature-libraries/sequence-field/formatV1.ts +2 -1
  583. package/src/feature-libraries/sequence-field/formatV2.ts +2 -1
  584. package/src/feature-libraries/sequence-field/formatV3.ts +2 -1
  585. package/src/index.ts +6 -1
  586. package/src/packageVersion.ts +1 -1
  587. package/src/shared-tree/isAuditableFromOutcome.ts +34 -0
  588. package/src/shared-tree/sharedTree.ts +2 -5
  589. package/src/shared-tree/sharedTreeChangeFormat.ts +2 -1
  590. package/src/shared-tree/treeCheckout.ts +55 -15
  591. package/src/shared-tree-core/editManager.ts +2 -2
  592. package/src/shared-tree-core/editManagerCodecs.ts +4 -6
  593. package/src/shared-tree-core/editManagerFormatCommons.ts +2 -1
  594. package/src/shared-tree-core/editManagerFormatV1toV4.ts +2 -1
  595. package/src/shared-tree-core/editManagerFormatVSharedBranches.ts +2 -1
  596. package/src/shared-tree-core/messageCodecVSharedBranches.ts +2 -1
  597. package/src/shared-tree-core/messageCodecs.ts +4 -4
  598. package/src/shared-tree-core/messageFormatV1ToV4.ts +2 -1
  599. package/src/shared-tree-core/messageFormatVSharedBranches.ts +2 -1
  600. package/src/simple-tree/core/treeNodeKernel.ts +66 -28
  601. package/src/simple-tree/simpleSchemaFormatV1.ts +2 -1
  602. package/src/text/codePointUtils.ts +81 -0
  603. package/src/text/index.ts +1 -0
  604. package/src/text/textDomain.ts +155 -2
  605. package/src/text/textDomainFormatted.ts +73 -2
  606. package/src/treeFactory.ts +5 -0
  607. package/src/util/breakable.ts +27 -6
  608. package/src/util/typeboxBrand.ts +2 -1
  609. package/src/util/utils.ts +2 -1
@@ -120,14 +120,16 @@ export class TreeNodeKernel {
120
120
  #hydrationState: HydrationState;
121
121
 
122
122
  /**
123
- * Events registered before hydration.
123
+ * Handler for events listeners registered with the kernel.
124
+ *
124
125
  * @remarks
125
- * Since these are usually not used, they are allocated lazily as an optimization.
126
- * The laziness also avoids extra forwarding overhead for events from this kernel's anchor node and also avoids registering for events that are unneeded.
127
- * This means optimizations like skipping processing data in subtrees where no subtreeChanged events are subscribed to would be able to work,
128
- * since the kernel does not unconditionally subscribe to those events (like a design which simply forwards all events would).
126
+ * Supports event buffering via {@link withBufferedEvents}.
127
+ *
128
+ * Allocated lazily on first access to {@link TreeNodeKernel.events}.
129
+ * We expect the majority of nodes to never have event listeners registered, so
130
+ * deferring construction avoids per-kernel allocations.
129
131
  */
130
- readonly #eventBuffer: KernelEventBuffer;
132
+ #eventBuffer: KernelEventBuffer | undefined;
131
133
 
132
134
  /**
133
135
  * Create a TreeNodeKernel which can be looked up with {@link getKernel}.
@@ -157,12 +159,9 @@ export class TreeNodeKernel {
157
159
  this.#hydrationState = {
158
160
  innerNode,
159
161
  };
160
-
161
- this.#eventBuffer = new KernelEventBuffer(innerNode.events);
162
162
  } else {
163
163
  // Hydrated case
164
164
  this.#hydrationState = this.createHydratedState(innerNode);
165
- this.#eventBuffer = new KernelEventBuffer(innerNode.anchorNode.events);
166
165
  }
167
166
  }
168
167
 
@@ -190,8 +189,10 @@ export class TreeNodeKernel {
190
189
 
191
190
  this.#hydrationState = this.createHydratedState(inner);
192
191
 
193
- // Lazily migrate existing event listeners to the anchor node
194
- this.#eventBuffer.migrateEventSource(inner.anchorNode.events);
192
+ // Lazily migrate existing event listeners to the anchor node.
193
+ // If no one ever subscribed to this kernel's events, the buffer was never allocated
194
+ // and there is nothing to migrate.
195
+ this.#eventBuffer?.migrateEventSource(inner.anchorNode.events);
195
196
  }
196
197
 
197
198
  private createHydratedState(innerNode: HydratedFlexTreeNode): HydratedState {
@@ -233,6 +234,14 @@ export class TreeNodeKernel {
233
234
  }
234
235
 
235
236
  public get events(): Listenable<KernelEvents> {
237
+ assert(!this.disposed, 0xcfa /* Cannot register events on a disposed node */);
238
+ // Allocate the buffer on first access. See {@link TreeNodeKernel.#eventBuffer} for rationale.
239
+ if (this.#eventBuffer === undefined) {
240
+ const eventSource = isHydrated(this.#hydrationState)
241
+ ? this.#hydrationState.innerNode.anchorNode.events
242
+ : this.#hydrationState.innerNode.events;
243
+ this.#eventBuffer = new KernelEventBuffer(eventSource);
244
+ }
236
245
  return this.#eventBuffer;
237
246
  }
238
247
 
@@ -244,7 +253,7 @@ export class TreeNodeKernel {
244
253
  off();
245
254
  }
246
255
  }
247
- this.#eventBuffer.dispose();
256
+ this.#eventBuffer?.dispose();
248
257
  // TODO: go to the context and remove myself from withAnchors
249
258
  }
250
259
 
@@ -323,34 +332,53 @@ export function withBufferedTreeEvents(callback: () => void): void {
323
332
  callback();
324
333
  } else {
325
334
  bufferTreeEvents = true;
335
+ const toFlush: KernelEventBuffer[] = [];
326
336
  try {
327
337
  callback();
328
338
  } finally {
329
339
  bufferTreeEvents = false;
330
- flushEventsEmitter.emit("flush");
340
+ // Snapshot-and-clear before flushing to safely handle reentrant `withBufferedTreeEvents`
341
+ // calls made by listeners that fire during `buffer.flush()` below:
342
+ // - Iterating an array means a reentrant call's `clear()` cannot truncate our loop
343
+ // and cause buffers later in `activeBuffers` to be skipped (and their events dropped).
344
+ // - Clearing up front means the reentrant call starts from an empty set, so its own
345
+ // finally block only flushes what it buffered - not a re-flush of our remaining buffers.
346
+ toFlush.push(...activeBuffers);
347
+ activeBuffers.clear();
348
+ }
349
+
350
+ // Don't flush/emit events in the case of an error
351
+ for (const buffer of toFlush) {
352
+ buffer.flush();
331
353
  }
332
354
  }
333
355
  }
334
356
 
335
357
  /**
336
- * Event emitter to notify subscribers when tree events buffered due to {@link withBufferedTreeEvents} should be flushed.
358
+ * Set of {@link KernelEventBuffer}s that have accumulated buffered events during the current
359
+ * {@link withBufferedTreeEvents} window and therefore need to be flushed when it ends.
360
+ *
361
+ * @remarks
362
+ * The set should be empty whenever no buffering window is in progress.
337
363
  */
338
- const flushEventsEmitter = createEmitter<{
339
- flush: () => void;
340
- }>();
364
+ const activeBuffers: Set<KernelEventBuffer> = new Set();
365
+
366
+ /**
367
+ * Test-only accessor for the current size of {@link activeBuffers}.
368
+ * @remarks Only exported for testing purposes. Not intended for any other use.
369
+ */
370
+ export function TEST_activeBufferCount(): number {
371
+ return activeBuffers.size;
372
+ }
341
373
 
342
374
  /**
343
375
  * Event emitter for {@link TreeNodeKernel}, which optionally buffers events based on {@link bufferTreeEvents}.
344
- * @remarks Listens to {@link flushEventsEmitter} to know when to flush any buffered events.
376
+ * @remarks When buffering is active, this adds itself to {@link activeBuffers} so that
377
+ * {@link withBufferedTreeEvents} can flush it at the end of the buffering window.
345
378
  */
346
379
  class KernelEventBuffer implements Listenable<KernelEvents> {
347
380
  #disposed: boolean = false;
348
381
 
349
- /**
350
- * Listen to {@link flushEventsEmitter} to know when to flush buffered events.
351
- */
352
- readonly #disposeOnFlushListener = flushEventsEmitter.on("flush", this.flush.bind(this));
353
-
354
382
  readonly #events = createEmitter<KernelEvents>();
355
383
 
356
384
  #eventSource: Listenable<KernelEvents> & HasListeners<KernelEvents>;
@@ -430,6 +458,8 @@ class KernelEventBuffer implements Listenable<KernelEvents> {
430
458
  }
431
459
 
432
460
  public on(eventName: keyof KernelEvents, listener: KernelEvents[typeof eventName]): Off {
461
+ this.#assertNotDisposed();
462
+
433
463
  // Lazily bind event listeners to the source.
434
464
  // If we do not have any existing listeners for this event, then we need to bind to the source.
435
465
  if (!this.#events.hasListeners(eventName)) {
@@ -446,7 +476,10 @@ class KernelEventBuffer implements Listenable<KernelEvents> {
446
476
  }
447
477
 
448
478
  this.#events.on(eventName, listener);
449
- return () => this.off(eventName, listener);
479
+ // Return a bound method instead of an arrow closure. A bound function captures
480
+ // (target, thisArg, ...boundArgs) in a fixed shape that V8 can optimize more
481
+ // uniformly than a closure that captures its lexical context.
482
+ return this.off.bind(this, eventName, listener);
450
483
  }
451
484
 
452
485
  public off(eventName: keyof KernelEvents, listener: KernelEvents[typeof eventName]): void {
@@ -487,6 +520,7 @@ class KernelEventBuffer implements Listenable<KernelEvents> {
487
520
  fieldMarks: ReadonlyMap<FieldKey, readonly DeltaMark[]>,
488
521
  ): void {
489
522
  if (bufferTreeEvents) {
523
+ activeBuffers.add(this);
490
524
  for (const fieldKey of changedFields) {
491
525
  this.#childrenChangedBuffer.add(fieldKey);
492
526
  }
@@ -514,6 +548,7 @@ class KernelEventBuffer implements Listenable<KernelEvents> {
514
548
 
515
549
  #handleSubtreeChangedAfterBatch(): void {
516
550
  if (bufferTreeEvents) {
551
+ activeBuffers.add(this);
517
552
  this.#subTreeChangedBuffer = true;
518
553
  } else {
519
554
  this.#events.emit("subtreeChangedAfterBatch");
@@ -551,12 +586,15 @@ class KernelEventBuffer implements Listenable<KernelEvents> {
551
586
  return;
552
587
  }
553
588
 
554
- assert(
555
- this.#childrenChangedBuffer.size === 0 && !this.#subTreeChangedBuffer,
556
- 0xc52 /* Buffered kernel events should have been flushed before disposing. */,
589
+ debugAssert(
590
+ () =>
591
+ (this.#childrenChangedBuffer.size === 0 && !this.#subTreeChangedBuffer) ||
592
+ "Buffered kernel events should have been flushed before disposing.",
593
+ );
594
+ debugAssert(
595
+ () => !activeBuffers.has(this) || "Disposed buffer should not be in activeBuffers.",
557
596
  );
558
597
 
559
- this.#disposeOnFlushListener();
560
598
  for (const off of this.#disposeSourceListeners.values()) {
561
599
  off();
562
600
  }
@@ -11,7 +11,8 @@
11
11
  * It may not include some details which impact maintenance of application enforced invariants (like persisted metadata or logic in view schema).
12
12
  */
13
13
 
14
- import { Type, type ObjectOptions, type Static } from "@sinclair/typebox";
14
+ import * as Type from "@sinclair/typebox";
15
+ import type { ObjectOptions, Static } from "@sinclair/typebox";
15
16
 
16
17
  const noAdditionalProps: ObjectOptions = { additionalProperties: false };
17
18
 
@@ -0,0 +1,81 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { UsageError } from "@fluidframework/telemetry-utils/internal";
7
+
8
+ /**
9
+ * Returns the number of Unicode code points in `value`.
10
+ * @remarks
11
+ * Use this to translate a JavaScript string length (which is in UTF-16 code units) into
12
+ * the atom/code-point space used by {@link TextAsTree}.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * codePointCount(""); // 0
17
+ * codePointCount("abc"); // 3
18
+ * codePointCount("a😀b"); // 3 — emoji is one code point, but "a😀b".length === 4 (UTF-16 surrogate pair)
19
+ * ```
20
+ *
21
+ * @internal
22
+ */
23
+ export function codePointCount(value: string): number {
24
+ // Iterate instead of spreading to avoid allocating an intermediate array.
25
+ let count = 0;
26
+ for (const _ of value) {
27
+ count++;
28
+ }
29
+ return count;
30
+ }
31
+
32
+ /**
33
+ * Returns the number of UTF-16 code units occupied by the first `count` Unicode code points in `value`,
34
+ * starting at UTF-16 index `start`.
35
+ * @remarks
36
+ * Use this to translate {@link TextAsTree}-space counts (code points) into JavaScript string indices (UTF-16).
37
+ * One code point outside the Basic Multilingual Plane (e.g. most emoji) occupies two UTF-16 code units.
38
+ *
39
+ * Validates that the requested `count` code points are fully consumable from `start`; silent truncation
40
+ * would misalign delta offsets applied to strings rather than surface the drift to the caller.
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * utf16LengthForCodePoints("abc", 0, 3); // 3 — three single-unit characters
45
+ * utf16LengthForCodePoints("a😀b", 0, 3); // 4 — a (1) + 😀 (2) + b (1)
46
+ * utf16LengthForCodePoints("a😀b", 1, 1); // 2 — just the emoji
47
+ * utf16LengthForCodePoints("abc", 0, 0); // 0 — no code points requested
48
+ * ```
49
+ *
50
+ * @param value - The string to measure.
51
+ * @param start - The UTF-16 index in `value` to start measuring from. Must be in `[0, value.length]`.
52
+ * @param count - The number of Unicode code points to measure. Must be non-negative, and there must
53
+ * be at least `count` code points available in `value` starting at `start`.
54
+ * @throws A {@link @fluidframework/telemetry-utils#UsageError} if `start` is out of range,
55
+ * `count` is negative, or fewer than `count` code points are available from `start`.
56
+ * @internal
57
+ */
58
+ export function utf16LengthForCodePoints(value: string, start: number, count: number): number {
59
+ if (start < 0 || start > value.length) {
60
+ throw new UsageError(
61
+ `start (${start}) must be within [0, ${value.length}] (value.length).`,
62
+ );
63
+ }
64
+ if (count < 0) {
65
+ throw new UsageError(`count (${count}) must be non-negative.`);
66
+ }
67
+ let utf16 = 0;
68
+ let counted = 0;
69
+ while (counted < count && start + utf16 < value.length) {
70
+ // Code points above 0xFFFF are encoded in UTF-16 as a surrogate pair (2 units);
71
+ // everything else takes a single UTF-16 unit.
72
+ utf16 += (value.codePointAt(start + utf16) ?? 0) > 0xffff ? 2 : 1;
73
+ counted++;
74
+ }
75
+ if (counted !== count) {
76
+ throw new UsageError(
77
+ `count (${count}) exceeds the ${counted} code point(s) available from start (${start}) in a value of length ${value.length}.`,
78
+ );
79
+ }
80
+ return utf16;
81
+ }
package/src/text/index.ts CHANGED
@@ -5,3 +5,4 @@
5
5
 
6
6
  export { TextAsTree } from "./textDomain.js";
7
7
  export { FormattedTextAsTree } from "./textDomainFormatted.js";
8
+ export { codePointCount, utf16LengthForCodePoints } from "./codePointUtils.js";
@@ -14,6 +14,7 @@ import {
14
14
  import { typeFactory as tf } from "@fluidframework/type-factory/internal";
15
15
 
16
16
  import { EmptyKey, mapCursorField, type ITreeCursorSynchronous } from "../core/index.js";
17
+ import { TreeAlpha } from "../shared-tree/index.js";
17
18
  import {
18
19
  eraseSchemaDetails,
19
20
  getInnerNode,
@@ -21,8 +22,13 @@ import {
21
22
  SchemaFactoryAlpha,
22
23
  TreeArrayNode,
23
24
  } from "../simple-tree/index.js";
24
- // eslint-disable-next-line import-x/no-duplicates
25
- import type { TreeNode, WithType } from "../simple-tree/index.js";
25
+ import type {
26
+ ArrayNodeDeltaOp,
27
+ ArrayNodeTreeChangedDeltaOp,
28
+ TreeNode,
29
+ WithType,
30
+ // eslint-disable-next-line import-x/no-duplicates
31
+ } from "../simple-tree/index.js";
26
32
  // Add some unused imports which show up in the generated d.ts file.
27
33
  // This prevents them from getting inline imports generated, cleaning up the d.ts file and API reports.
28
34
  // eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-imports, import-x/no-duplicates
@@ -144,6 +150,14 @@ class TextNode
144
150
  return [...this.content];
145
151
  }
146
152
 
153
+ public onCharactersChanged(
154
+ callback: (ops: readonly TextAsTree.TextOp[] | undefined) => void,
155
+ ): () => void {
156
+ return TreeAlpha.on(this.content, "nodeChanged", ({ delta }) =>
157
+ processCharactersChangedDelta(delta, (i) => this.content[i], callback),
158
+ );
159
+ }
160
+
147
161
  public static fromString(value: string): TextNode {
148
162
  // Constructing an ArrayNode from an iterator is supported, so creating an array from the iterable of characters seems like its not necessary here,
149
163
  // but to reduce the risk of incorrect data interpretation, we actually ban this in the special case where the iterable is a string directly, which is the case here.
@@ -186,6 +200,63 @@ class StringArray extends sf.array("StringArray", SchemaFactory.string) {
186
200
  }
187
201
  }
188
202
 
203
+ /**
204
+ * Processes an array-node delta into a {@link TextAsTree.TextOp}[] and calls `callback`.
205
+ * @remarks
206
+ * Shared by both the plain `onCharactersChanged` (from `nodeChanged`) and formatted `onContentChanged`
207
+ * (from `treeChanged`) implementations.
208
+ * @param delta - The raw array-node delta, or `undefined` when no delta is available.
209
+ * When retain ops carry `subtreeChanged` (i.e. delta comes from a `treeChanged` event), the emitted
210
+ * retain ops include an explicit `formattingChanged: boolean`. Otherwise `formattingChanged` is omitted.
211
+ * @param getCharacter - Returns the character string at the given array index in the **post-edit** tree.
212
+ * Only invoked for insert ops, where it must read the inserted character at the given index of the tree
213
+ * after the edit has been applied. Passing an accessor that reads pre-edit content will silently produce wrong text.
214
+ * Return `undefined` if the tree is out of sync with the delta; this triggers a full-reread fallback.
215
+ * @param callback - The user-supplied callback to invoke with the translated ops.
216
+ */
217
+ export function processCharactersChangedDelta(
218
+ delta: readonly (ArrayNodeDeltaOp | ArrayNodeTreeChangedDeltaOp)[] | undefined,
219
+ getCharacter: (index: number) => string | undefined,
220
+ callback: (ops: readonly TextAsTree.TextOp[] | undefined) => void,
221
+ ): void {
222
+ if (delta === undefined) {
223
+ callback(undefined);
224
+ return;
225
+ }
226
+ let readPosition = 0;
227
+ const ops: TextAsTree.TextOp[] = [];
228
+ for (const op of delta) {
229
+ if (op.type === "retain") {
230
+ // `subtreeChanged` is only present on retain ops from `treeChanged` deltas.
231
+ ops.push(
232
+ "subtreeChanged" in op
233
+ ? { type: "retain", count: op.count, formattingChanged: op.subtreeChanged === true }
234
+ : { type: "retain", count: op.count },
235
+ );
236
+ readPosition += op.count;
237
+ } else if (op.type === "insert") {
238
+ // Accumulate into an array and join at the end to keep this O(n) for large inserts
239
+ // (paste of long text) instead of O(n^2) from repeated string concatenation.
240
+ const characters: string[] = [];
241
+ for (let i = 0; i < op.count; i++) {
242
+ const character = getCharacter(readPosition);
243
+ if (character === undefined) {
244
+ // Tree is out of sync with the delta — fall back to full re-read.
245
+ callback(undefined);
246
+ return;
247
+ }
248
+ characters.push(character);
249
+ readPosition++;
250
+ }
251
+ ops.push({ type: "insert", text: characters.join("") });
252
+ } else {
253
+ // Construct explicit remove op so internal fields on the source op don't leak.
254
+ ops.push({ type: "remove", count: op.count });
255
+ }
256
+ }
257
+ callback(ops);
258
+ }
259
+
189
260
  /**
190
261
  * A collection of text related types, schema and utilities for working with text beyond the basic {@link SchemaStatics.string}.
191
262
  * @privateRemarks
@@ -249,6 +320,71 @@ class StringArray extends sf.array("StringArray", SchemaFactory.string) {
249
320
  * @alpha
250
321
  */
251
322
  export namespace TextAsTree {
323
+ /**
324
+ * A retain op in a character-level delta — a span of unchanged characters that the consumer should skip over.
325
+ * @sealed
326
+ * @alpha
327
+ */
328
+ export interface TextRetainOp {
329
+ /**
330
+ * Discriminator identifying this op as a retain.
331
+ */
332
+ readonly type: "retain";
333
+ /**
334
+ * The number of Unicode code points to retain.
335
+ */
336
+ readonly count: number;
337
+ /**
338
+ * Whether at least one character in the retained range had a deep change.
339
+ * @remarks
340
+ * Present only on retain ops delivered by {@link @fluidframework/tree#FormattedTextAsTree.Members.onContentChanged};
341
+ * always absent on retain ops delivered by {@link TextAsTree.Members.onCharactersChanged}.
342
+ * When present, `true` indicates the retained range contained a formatting property update
343
+ * or an atom content edit; `false` indicates no deep change.
344
+ */
345
+ readonly formattingChanged?: boolean;
346
+ }
347
+
348
+ /**
349
+ * An insert op in a character-level delta — characters newly added to the text.
350
+ * @remarks
351
+ * Carries the inserted text as a single string, which is more convenient for consumers than individual characters.
352
+ * @sealed
353
+ * @alpha
354
+ */
355
+ export interface TextInsertOp {
356
+ /**
357
+ * Discriminator identifying this op as an insert.
358
+ */
359
+ readonly type: "insert";
360
+ /**
361
+ * The newly inserted characters, concatenated into a single string.
362
+ */
363
+ readonly text: string;
364
+ }
365
+
366
+ /**
367
+ * A remove op in a character-level delta — a span of characters that has been deleted from the text.
368
+ * @sealed
369
+ * @alpha
370
+ */
371
+ export interface TextRemoveOp {
372
+ /**
373
+ * Discriminator identifying this op as a remove.
374
+ */
375
+ readonly type: "remove";
376
+ /**
377
+ * The number of Unicode code points removed.
378
+ */
379
+ readonly count: number;
380
+ }
381
+
382
+ /**
383
+ * A single operation in a character-level delta describing an insert, remove, or retain of text.
384
+ * @alpha
385
+ */
386
+ export type TextOp = TextRetainOp | TextInsertOp | TextRemoveOp;
387
+
252
388
  /**
253
389
  * Statics for text nodes.
254
390
  * @alpha
@@ -276,6 +412,7 @@ export namespace TextAsTree {
276
412
  *
277
413
  * @see {@link TextAsTree.Statics.fromString} for construction.
278
414
  * @see {@link TextAsTree.(Tree:type)} for schema.
415
+ * @sealed
279
416
  * @alpha
280
417
  */
281
418
  export interface Members {
@@ -325,6 +462,22 @@ export namespace TextAsTree {
325
462
  * See {@link (TreeArrayNode:interface).removeRange} for more details on the behavior.
326
463
  */
327
464
  removeRange(startIndex: number | undefined, endIndex: number | undefined): void;
465
+
466
+ /**
467
+ * Subscribe to shallow character-level changes on this text node — inserts and removes only.
468
+ * @param callback - Called after each change with a sequence of {@link TextAsTree.TextOp}s describing what changed,
469
+ * or `undefined` when a delta could not be computed (e.g. during a schema upgrade).
470
+ * @returns A cleanup function that unsubscribes the callback when called.
471
+ * @remarks
472
+ * Only fires on shallow changes — inserts and removes.
473
+ * It does not fire on deep changes such as formatting property updates on existing characters.
474
+ * For formatted text, use {@link @fluidframework/tree#FormattedTextAsTree.Members.onContentChanged} to also receive deep changes.
475
+ *
476
+ * All counts in the delivered ops are in Unicode code points, not UTF-16 code units.
477
+ * For characters outside the Basic Multilingual Plane (e.g. emoji), one code point
478
+ * corresponds to two UTF-16 code units — convert before using the counts as string indices.
479
+ */
480
+ onCharactersChanged(callback: (ops: readonly TextOp[] | undefined) => void): () => void;
328
481
  }
329
482
 
330
483
  /**
@@ -31,7 +31,11 @@ import type {
31
31
  } from "../simple-tree/index.js";
32
32
  import { brand, mapIterable, validateIndex, validateIndexRange } from "../util/index.js";
33
33
 
34
- import { charactersFromString, type TextAsTree } from "./textDomain.js";
34
+ import {
35
+ charactersFromString,
36
+ processCharactersChangedDelta,
37
+ type TextAsTree,
38
+ } from "./textDomain.js";
35
39
 
36
40
  const sf = new SchemaFactoryAlpha("com.fluidframework.text.formatted");
37
41
 
@@ -169,6 +173,15 @@ class TextNode
169
173
  // If this node does not have a corresponding branch, then it is unhydrated.
170
174
  // I.e., it is not part of a collaborative session yet.
171
175
  // Therefore, we don't need to run the edits as a transaction.
176
+ // Note: for unhydrated nodes each atom edit fires a separate `treeChanged` event,
177
+ // so formatting N atoms will produce N callbacks on `onContentChanged` subscribers
178
+ // instead of the single callback that hydrated (transacted) edits produce.
179
+ // `withBufferedTreeEvents` is not a viable mitigation here: when more than one atom's
180
+ // `format` field changes within the same buffered scope, the kernel's per-field
181
+ // dedup logic discards the delta (see `treeNodeKernel.ts` `#fieldMarksBuffer`),
182
+ // which is worse for incremental consumers than N well-formed callbacks.
183
+ // Use `runTransaction` on a hydrated node (i.e. after inserting into the document)
184
+ // if batched events matter.
172
185
  applyFormatting();
173
186
  } else {
174
187
  // Wrap all formatting operations in a single transaction for atomicity.
@@ -177,6 +190,43 @@ class TextNode
177
190
  });
178
191
  }
179
192
  }
193
+ /**
194
+ * Returns the character string at the given atom index, or `undefined` if out of bounds.
195
+ * @remarks
196
+ * Line atoms expand to `"\n"`; text atoms return their underlying code point(s).
197
+ */
198
+ private getAtomCharacterAt(index: number): string | undefined {
199
+ const atom = this.content[index];
200
+ if (atom === undefined) return undefined;
201
+ return atom.content instanceof FormattedTextAsTree.StringLineAtom
202
+ ? "\n"
203
+ : atom.content.content;
204
+ }
205
+
206
+ public onCharactersChanged(
207
+ callback: (ops: readonly TextAsTree.TextOp[] | undefined) => void,
208
+ ): () => void {
209
+ return TreeAlpha.on(this.content, "nodeChanged", ({ delta }) =>
210
+ processCharactersChangedDelta(
211
+ delta,
212
+ (index) => this.getAtomCharacterAt(index),
213
+ callback,
214
+ ),
215
+ );
216
+ }
217
+
218
+ public onContentChanged(
219
+ callback: (ops: readonly TextAsTree.TextOp[] | undefined) => void,
220
+ ): () => void {
221
+ return TreeAlpha.on(this.content, "treeChanged", ({ delta }) =>
222
+ processCharactersChangedDelta(
223
+ delta,
224
+ (index) => this.getAtomCharacterAt(index),
225
+ callback,
226
+ ),
227
+ );
228
+ }
229
+
180
230
  public getUniformRun(startIndex: number, endIndex?: number): number {
181
231
  return this.content.getUniformRun(startIndex, endIndex);
182
232
  }
@@ -363,7 +413,7 @@ export namespace FormattedTextAsTree {
363
413
  /**
364
414
  * The underlying text content of this atom.
365
415
  * @remarks
366
- * This is typically a single unicode codepoint, and thus may contain multiple utf-16 surrogate pair code units.
416
+ * This is typically a single Unicode code point, and thus may contain multiple UTF-16 surrogate pair code units.
367
417
  * Using longer strings is still valid. For example, so users might store whole grapheme clusters here, or even longer sections of text.
368
418
  * Anything combined into a single atom will be treated atomically, and can not be partially selected or formatted.
369
419
  * Using larger atoms and splitting them as needed is NOT a recommended approach, since this will result in poor merge behavior for concurrent edits.
@@ -529,6 +579,27 @@ export namespace FormattedTextAsTree {
529
579
  * @param endIndex - Optional ending index (exclusive). Defaults to the end of the text.
530
580
  */
531
581
  getString(startIndex: number, endIndex?: number): string;
582
+
583
+ /**
584
+ * Subscribe to all content changes on this text node, including both shallow
585
+ * changes (inserts/removes) and deep changes (formatting updates on existing characters).
586
+ * @param callback - Called after each change with a sequence of {@link TextAsTree.TextOp}s describing what changed,
587
+ * or `undefined` when a delta could not be computed (e.g. during a schema upgrade).
588
+ * @returns A cleanup function that unsubscribes the callback when called.
589
+ * @remarks
590
+ * Unlike {@link TextAsTree.Members.onCharactersChanged} which only fires on
591
+ * shallow changes (inserts and removes), this method also fires on deep changes —
592
+ * formatting property updates on existing characters.
593
+ * The {@link TextAsTree.TextRetainOp.formattingChanged} flag on retain ops
594
+ * indicates which character ranges had formatting updates.
595
+ *
596
+ * All counts in the delivered ops are in Unicode code points, not UTF-16 code units.
597
+ * For characters outside the Basic Multilingual Plane (e.g. emoji), one code point
598
+ * corresponds to two UTF-16 code units — convert before using the counts as string indices.
599
+ */
600
+ onContentChanged(
601
+ callback: (ops: readonly TextAsTree.TextOp[] | undefined) => void,
602
+ ): () => void;
532
603
  }
533
604
 
534
605
  /**
@@ -17,6 +17,10 @@ import {
17
17
  import { UsageError } from "@fluidframework/telemetry-utils/internal";
18
18
 
19
19
  import { FluidClientVersion, type FormatVersion } from "./codec/index.js";
20
+ import {
21
+ detachedFieldIndexCodecBuilder,
22
+ DetachedFieldIndexFormatVersion,
23
+ } from "./core/index.js";
20
24
  import {
21
25
  SharedTreeKernel,
22
26
  type ITreePrivate,
@@ -227,6 +231,7 @@ const sharedBranchesOptions: SharedTreeOptionsInternal = {
227
231
  writeVersionOverrides: new Map<string, FormatVersion>([
228
232
  [editManagerCodecName, EditManagerFormatVersion.vSharedBranches],
229
233
  [messageCodecName, MessageFormatVersion.vSharedBranches],
234
+ [detachedFieldIndexCodecBuilder.name, DetachedFieldIndexFormatVersion.v2],
230
235
  ]),
231
236
  allowPossiblyIncompatibleWriteVersionOverrides: true,
232
237
  };
@@ -29,13 +29,14 @@ export class Breakable {
29
29
  * @remarks
30
30
  * Can use {@link throwIfBroken} to apply this to a method.
31
31
  */
32
- public use(): void {
32
+ public use(
33
+ message: (brokenBy: Error) => string = (brokenBy) =>
34
+ `Invalid use of ${this.name} after it was put into an invalid state by another error.\nOriginal Error:\n${brokenBy}`,
35
+ ): void {
33
36
  if (this.brokenBy !== undefined) {
34
- const error = new UsageError(
35
- `Invalid use of ${this.name} after it was put into an invalid state by another error.\nOriginal Error:\n${this.brokenBy}`,
36
- );
37
+ const error = new UsageError(message(this.brokenBy));
37
38
 
38
- // This "cause" field is added in ES2022, but using if even without that built in support, it is still helpful.
39
+ // This "cause" field is added in ES2022, but using it even without that built in support, it is still helpful.
39
40
  // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause
40
41
  // TODO: remove this cast when targeting ES2022 lib or later.
41
42
  (error as { cause?: unknown }).cause =
@@ -80,11 +81,31 @@ export class Breakable {
80
81
  * Like {@link Breakable.use}, this also throws if already broken.
81
82
  * Any exceptions this catches are re-thrown.
82
83
  * Can use {@link breakingMethod} to apply this to a method.
84
+ *
85
+ * If `breaker` returns a Promise, the breakable is also broken if that Promise rejects, and the broken state is rechecked when it resolves:
86
+ * if the breakable was put into a broken state during the async operation (by some other code path), the resolved value is discarded and the returned Promise rejects with a {@link UsageError}.
87
+ *
88
+ * This does not serialize concurrent runs: a synchronous run invoked while an async run is in flight will execute immediately, and is only blocked if the breakable is already broken.
89
+ * Detection of an async result uses `instanceof Promise`, so custom Promise-like objects and Promises from other realms will be treated as synchronous results.
83
90
  */
84
91
  public run<TResult>(breaker: () => TResult): TResult {
85
92
  this.use();
86
93
  try {
87
- return breaker();
94
+ const result = breaker();
95
+ if (result instanceof Promise) {
96
+ return result.then(
97
+ (value: Awaited<TResult>) => {
98
+ // If broken while process was running: this will throw instead of returning the value.
99
+ this.use(
100
+ (brokenBy) =>
101
+ `${this.name} was put into a broken state during an async operation.\nOriginal Error:\n${brokenBy}`,
102
+ );
103
+ return value;
104
+ },
105
+ (error: unknown) => this.rethrowCaught(error),
106
+ ) as TResult;
107
+ }
108
+ return result;
88
109
  } catch (error: unknown) {
89
110
  this.rethrowCaught(error);
90
111
  }