diff --git a/.changeset/tricky-bees-peel.md b/.changeset/tricky-bees-peel.md new file mode 100644 index 00000000..5130f0d3 --- /dev/null +++ b/.changeset/tricky-bees-peel.md @@ -0,0 +1,5 @@ +--- +"loro-crdt": patch +--- + +Better event ordering diff --git a/crates/loro-internal/src/state.rs b/crates/loro-internal/src/state.rs index 9ef61f1c..9c1b8e2f 100644 --- a/crates/loro-internal/src/state.rs +++ b/crates/loro-internal/src/state.rs @@ -1302,7 +1302,16 @@ impl DocState { // Sort by path length, so caller can apply the diff from the root to the leaf. // Otherwise, the caller may use a wrong path to apply the diff. - diff.sort_by_key(|x| x.path.len()); + + diff.sort_by_key(|x| { + ( + x.path.len(), + match &x.id { + ContainerID::Root { .. } => 0, + ContainerID::Normal { counter, .. } => *counter + 1, + }, + ) + }); DocDiff { from, to, diff --git a/crates/loro/tests/loro_rust_test.rs b/crates/loro/tests/loro_rust_test.rs index 193132d5..ebbd33d2 100644 --- a/crates/loro/tests/loro_rust_test.rs +++ b/crates/loro/tests/loro_rust_test.rs @@ -2350,6 +2350,23 @@ fn test_detach_and_attach() { assert!(!doc.is_detached()); } +#[test] +fn test_event_order() { + let doc = LoroDoc::new(); + let _sub = doc.subscribe_root(Arc::new(|e| { + let e0 = &e.events[0].diff; + assert!(e0.is_map()); + let e1 = &e.events[1].diff; + assert!(e1.is_list()); + let e2 = &e.events[2].diff; + assert!(e2.is_tree()); + })); + doc.get_map("map").insert("key", "value").unwrap(); + doc.get_list("list").insert(0, "item").unwrap(); + doc.get_tree("tree").create(None).unwrap(); + doc.commit(); +} + #[test] fn test_rust_get_value_by_path() { let doc = LoroDoc::new();