diff --git a/.changeset/text-edit-utf16-quadratic.md b/.changeset/text-edit-utf16-quadratic.md deleted file mode 100644 index 26305fa7c..000000000 --- a/.changeset/text-edit-utf16-quadratic.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -"loro-crdt": patch -"loro-crdt-map": patch ---- - -Fix two O(n^2) editing slowdowns. - -1. Editing with UTF-16 / UTF-8 (byte) positions (the default in the JS binding) - validated each position by materializing the entire `[0, pos)` prefix string, - making every `insert`/`delete`/`splice`/`mark` O(n) and a run of edits O(n^2) - (regression since 1.12.0). The boundary check now reads the rope's prefix - caches via the cursor (O(log n)). Unicode-indexed editing was unaffected. - -2. When a subscriber is attached and many edits land on the same container within - one event batch (e.g. random-position inserts, or many distinct map-key - writes), building the event cloned the growing accumulated diff on every - compose — O(n^2) in the number of fragments. The diffs are now composed in - place. This affected text, map and list events. - -3. Converting a UTF-16 / UTF-8 position within a text chunk to a unicode offset - scanned the chunk char-by-char, so editing/slicing a large contiguous chunk - (a big insert, a loaded document, or a long run of typed text that merges into - one chunk) was O(chunk length) per op. Chunks that contain no astral-plane - characters (UTF-16) or are pure ASCII (UTF-8) now convert in O(1), covering - essentially all real-world text (ASCII/Latin/CJK). diff --git a/crates/loro-wasm-map/CHANGELOG.md b/crates/loro-wasm-map/CHANGELOG.md index fec729e35..e67794d89 100644 --- a/crates/loro-wasm-map/CHANGELOG.md +++ b/crates/loro-wasm-map/CHANGELOG.md @@ -1,5 +1,28 @@ # loro-crdt-map +## 1.13.4 + +### Patch Changes + +- 4d577ad: Fix two O(n^2) editing slowdowns. + + 1. Editing with UTF-16 / UTF-8 (byte) positions (the default in the JS binding) + validated each position by materializing the entire `[0, pos)` prefix string, + making every `insert`/`delete`/`splice`/`mark` O(n) and a run of edits O(n^2) + (regression since 1.12.0). The boundary check now reads the rope's prefix + caches via the cursor (O(log n)). Unicode-indexed editing was unaffected. + 2. When a subscriber is attached and many edits land on the same container within + one event batch (e.g. random-position inserts, or many distinct map-key + writes), building the event cloned the growing accumulated diff on every + compose — O(n^2) in the number of fragments. The diffs are now composed in + place. This affected text, map and list events. + 3. Converting a UTF-16 / UTF-8 position within a text chunk to a unicode offset + scanned the chunk char-by-char, so editing/slicing a large contiguous chunk + (a big insert, a loaded document, or a long run of typed text that merges into + one chunk) was O(chunk length) per op. Chunks that contain no astral-plane + characters (UTF-16) or are pure ASCII (UTF-8) now convert in O(1), covering + essentially all real-world text (ASCII/Latin/CJK). + ## 1.13.0 ### Minor Changes diff --git a/crates/loro-wasm-map/package.json b/crates/loro-wasm-map/package.json index 0c7845ede..d6f4f12d5 100644 --- a/crates/loro-wasm-map/package.json +++ b/crates/loro-wasm-map/package.json @@ -1,6 +1,6 @@ { "name": "loro-crdt-map", - "version": "1.13.3", + "version": "1.13.4", "description": "Source maps for the loro-crdt WebAssembly bundles.", "repository": { "type": "git", diff --git a/crates/loro-wasm/CHANGELOG.md b/crates/loro-wasm/CHANGELOG.md index 40d025878..62194deed 100644 --- a/crates/loro-wasm/CHANGELOG.md +++ b/crates/loro-wasm/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## 1.13.4 + +### Patch Changes + +- 4d577ad: Fix two O(n^2) editing slowdowns. + + 1. Editing with UTF-16 / UTF-8 (byte) positions (the default in the JS binding) + validated each position by materializing the entire `[0, pos)` prefix string, + making every `insert`/`delete`/`splice`/`mark` O(n) and a run of edits O(n^2) + (regression since 1.12.0). The boundary check now reads the rope's prefix + caches via the cursor (O(log n)). Unicode-indexed editing was unaffected. + 2. When a subscriber is attached and many edits land on the same container within + one event batch (e.g. random-position inserts, or many distinct map-key + writes), building the event cloned the growing accumulated diff on every + compose — O(n^2) in the number of fragments. The diffs are now composed in + place. This affected text, map and list events. + 3. Converting a UTF-16 / UTF-8 position within a text chunk to a unicode offset + scanned the chunk char-by-char, so editing/slicing a large contiguous chunk + (a big insert, a loaded document, or a long run of typed text that merges into + one chunk) was O(chunk length) per op. Chunks that contain no astral-plane + characters (UTF-16) or are pure ASCII (UTF-8) now convert in O(1), covering + essentially all real-world text (ASCII/Latin/CJK). + ## 1.13.3 ### Patch Changes diff --git a/crates/loro-wasm/Cargo.toml b/crates/loro-wasm/Cargo.toml index 5a935c20e..7ae83be26 100644 --- a/crates/loro-wasm/Cargo.toml +++ b/crates/loro-wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "loro-wasm" -version = "1.13.3" +version = "1.13.4" edition = "2021" publish = false repository = "https://github.com/loro-dev/loro/" diff --git a/crates/loro-wasm/package.json b/crates/loro-wasm/package.json index 1de91f2c3..0f2b6e082 100644 --- a/crates/loro-wasm/package.json +++ b/crates/loro-wasm/package.json @@ -1,6 +1,6 @@ { "name": "loro-crdt", - "version": "1.13.3", + "version": "1.13.4", "description": "Loro CRDTs is a high-performance CRDT framework that makes your app state synchronized, collaborative and maintainable effortlessly.", "keywords": [ "crdt",