Repository navigation
fix(loro.js): record absent-key map deletes and zero counter increments like loro-crdt - #1145
Merged
Merged
Conversation
Three API calls produced different ops than Rust, so the same edits got different op IDs, and a concurrent map set/delete could resolve differently: - Map.delete of an absent key recorded nothing; Rust records a delete. - Counter.increment(0) and attaching a detached counter with value 0 recorded nothing; Rust records the increment. - A text delete across several ID runs was emitted left to right; Rust's TextHandler::delete emits the runs right to left. The old "no semantic no-op edits" test asserted the loro.js behavior; it now asserts Rust's. MovableList set-to-same-value (Rust records it) is left to the MovableList rework. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Contributor
WASM Size Report
|
…parity Main already writes multi-run text deletes right to left (#1136); keep its version and drop the duplicate test and changeset bullet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Summary
For two API calls
loro.jsrecorded different ops thanloro-crdt. The same edits then got different op IDs, and in one case a different concurrent result:mainloro-crdt/ this PRmap.delete("absent")setof that key: peer 1 setsk, peer 2 deletes the absentk, both merge →{}in Rust,{ k: 1 }inloro.jsonmain.counter.increment(0), attaching a detached counterCounterHandler::attachincrements by the detached value, even 0)map.setof the current value stays a no-op in both.Rationale
loro.jsaims at API compatibility withloro-crdt. Op-level parity matters for concurrent outcomes (the map case), for checking out versions inside a multi-run delete, and for any tool that compares histories across the two packages. The differential fuzz harness (#1141) needs it to run peers in lockstep with Rust: without it, most Map/Counter seeds diverge on the first such call.The old test "does not record semantic no-op edits" asserted the
loro.jsbehavior; it now asserts Rust's op counts. Rust also recordsmovableList.set(i, sameValue); that is left to the MovableList rework (#1132 stack), and the assertion was dropped from this test.Validation
loro-js/tests/runtime.test.tsfor the op counts and for the absent-key delete winning a concurrent set. Both fail onmain. The expected values are whatloro-crdt(WASM build of thismain) produces for the same calls.Op/hint length mismatch, covered by fix: rich-text insert positions near style anchors, delete IDs, and delete events #1135).pnpm --dir loro-js format:check,lint,typecheck,test(415 passed, 1 skipped; withLORO_REQUIRE_WASM_REFERENCE=1after the merge),build.bench:complexity(1k–8k), 7 alternating rounds vsmain, loadavg 30–31: 284 items, none both >1.5× and >0.3 ms slower. Total 1265 ms onmain, 1287 ms here. B4 (259,778 actions, 3 samples × 3 alternating rounds, loadavg 23–30): apply medians 305/516/774 ms onmainvs 289/500/753 ms here. The load made B4 noisy, but each round was within noise.🤖 Generated with Claude Code