Skip to content

Commit

Permalink
Merge pull request #459 from streamich/delete-lifecycle
Browse files Browse the repository at this point in the history
Propagate `delete` event
  • Loading branch information
streamich authored Nov 25, 2023
2 parents 8c2dcfe + 46e75f8 commit a63f12b
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/json-crdt/model/Model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {AvlMap} from '../../util/trees/avl/AvlMap';
import type {JsonNode, JsonNodeView} from '../nodes/types';
import type {Printable} from '../../util/print/types';
import type {NodeBuilder} from '../../json-crdt-patch';
import type {NodeApi} from './api/nodes';

export const UNDEFINED = new ConNode(ORIGIN, undefined);

Expand Down Expand Up @@ -291,6 +292,8 @@ export class Model<N extends JsonNode = JsonNode> implements Printable {
if (isSystemNode) return;
const node = this.index.get(value);
if (!node) return;
const api = node.api;
if (api) (api as NodeApi).events.onDelete();
node.children((child) => this.deleteNodeTree(child.id));
this.index.del(value);
}
Expand Down
25 changes: 25 additions & 0 deletions src/json-crdt/model/api/__tests__/NodeEvents.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {Model} from '../..';

test('does not fire events after node is deleted', () => {
const model = Model.withLogicalClock();
model.api.root({
foo: {
bar: {
baz: 'asdf',
},
},
});
const bar = model.api.obj(['foo', 'bar']);
let cnt = 0;
bar.events.changes.listen(() => {
cnt++;
});
expect(cnt).toBe(0);
bar.set({
gg: 'wp',
});
expect(cnt).toBe(1);
model.api.obj(['foo']).del(['bar']);
model.api.obj(['foo']).set({gl: 'hf'});
expect(cnt).toBe(1);
});
25 changes: 24 additions & 1 deletion src/json-crdt/model/api/events/NodeEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ export interface NodeEventMap {
}

class ChangesFanOut<N extends JsonNode = JsonNode> extends FanOut<JsonNodeView<N>> {
/** @ignore */
private _v: JsonNodeView<N> | undefined = undefined;
/** @ignore */
private _u: FanOutUnsubscribe | undefined = undefined;

/** @ignore */
constructor(private readonly api: NodeApi<N>) {
super();
}
Expand All @@ -45,10 +48,20 @@ class ChangesFanOut<N extends JsonNode = JsonNode> extends FanOut<JsonNodeView<N
unsubscribe();
if (!this.listeners.size) {
this._u?.();
// this._unsub = this._view = undefined;
this._u = this._v = undefined;
}
};
}

/**
* @internal
* @ignore
*/
public dispose() {
this.listeners.clear();
this._u?.();
this._u = this._v = undefined;
}
}

export class NodeEvents<N extends JsonNode = JsonNode>
Expand Down Expand Up @@ -101,6 +114,16 @@ export class NodeEvents<N extends JsonNode = JsonNode>
super.off(type, listener, options);
}

/**
* Called when this node is deleted.
*
* @internal
* @ignore
*/
public onDelete() {
this.changes.dispose();
}

// ---------------------------------------------------------------- SyncStore

public readonly subscribe = (callback: () => void): SyncStoreUnsubscribe => {
Expand Down

0 comments on commit a63f12b

Please sign in to comment.