Conversation
…call
Mirror initialization previously walked the document container by
container (~10 wasm crossings per container: id/kind/get/keys/toJSON).
buildRootStateSnapshot now reads the whole doc with a single
doc.getDeepValueWithID() call and builds state, $cid markers,
containerRegistry, inferOptionsByContainerId and rootPathById in one JS
walk that replicates registerChildContainer/containerToMirrorState
semantics exactly. No container handles are created during init; trees
and unhandled kinds fall back to the existing handle-based logic, and
the legacy traversal is kept as a fallback for loro-crdt versions
without getDeepValueWithID.
- Defensive cid parsing: tolerates both the Debug-like
"idx:N, id:cid:..." format and bare container ids.
- loro-crdt <1.15 drops the {value,cid} wrapper for empty containers,
making them indistinguishable from embedded plain values; the walk
disambiguates via the parent's cached getShallowValue() (one extra
call per affected parent only).
- Adds a seeded parity fuzz test (bulk vs legacy: state, $cid via
cidsEqual, registry, infer options) and a dependency-free benchmark
(pnpm bench:bulk-init, ~67k-container session-history-shaped doc):
wasm crossings during init drop from ~527k to 1.
This was referenced Sep 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem and behavior
Mirror initialization previously traversed document containers through many individual WASM calls. This PR builds state,
$cidmarkers, schema registrations, and inference options from onedoc.getDeepValueWithID()snapshot and a JS walk. Trees and unsupported shapes retain the handle-based fallback; versions without the deep-value API retain the legacy snapshot path.Container identity is verified against a cached parent shallow read before a child wrapper is interpreted. Embedded user objects such as
{ cid: "cid:root-other:Map", value: { message: "kept" }, extra: 123 }remain intact rather than being unwrapped. This also handles empty containers with omitted wrappers in loro-crdt 1.13.3. Old mergeable-reference binary markers use a targetedget()check to distinguish containers from user bytes.The deep-value CID parser supports Debug-format and bare IDs. Unknown-root normalization, Ignore fields, decoding, and incremental state behavior are retained.
Validation
Performance limitation
The correctness fix requires additional parent shallow reads; this is not a one-WASM-call initialization. The benchmark now reports these reads explicitly.
Same-process Node 22 / locked loro-crdt 1.13.3 comparison, 171 entries × 30 items (~67k containers), 3 warmups and 10 samples, explicit GC:
The corrected bulk path is slower in this measurement. The original speedup / projected 2× claim is not an acceptance result for the corrected code; performance needs further work before this PR should be merged as an optimization. Read counts above are instrumented methods, not every WASM crossing.
Published loro-crdt 1.16.0 follow-up
Updated core/react/jotai loro-crdt requirements and the lockfile to ^1.16.0 / 1.16.0. Build, 525 tests, lint (0 errors), and typecheck pass. A fresh default ~67k-container benchmark on the published package reports bulk p50 360.044 ms (1 deep read, 15,733 instrumented parent shallow reads). The older 1.13.3 comparison above remains historical; this change does not replace the standalone performance acceptance requirement. #98 now tests the published container-tree path.