Skip to content

chore(deps): update dependency loro-crdt to ^1.16.0 - #1866

Merged
renovate[bot] merged 1 commit into
masterfrom
renovate/loro-crdt-1-x
Sep 6, 2026
Merged

chore(deps): update dependency loro-crdt to ^1.16.0#1866
renovate[bot] merged 1 commit into
masterfrom
renovate/loro-crdt-1-x

Conversation

@renovate

@renovate renovate Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
loro-crdt (source) ^1.14.1^1.16.0 age confidence

Release Notes

loro-dev/loro (loro-crdt)

v1.16.0

Compare Source

Minor Changes
  • 98b2ac6: Add bulk deep-read APIs on containers. LoroMap/LoroList/LoroMovableList/LoroTree/LoroText now expose getDeepValueWithID() returning the same { cid, value } node shape as LoroDoc.getDeepValueWithID(). LoroList and LoroMovableList also expose getRangeDeepValueWithID(start, end) and getRangeValue(start, end) for reading a slice of a list in one WASM call; bounds are clamped (negatives to 0, overflows to the length) and empty or inverted ranges return []. Detached containers throw a readable error instead of trapping.

    Potentially breaking: the cid field in getDeepValueWithID() results is now the bare container id string (e.g. cid:92@2311024965712536503:Map, cid:root-map:Map) — exactly what the container's id property returns. Previously it was a Debug-style composite like idx:85, id:cid:92@2311024965712536503:Map. Update any consumer that parsed or matched the old idx:N, id:... shape.

  • c594ee0: Add toContainerTree() to documents and attached containers. It returns independent recursive {type, cid, value} nodes and opaque ordinary Value nodes. Documents can select visible roots without creating missing roots. Text formatting applies to all descendants and is inferred in TypeScript. List and MovableList expose toContainerTreeSlice(start, end) with explicit start, totalLength, and items. Fixed JS construction, per-read key/peer reuse, and owned binary buffers avoid a public transport protocol.

    Optional text configurations retain the default plain-text possibility in TypeScript. Literal root selections preserve their names as optional result properties.

    Compile Node snippets to CommonJS so the package does not require require(esm) support.

Patch Changes
  • fcd039c: Fix wasm memory retention when reading a document container by container
    (#​1092).

    Every read through a container handle (LoroMap.keys()/get(),
    LoroList.get(), LoroText.toJSON(), ...) decoded the container's value into
    an in-memory cache that was pinned for the lifetime of the document — about
    4 KB per container, released only by doc.free(). Walking a large document
    this way (the pattern loro-mirror's initial state build uses) retained ~4 KB ×
    containers-ever-read and trapped wasm32 at the 4 GiB limit around one million
    containers.

    The decoded-value cache is now bounded (2048 entries, second-chance FIFO).
    Evicted entries are pure caches over the KV store and are re-decoded on the
    next read, so this only changes memory behavior, not API semantics.
    doc.free() semantics are unchanged.

    Measured on the issue's repro (570-turn document, 188k container handles,
    release build): the handle walk retains no per-container memory (external
    memory flat at ~84 MiB vs +641 MiB before) and runs ~10x faster
    (1.28 s vs 12.5 s) thanks to the smaller working set.

  • f03d283: Speed up export({ mode: "shallow-snapshot" }) by up to ~20x on container-heavy documents with a large retained history.

    Building the state at the shallow root used to check the live document out
    backwards (latest -> root). That reverse diff makes the richtext/list diff
    calculators rebuild a full CRDT tracker from empty for every container touched
    in the range, which dominated the export cost: on a doc with ~66k containers
    and ~720k streaming-edit ops, shallow export at a mid-history root took ~3.2s
    versus ~1.5ms for a full snapshot. When at least 64k ops are retained since
    the root, the root state is now reconstructed by replaying the pre-root
    history forward into a temporary doc, and the latest state is read from the
    live store directly without moving the document. The pre-root prefix is bounded
    both relative to the tail (at most 16x the retained op count) and absolutely
    (at most 1M ops) and decoded payload size (at most 32 MiB, estimated by
    walking op payloads — recursing into nested values, style values, and commit
    messages — before any value is copied; op counts miss value sizes, since a Map
    write is one atom regardless of payload size), so a document whose
    pre-root history is huge or byte-heavy and unrelated to the tail keeps the
    previous checkout path. The same export drops to
    ~370ms and the produced blob is slightly smaller (~17% on the same fixture).
    With a small retained range — including a root at the latest version — the
    previous checkout path is kept: it is then equally fast and peaks at ~4x less
    memory, so exporting a lazily imported document no longer materializes its
    whole state. Exported blobs remain logically equivalent; detached or
    already-shallow source docs also keep the previous code path.

    Also fixes shallow snapshot export resurrecting, as an empty entry, a root
    container deleted with deleteRootContainer before the shallow root.

  • 7d26c7e: Reject updates concurrent with the shallow root frontier with
    ImportUpdatesThatDependsOnOutdatedVersion instead of queuing them and panicking
    while resolving a dependency that has already been trimmed. Rejected updates do
    not enter pending storage; subsequent valid post-root updates still apply.

  • 8874574: perf: cache kind() results on container wrappers. kind() returns a constant string per container class; it is now memoized after the first call, so repeated reads (e.g. tree traversal in loro-mirror) no longer cross into WASM or allocate a fresh JS string. This extends the existing id cache to kind().

v1.15.1

Compare Source

Patch Changes
  • 34b1fae: Cache immutable container ids per JavaScript wrapper to avoid repeated WASM string decoding.
  • 48b3c52: Keep malformed cid:-prefixed strings returned from toJsonWithReplacer as
    plain strings instead of throwing while resolving them as container IDs.

v1.15.0

Compare Source

Minor Changes
  • 5ea2e37: Add pause(), resume(), and isPaused() to UndoManager. While paused,
    local edits are not recorded as undo steps and checkout events do not clear the
    stacks. Import events (remote changes) are still processed so that the stacks
    remain correctly transformed against concurrent edits. Use this to preserve
    undo/redo history across temporary checkouts such as read-only history previews.
Patch Changes
  • 4d3d3f1: Shallow snapshot export no longer leaks the values of rich-text marks whose
    whole range was deleted before the shallow root.

    Deleting styled text removes the characters but keeps the style anchors, and the
    shallow-root state encoding shipped each anchor's value verbatim — so a mark
    value (e.g. an inline comment) that every read API already reported as gone
    still appeared in the exported bytes, defeating the documented content-redaction
    use of shallow snapshots. Dead style pairs now have their values nulled during
    export (anchors stay, so positions and replay are unaffected). Styles that only
    become dead after the shallow root keep their values so historical checkouts
    render correctly, and styles configured with expand: "both" are kept because
    an empty both-expand pair still applies to future inserts. Re-exporting a
    shallow snapshot produced by an older version also cleans it.

  • 4837d07: Fix unbounded degradation when re-asserting identical text marks over styled ranges.

    mark already tried to skip no-op marks, but the check used
    StyleRangeMap::get_styles_of_range, which returns None whenever the marked
    range spans more than one style-range leaf. On any document whose style ranges
    are already fragmented (i.e. any document with styles), re-asserting an
    identical mark recorded a new op every time.

    Each redundant mark leaves a pair of style anchors in the container state
    forever — they survive snapshots and are never consolidated — and every styled
    read walks all of them. Callers that re-assert marks (for example editor
    bindings syncing mark state) therefore permanently degraded styled reads without
    bound: reading a 724-character paragraph went from ~5µs to ~4ms after 1000
    redundant marks.

    The skip path now falls back to StyleRangeMap::range_has_key_value, which
    scans every style range covering the mark and reports whether each position
    already resolves the key to the given value. Attached and detached texts both
    use the new path when the single-leaf fast path cannot answer.

  • f4e011f: Fix an O(n^2) slowdown when reading styled text.

    Building the per-range style metadata for toDelta / getRichtextValue (and
    the sliced variants used to emit text events) deep-copied the whole Styles
    map once per style range. Each key in that map owns the set of every style op
    covering the range, while the resulting StyleMeta keeps only the LWW winner,
    so the copy scaled with the number of marks accumulated on the container and
    then discarded all but one element of it — O(marks) per range across O(marks)
    ranges. The conversion now borrows instead of cloning.

    Style anchors are never consolidated, so marks accumulate in the container
    state and every styled read paid for all of them. On a 724-character paragraph
    carrying 2000 accumulated marks, a styled read drops from ~103ms to ~1ms; a
    simulated editor binding that re-asserts marks on each keystroke drops from
    ~5ms to ~200us per read after 500 keystrokes.


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Enabled.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate
renovate Bot enabled auto-merge (squash) September 6, 2026 07:19
@renovate
renovate Bot merged commit e0d337f into master Sep 6, 2026
11 of 12 checks passed
@renovate
renovate Bot deleted the renovate/loro-crdt-1-x branch September 6, 2026 07:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants