Skip to content

Commit f2fa4a3

Browse files
committed
perf(computed): clear subscriptions when untracked by all subscribers
1 parent 430a509 commit f2fa4a3

File tree

3 files changed

+21
-7
lines changed

3 files changed

+21
-7
lines changed

lib/computed.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { currentEffectScope } from './effectScope';
21
import { Dependency, DirtyLevels, Subscriber } from './system';
32

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

2120
constructor(
2221
public getter: (cachedValue?: T) => T
23-
) {
24-
currentEffectScope?.subs.push(this);
25-
}
22+
) { }
2623

2724
get(): T {
2825
Dependency.link(this);

lib/system.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ export namespace Link {
103103
}
104104

105105
export function release(link: Link) {
106+
const dep = link.dep as Dependency & ({} | Subscriber);
106107
const nextSub = link.nextSub;
107108
const prevSub = link.prevSubOrUpdate;
108109

@@ -130,6 +131,10 @@ export namespace Link {
130131

131132
link.nextPropagateOrReleased = pool;
132133
pool = link;
134+
135+
if (dep.subs === undefined && 'deps' in dep) {
136+
Subscriber.clearTrack(dep);
137+
}
133138
}
134139
}
135140

@@ -156,9 +161,7 @@ export namespace Dependency {
156161
if (old === undefined || old.dep !== dep) {
157162
const newLink = Link.get(dep, sub);
158163
if (old !== undefined) {
159-
const nextDep = old.nextDep;
160-
Link.release(old);
161-
newLink.nextDep = nextDep;
164+
newLink.nextDep = old;
162165
}
163166
if (depsTail === undefined) {
164167
sub.depsTail = sub.deps = newLink;

tests/effect.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { describe, expect, test } from 'vitest';
2+
import { computed, effect, signal, Subscriber } from '..';
3+
4+
test('should clear subscriptions when untracked by all subscribers', () => {
5+
const src = signal(1);
6+
const double = computed(() => src.get() * 2);
7+
const effect1 = effect(() => {
8+
double.get();
9+
});
10+
11+
expect(!!double.subs).toBe(true);
12+
Subscriber.clearTrack(effect1);
13+
expect(!!double.subs).toBe(false);
14+
});

0 commit comments

Comments
 (0)