Skip to content

Commit

Permalink
fix(signals): remove signalMethod instance watcher on destroy (#4648)
Browse files Browse the repository at this point in the history
Closes #4644
  • Loading branch information
rainerhahnekamp authored Jan 8, 2025
1 parent 3803550 commit 7f42065
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 7 deletions.
26 changes: 21 additions & 5 deletions modules/signals/spec/signal-method.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,15 @@ describe('signalMethod', () => {
const adder = createAdder((value) => (a += value));
adder(summand1);
adder(summand2);

summand1.set(2);
summand2.set(3);
TestBed.flushEffects();
expect(a).toBe(6);
expect(a).toBe(4);

adder.destroy();

summand1.set(2);
summand2.set(3);
TestBed.flushEffects();
expect(a).toBe(6);
expect(a).toBe(4);
});

it('does not cause issues if destroyed signalMethodFn contains destroyed effectRefs', () => {
Expand Down Expand Up @@ -198,4 +195,23 @@ describe('signalMethod', () => {
expect(a).toBe(5);
});
});

it('stops specific tracking when calling destroy manually on an instance', () => {
let a = 1;
const summand1 = signal(1);
const summand2 = signal(2);
const adder = createAdder((value) => (a += value));
adder(summand1);
const s2 = adder(summand2);

TestBed.flushEffects();
s2.destroy();
expect(a).toBe(4);

summand1.set(100);
summand2.set(3000);

TestBed.flushEffects();
expect(a).toBe(104);
});
});
11 changes: 9 additions & 2 deletions modules/signals/src/signal-method.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
assertInInjectionContext,
DestroyRef,
effect,
EffectRef,
inject,
Expand Down Expand Up @@ -35,15 +36,21 @@ export function signalMethod<Input>(
config?.injector ?? getCallerInjector() ?? sourceInjector;

const watcher = effect(
(onCleanup) => {
() => {
const value = input();
untracked(() => processingFn(value));
onCleanup(() => watchers.splice(watchers.indexOf(watcher), 1));
},
{ injector: instanceInjector }
);
watchers.push(watcher);

instanceInjector.get(DestroyRef).onDestroy(() => {
const ix = watchers.indexOf(watcher);
if (ix !== -1) {
watchers.splice(ix, 1);
}
});

return watcher;
} else {
processingFn(input);
Expand Down

0 comments on commit 7f42065

Please sign in to comment.