diff --git a/crates/loro-internal/src/handler.rs b/crates/loro-internal/src/handler.rs index 63205c279..3b43329c9 100644 --- a/crates/loro-internal/src/handler.rs +++ b/crates/loro-internal/src/handler.rs @@ -1131,7 +1131,9 @@ impl Handler { // In this method we will not clone the values of the containers if // they are remapped. It's the caller's duty to do so let on_container_remap = &mut |old_id, new_id| { - container_remap.insert(old_id, new_id); + if old_id != new_id { + container_remap.insert(old_id, new_id); + } }; match self { Self::Map(x) => { diff --git a/crates/loro-internal/tests/test.rs b/crates/loro-internal/tests/test.rs index 09886b1f5..949e768db 100644 --- a/crates/loro-internal/tests/test.rs +++ b/crates/loro-internal/tests/test.rs @@ -1513,3 +1513,31 @@ fn test_origin() { .unwrap(); sub.unsubscribe(); } + +#[test] +fn apply_diff_with_same_peer_id_should_not_hang() { + let doc1 = LoroDoc::new_auto_commit(); + doc1.set_peer_id(1).unwrap(); + + let doc2 = doc1.fork(); + doc2.set_peer_id(1).unwrap(); // Same peer ID + + // The key issue: setContainer creates a nested container + let map = doc2.get_map("root"); + let nested = map + .insert_container("nested", MapHandler::new_detached()) + .unwrap(); // This is what triggers the hang + nested.insert("key", "value").unwrap(); + doc2.commit_then_renew(); + + let frontiers_before = doc1.oplog_frontiers(); + let frontiers_after = doc2.oplog_frontiers(); + let diff = doc2.diff(&frontiers_before, &frontiers_after).unwrap(); + + // This should NOT hang + doc1.apply_diff(diff).unwrap(); + assert_eq!( + doc1.get_deep_value().to_json_value(), + doc2.get_deep_value().to_json_value() + ); +}