Skip to content

fix(loro.js): use Rust's L{lamport}@{peer} format for movable-list JSON element IDs - #1129

Merged
zxch3n merged 1 commit into
mainfrom
fix/loro-js-json-movable-elem-id
Sep 27, 2026
Merged

zxch3n merged 1 commit into
mainfrom
fix/loro-js-json-movable-elem-id

Conversation

@zxch3n

@zxch3n zxch3n commented Sep 27, 2026

Copy link
Copy Markdown
Member

Summary

Found while porting the Rust #1125 MovableList tests to loro.js: their forged JSON updates ("elem_id": "L1@0") could not be imported.

JSON updates that contain MovableList move/set ops are not interoperable between loro.js and Rust/loro-crdt:

  • Rust writes elem_id as IdLp, which is L{lamport}@{peer} (crates/loro-common/src/id.rs).
  • loro.js wrote {lamport}@{peer}. Rust rejects that with DecodeError("Invalid ID format").
  • loro.js fails on Rust's form with counter is out of range: NaN. The Rust fixture loro-js/tests/fixtures/rust/updates.json already contained such ops but was not imported by any test.

Fix

exportJsonUpdates now writes L{lamport}@{peer}. importJsonUpdates accepts it and still accepts the unprefixed form that loro.js 0.2.1 and earlier wrote. The elem_id field type changes from JsonOpID to a new exported JsonIdLp.

Validation

  • New test in loro-js/tests/runtime.test.ts: it imports Rust's updates.json, checks it against the same history from updates.blob, and asserts every exported elem_id matches ^L\d+@\d+$. It also checks that the legacy unprefixed JSON still imports. The test fails on main with counter is out of range: NaN. Binary values are normalized in the comparison because the JSON schema stores them as number arrays, and Rust's own JSON round trip does the same.
  • Cross-runtime check: Rust main imports loro.js JSON (move + set) and reaches the same value, {"l":["b","B","a"]}. Before this change it failed to decode.
  • pnpm --dir loro-js test (17 files, 241 tests), typecheck, lint, format:check all pass.
  • No performance impact: this only changes a string prefix on JSON export and import.

Related: #1125, whose tests use this format.

🤖 Generated with Claude Code

…t JSON element IDs

Rust rejected loro.js JSON updates containing movable-list moves or sets, and
loro.js failed on Rust's. The unprefixed form is still accepted on import.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

WASM Size Report

  • Original size: 3200.65 KB
  • Gzipped size: 1058.59 KB
  • Brotli size: 741.14 KB

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.

1 participant