Skip to content

Commit

Permalink
perf(computed): clear subscriptions when untracked by all subscribers
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk committed Oct 7, 2024
1 parent 430a509 commit f2fa4a3
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 7 deletions.
5 changes: 1 addition & 4 deletions lib/computed.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { currentEffectScope } from './effectScope';
import { Dependency, DirtyLevels, Subscriber } from './system';

export function computed<T>(getter: (cachedValue?: T) => T) {
Expand All @@ -20,9 +19,7 @@ export class Computed<T = any> implements Dependency, Subscriber {

constructor(
public getter: (cachedValue?: T) => T
) {
currentEffectScope?.subs.push(this);
}
) { }

get(): T {
Dependency.link(this);
Expand Down
9 changes: 6 additions & 3 deletions lib/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export namespace Link {
}

export function release(link: Link) {
const dep = link.dep as Dependency & ({} | Subscriber);
const nextSub = link.nextSub;
const prevSub = link.prevSubOrUpdate;

Expand Down Expand Up @@ -130,6 +131,10 @@ export namespace Link {

link.nextPropagateOrReleased = pool;
pool = link;

if (dep.subs === undefined && 'deps' in dep) {
Subscriber.clearTrack(dep);
}
}
}

Expand All @@ -156,9 +161,7 @@ export namespace Dependency {
if (old === undefined || old.dep !== dep) {
const newLink = Link.get(dep, sub);
if (old !== undefined) {
const nextDep = old.nextDep;
Link.release(old);
newLink.nextDep = nextDep;
newLink.nextDep = old;
}
if (depsTail === undefined) {
sub.depsTail = sub.deps = newLink;
Expand Down
14 changes: 14 additions & 0 deletions tests/effect.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { describe, expect, test } from 'vitest';
import { computed, effect, signal, Subscriber } from '..';

test('should clear subscriptions when untracked by all subscribers', () => {
const src = signal(1);
const double = computed(() => src.get() * 2);
const effect1 = effect(() => {
double.get();
});

expect(!!double.subs).toBe(true);
Subscriber.clearTrack(effect1);
expect(!!double.subs).toBe(false);
});

0 comments on commit f2fa4a3

Please sign in to comment.