Skip to content

Commit ebd67f8

Browse files
committed
fix: handle fork on shallow snapshots
1 parent 1e986f3 commit ebd67f8

File tree

4 files changed

+52
-2
lines changed

4 files changed

+52
-2
lines changed

.changeset/silver-snails-own.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"loro-crdt": patch
3+
---
4+
5+
Fix a panic when calling `fork()` on a document imported from a `shallow-snapshot`.

crates/loro-internal/src/loro.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,10 @@ impl LoroDoc {
133133

134134
let snapshot = self.with_barrier(|| encoding::fast_snapshot::encode_snapshot_inner(self));
135135
let doc = Self::new();
136-
encoding::fast_snapshot::decode_snapshot_inner(snapshot, &doc, Default::default()).unwrap();
136+
doc.with_barrier(|| {
137+
encoding::fast_snapshot::decode_snapshot_inner(snapshot, &doc, Default::default())
138+
})
139+
.unwrap();
137140
doc.set_config(&self.config);
138141
if self.auto_commit.load(std::sync::atomic::Ordering::Relaxed) {
139142
doc.start_auto_commit();

crates/loro-wasm/tests/gc.test.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,24 @@ describe("gc", () => {
4848
gcDoc.import(bytes);
4949

5050
expect(() => gcDoc.import(updates)).toThrow();
51-
})
51+
});
52+
53+
it("can fork a shallow snapshot", () => {
54+
const docA = new LoroDoc();
55+
const listA = docA.getList("list");
56+
listA.insert(0, "A");
57+
listA.insert(1, "B");
58+
listA.insert(2, "C");
59+
60+
const bytes = docA.export({
61+
mode: "shallow-snapshot",
62+
frontiers: docA.oplogFrontiers(),
63+
});
64+
65+
const docB = new LoroDoc();
66+
docB.import(bytes);
67+
68+
const docC = docB.fork();
69+
expect(docC.toJSON()).toEqual(docB.toJSON());
70+
});
5271
});

crates/loro/tests/issue.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,29 @@ fn fix_get_unknown_cursor_position() {
360360
assert!(matches!(pos, Err(..)));
361361
}
362362

363+
#[test]
364+
fn issue_924_fork_shallow_snapshot() {
365+
let doc_a = LoroDoc::new();
366+
let list_a = doc_a.get_list("list");
367+
list_a.insert(0, "A").unwrap();
368+
list_a.insert(1, "B").unwrap();
369+
list_a.insert(2, "C").unwrap();
370+
371+
let bytes = doc_a
372+
.export(ExportMode::shallow_snapshot(&doc_a.oplog_frontiers()))
373+
.unwrap();
374+
375+
let doc_b = LoroDoc::new();
376+
doc_b.import(&bytes).unwrap();
377+
378+
assert!(doc_b.is_shallow());
379+
assert!(!doc_b.is_detached());
380+
381+
let doc_c = doc_b.fork();
382+
assert!(doc_c.is_shallow());
383+
assert_eq!(doc_b.get_deep_value(), doc_c.get_deep_value());
384+
}
385+
363386
#[test]
364387
fn get_unknown_cursor_position_but_its_in_pending() {
365388
let doc_0 = LoroDoc::new();

0 commit comments

Comments
 (0)