mirror of
https://github.com/loro-dev/loro.git
synced 2025-01-22 21:07:43 +00:00
fix: should filter out non-active spans on delete
This commit is contained in:
parent
ec07825c4f
commit
a2fcd73b44
8 changed files with 42 additions and 24 deletions
|
@ -142,6 +142,7 @@ impl Container for TextContainer {
|
|||
common_ancestors_vv.retreat(&path_to_head.right);
|
||||
let mut latest_head: SmallVec<[ID; 2]> = self.head.clone();
|
||||
latest_head.push(new_op_id);
|
||||
debug_log!("START FROM {:?}", &common_ancestors_vv);
|
||||
if common_ancestors.is_empty()
|
||||
|| !common_ancestors.iter().all(|x| self.tracker.contains(*x))
|
||||
{
|
||||
|
@ -166,7 +167,7 @@ impl Container for TextContainer {
|
|||
"Stage1 retreat:{} forward:{}\n{}",
|
||||
format!("{:?}", &iter.retreat).red(),
|
||||
format!("{:?}", &iter.forward).red(),
|
||||
format!("{:#?}", &change).blue(),
|
||||
// format!("{:#?}", &change).blue(),
|
||||
);
|
||||
for op in change.ops.iter() {
|
||||
if op.container == self.id {
|
||||
|
@ -182,7 +183,7 @@ impl Container for TextContainer {
|
|||
self.tracker.checkout(&self.vv);
|
||||
debug_log!(
|
||||
"Iterate path: {} from {} => {}",
|
||||
format!("{:?}", path.left).red(),
|
||||
format!("{:?}", path.right).red(),
|
||||
format!("{:?}", self.head).red(),
|
||||
format!("{:?}", latest_head).red(),
|
||||
);
|
||||
|
|
|
@ -230,7 +230,7 @@ impl Tracker {
|
|||
unsafe { crdt_list::yata::integrate::<YataImpl>(self, yspan) };
|
||||
}
|
||||
ListOp::Delete { pos, len } => {
|
||||
let spans = self.content.get_id_spans(*pos, *len);
|
||||
let spans = self.content.get_active_id_spans(*pos, *len);
|
||||
self.update_spans(&spans, StatusChange::Delete);
|
||||
self.id_to_cursor
|
||||
.set((id).into(), cursor_map::Marker::Delete(spans));
|
||||
|
|
|
@ -120,16 +120,18 @@ impl ContentMap {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_id_spans(&self, pos: usize, len: usize) -> RleVec<IdSpan> {
|
||||
pub fn get_active_id_spans(&self, pos: usize, len: usize) -> RleVec<IdSpan> {
|
||||
let mut ans = RleVec::new();
|
||||
for cursor in self.iter_range(pos, Some(pos + len)) {
|
||||
let id = cursor.as_ref().id;
|
||||
let cursor = cursor.unwrap();
|
||||
ans.push(IdSpan::new(
|
||||
id.client_id,
|
||||
id.counter + (cursor.offset as i32),
|
||||
id.counter + (cursor.offset + cursor.len) as i32,
|
||||
));
|
||||
if cursor.as_ref().status.is_activated() {
|
||||
let cursor = cursor.unwrap();
|
||||
ans.push(IdSpan::new(
|
||||
id.client_id,
|
||||
id.counter + (cursor.offset as i32),
|
||||
id.counter + (cursor.offset + cursor.len) as i32,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
ans
|
||||
|
|
|
@ -285,7 +285,7 @@ pub mod fuzz {
|
|||
return RleVec::new();
|
||||
}
|
||||
|
||||
container.content.get_id_spans(pos, len)
|
||||
container.content.get_active_id_spans(pos, len)
|
||||
}
|
||||
|
||||
fn integrate_delete_op(container: &mut Self::Container, op: Self::DeleteOp) {
|
||||
|
|
|
@ -1110,6 +1110,7 @@ mod dag_partial_iter {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn issue() {
|
||||
if let Err(err) = test_partial_iter(
|
||||
5,
|
||||
|
@ -1142,6 +1143,7 @@ mod dag_partial_iter {
|
|||
|
||||
proptest! {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn proptest_iter_2(
|
||||
interactions in prop::collection::vec(gen_interaction(2), 0..40 * PROPTEST_FACTOR_10),
|
||||
) {
|
||||
|
|
|
@ -308,8 +308,28 @@ mod test {
|
|||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
test_single_client(vec![])
|
||||
fn test_two_1() {
|
||||
test_multi_sites(
|
||||
2,
|
||||
vec![
|
||||
Ins {
|
||||
content: "1".into(),
|
||||
pos: 0,
|
||||
site: 0,
|
||||
},
|
||||
Sync { from: 0, to: 1 },
|
||||
Del {
|
||||
pos: 0,
|
||||
len: 1,
|
||||
site: 1,
|
||||
},
|
||||
Ins {
|
||||
content: "2".into(),
|
||||
pos: 1,
|
||||
site: 0,
|
||||
},
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -25,12 +25,13 @@ macro_rules! fx_map {
|
|||
macro_rules! debug_log {
|
||||
() => {
|
||||
if cfg!(test) {
|
||||
// $crate::print!("\n")
|
||||
// $crate::print!("\n")
|
||||
}
|
||||
};
|
||||
($($arg:tt)*) => {{
|
||||
if cfg!(test) {
|
||||
// print!("{}:{}\t", file!(), line!());
|
||||
// use colored::Colorize;
|
||||
// print!("{}:{}\t", file!().purple(), line!().to_string().purple());
|
||||
// println!($($arg)*);
|
||||
}
|
||||
}};
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
|
||||
use crate::Rle;
|
||||
|
||||
use super::{
|
||||
|
@ -104,18 +102,12 @@ impl<'tree, T: Rle, A: RleTreeTrait<T>> Iter<'tree, T, A> {
|
|||
#[inline]
|
||||
pub fn from_cursor(
|
||||
mut start: SafeCursor<'tree, T, A>,
|
||||
mut end: Option<SafeCursor<'tree, T, A>>,
|
||||
end: Option<SafeCursor<'tree, T, A>>,
|
||||
) -> Option<Self> {
|
||||
if start.0.pos == Position::After {
|
||||
start = start.next_elem_start()?
|
||||
}
|
||||
|
||||
if let Some(end_inner) = end {
|
||||
if end_inner.0.pos == Position::End || end_inner.0.pos == Position::After {
|
||||
end = end_inner.next_elem_start();
|
||||
}
|
||||
}
|
||||
|
||||
Some(Self {
|
||||
cursor: Some(start.0),
|
||||
end_cursor: end.map(|x| x.0),
|
||||
|
|
Loading…
Reference in a new issue