Skip to content

Commit c029c67

Browse files
skrthebossthePunderWoman
authored andcommitted
fix(core): ensure takeUntilDestroyed unregisters onDestroy listener on unsubscribe (#49901)
The takeUntilDestroyed must always remove the onDestroy listener, in the teardown logic. PR Close #49901
1 parent 856a0ec commit c029c67

File tree

2 files changed

+15
-1
lines changed

2 files changed

+15
-1
lines changed

packages/core/rxjs-interop/src/take_until_destroyed.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ export function takeUntilDestroyed<T>(destroyRef?: DestroyRef): MonoTypeOperator
2727
}
2828

2929
const destroyed$ = new Observable<void>(observer => {
30-
destroyRef!.onDestroy(observer.next.bind(observer));
30+
const unregisterFn = destroyRef!.onDestroy(observer.next.bind(observer));
31+
return unregisterFn;
3132
});
3233

3334
return <T>(source: Observable<T>) => {

packages/core/rxjs-interop/test/take_until_destroyed_spec.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,17 @@ describe('takeUntilDestroyed', () => {
6363
source$.next(2);
6464
expect(last).toBe(1);
6565
});
66+
67+
it('should unregister listener if observable is unsubscribed', () => {
68+
const injector = Injector.create({providers: []}) as EnvironmentInjector;
69+
const destroyRef = injector.get(DestroyRef);
70+
const unregisterFn = jasmine.createSpy();
71+
spyOn(destroyRef, 'onDestroy').and.returnValue(unregisterFn);
72+
73+
const subscription = new BehaviorSubject(0).pipe(takeUntilDestroyed(destroyRef)).subscribe();
74+
75+
subscription.unsubscribe();
76+
77+
expect(unregisterFn).toHaveBeenCalled();
78+
});
6679
});

0 commit comments

Comments
 (0)