Skip to content

Commit

Permalink
fix(json-crdt-extensions): 🐛 delete slices from index on deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Apr 20, 2024
1 parent f6c55b3 commit db7f10e
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 29 deletions.
7 changes: 1 addition & 6 deletions src/json-crdt-extensions/peritext/slice/PersistedSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,6 @@ export class PersistedSlice<T = string> extends Range<T> implements MutableSlice
return this.behavior === SliceBehavior.Split;
}

protected tagNode(): JsonNode | undefined {
// TODO: Normalize `.get()` and `.getNode()` methods across VecNode and ArrNode.
return this.tuple.get(3);
}

protected tupleApi() {
return this.txt.model.api.wrap(this.tuple);
}
Expand Down Expand Up @@ -109,7 +104,7 @@ export class PersistedSlice<T = string> extends Range<T> implements MutableSlice
}

public data(): unknown | undefined {
return this.tuple.get(4)?.view();
return this.tuple.get(SliceTupleIndex.Data)?.view();
}

public dataNode() {
Expand Down
1 change: 1 addition & 0 deletions src/json-crdt-extensions/peritext/slice/Slices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export class Slices implements Stateful, Printable {
}

public del(id: ITimestampStruct): void {
this.list.del(id);
const api = this.txt.model.api;
api.builder.del(this.set.id, [tss(id.sid, id.time, 1)]);
api.apply();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import {SliceBehavior} from '../constants';
import {setup} from './setup';

const setupSlice = () => {
const deps = setup();
const range = deps.peritext.rangeAt(2, 3);
const slice = deps.peritext.slices.insSplit(range, 0);
return {...deps, range, slice};
};

test('can read slice data', () => {
const {range, slice} = setupSlice();
expect(slice.isSplit()).toBe(true);
expect(slice.behavior).toBe(SliceBehavior.Split);
expect(slice.type).toBe(0);
expect(slice.data()).toBe(undefined);
expect(slice.start).not.toBe(range.start);
expect(slice.start.cmp(range.start)).toBe(0);
expect(slice.end).not.toBe(range.end);
expect(slice.end.cmp(range.end)).toBe(0);
});

describe('.update()', () => {
const testUpdate = (name: string, update: (deps: ReturnType<typeof setupSlice>) => void) => {
test('can update: ' + name, () => {
const deps = setupSlice();
const {slice} = deps;
const hash1 = slice.refresh();
const hash2 = slice.refresh();
expect(hash1).toBe(hash2);
update(deps);
const hash3 = slice.refresh();
expect(hash3).not.toBe(hash2);
});
};

testUpdate('behavior', ({slice}) => {
slice.update({behavior: SliceBehavior.Erase});
expect(slice.behavior).toBe(SliceBehavior.Erase);
});

testUpdate('type', ({slice}) => {
slice.update({type: 1});
expect(slice.type).toBe(1);
});

testUpdate('data', ({slice}) => {
slice.update({data: 123});
expect(slice.data()).toBe(123);
});

testUpdate('range', ({peritext, slice}) => {
const range2 = peritext.rangeAt(0, 1);
slice.update({range: range2});
expect(slice.cmp(range2)).toBe(0);
});
});

describe('.del() and .isDel()', () => {
test('can delete a slice', () => {
const {peritext, slice} = setupSlice();
expect(peritext.model.view().slices.length).toBe(1);
expect(slice.isDel()).toBe(false);
const slice2 = peritext.slices.get(slice.id)!;
expect(peritext.model.view().slices.length).toBe(1);
expect(slice2.isDel()).toBe(false);
expect(slice2).toBe(slice);
slice.del();
expect(peritext.model.view().slices.length).toBe(0);
expect(slice.isDel()).toBe(true);
expect(slice2.isDel()).toBe(true);
const slice3 = peritext.slices.get(slice.id);
expect(slice3).toBe(undefined);
});
});

25 changes: 2 additions & 23 deletions src/json-crdt-extensions/peritext/slice/__tests__/Slices.spec.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,10 @@
import {Model, ObjApi} from '../../../../json-crdt/model';
import {Model} from '../../../../json-crdt/model';
import {Peritext} from '../../Peritext';
import {Range} from '../../rga/Range';
import {Anchor} from '../../rga/constants';
import {PersistedSlice} from '../PersistedSlice';
import {SliceBehavior} from '../constants';

const setup = () => {
const model = Model.withLogicalClock(12345678);
model.api.root({
text: '',
slices: [],
});
model.api.str(['text']).ins(0, 'wworld');
model.api.str(['text']).ins(0, 'helo ');
model.api.str(['text']).ins(2, 'l');
model.api.str(['text']).del(7, 1);
model.api.str(['text']).ins(11, ' this game is awesome');
const peritext = new Peritext(model, model.api.str(['text']).node, model.api.arr(['slices']).node);
const slices = peritext.slices;
const encodeAndDecode = () => {
const buf = model.toBinary();
const model2 = Model.fromBinary(buf);
const peritext2 = new Peritext(model2, model2.api.str(['text']).node, model2.api.arr(['slices']).node);
return {model2, peritext2};
};
return {model, peritext, slices, encodeAndDecode};
};
import {setup} from './setup';

test('initially slice list is empty', () => {
const {peritext} = setup();
Expand Down
24 changes: 24 additions & 0 deletions src/json-crdt-extensions/peritext/slice/__tests__/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {Model} from '../../../../json-crdt/model';
import {Peritext} from '../../Peritext';

export const setup = () => {
const model = Model.withLogicalClock(12345678);
model.api.root({
text: '',
slices: [],
});
model.api.str(['text']).ins(0, 'wworld');
model.api.str(['text']).ins(0, 'helo ');
model.api.str(['text']).ins(2, 'l');
model.api.str(['text']).del(7, 1);
model.api.str(['text']).ins(11, ' this game is awesome');
const peritext = new Peritext(model, model.api.str(['text']).node, model.api.arr(['slices']).node);
const slices = peritext.slices;
const encodeAndDecode = () => {
const buf = model.toBinary();
const model2 = Model.fromBinary(buf);
const peritext2 = new Peritext(model2, model2.api.str(['text']).node, model2.api.arr(['slices']).node);
return {model2, peritext2};
};
return {model, peritext, slices, encodeAndDecode};
};

0 comments on commit db7f10e

Please sign in to comment.