Skip to content

Commit 29b630b

Browse files
kwonojbenlesh
authored andcommitted
fix(Subject): throw ObjectUnsubscribedError when unsubecribed
closes #859
1 parent 51add30 commit 29b630b

File tree

4 files changed

+72
-14
lines changed

4 files changed

+72
-14
lines changed

spec/Subject-spec.js

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,6 @@ describe('Subject', function () {
129129
subscription1.unsubscribe();
130130

131131
subject.complete();
132-
subject.next(9);
133-
subject.complete();
134-
subject.error(new Error('err'));
135132

136133
subscription2.unsubscribe();
137134

@@ -179,9 +176,6 @@ describe('Subject', function () {
179176

180177
subscription1.unsubscribe();
181178

182-
subject.error(new Error('err'));
183-
subject.next(9);
184-
subject.complete();
185179
subject.error(new Error('err'));
186180

187181
subscription2.unsubscribe();
@@ -221,9 +215,6 @@ describe('Subject', function () {
221215
subscription1.unsubscribe();
222216

223217
subject.complete();
224-
subject.next(9);
225-
subject.complete();
226-
subject.error(new Error('err'));
227218

228219
subscription2.unsubscribe();
229220

@@ -509,6 +500,57 @@ describe('Subject', function () {
509500
source.subscribe(subject);
510501
});
511502

503+
it('should throw ObjectUnsubscribedError when emit after unsubscribed', function () {
504+
var subject = new Rx.Subject();
505+
subject.unsubscribe();
506+
507+
expect(function () {
508+
subject.next('a');
509+
}).toThrow(new Rx.ObjectUnsubscribedError());
510+
511+
expect(function () {
512+
subject.error('a');
513+
}).toThrow(new Rx.ObjectUnsubscribedError());
514+
515+
expect(function () {
516+
subject.complete();
517+
}).toThrow(new Rx.ObjectUnsubscribedError());
518+
});
519+
520+
it('should throw ObjectUnsubscribedError when emit after completed', function () {
521+
var subject = new Rx.Subject();
522+
subject.complete();
523+
524+
expect(function () {
525+
subject.next('a');
526+
}).toThrow(new Rx.ObjectUnsubscribedError());
527+
528+
expect(function () {
529+
subject.error('a');
530+
}).toThrow(new Rx.ObjectUnsubscribedError());
531+
532+
expect(function () {
533+
subject.complete();
534+
}).toThrow(new Rx.ObjectUnsubscribedError());
535+
});
536+
537+
it('should throw ObjectUnsubscribedError when emit after error', function () {
538+
var subject = new Rx.Subject();
539+
subject.error('e');
540+
541+
expect(function () {
542+
subject.next('a');
543+
}).toThrow(new Rx.ObjectUnsubscribedError());
544+
545+
expect(function () {
546+
subject.error('a');
547+
}).toThrow(new Rx.ObjectUnsubscribedError());
548+
549+
expect(function () {
550+
subject.complete();
551+
}).toThrow(new Rx.ObjectUnsubscribedError());
552+
});
553+
512554
describe('asObservable', function () {
513555
it('should hide subject', function () {
514556
var subject = new Rx.Subject();

spec/subjects/AsyncSubject-spec.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,6 @@ describe('AsyncSubject', function () {
7070
expect(observer.results).toEqual([]);
7171
subject.complete();
7272
expect(observer.results).toEqual([2, 'done']);
73-
subject.next(3);
74-
expect(observer.results).toEqual([2, 'done']);
7573
});
7674

7775
it('should not emit values if unsubscribed before complete', function () {

spec/subjects/BehaviorSubject-spec.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,10 @@ describe('BehaviorSubject', function () {
9696

9797
subject.next('foo');
9898
subject.complete();
99-
subject.next('bar');
99+
100+
expect(function () {
101+
subject.next('bar');
102+
}).toThrow(new Rx.ObjectUnsubscribedError());
100103
});
101104

102105
it('should clean out unsubscribed subscribers', function (done) {

src/Subject.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import {Subscription} from './Subscription';
66
import {SubjectSubscription} from './subject/SubjectSubscription';
77
import {rxSubscriber} from './symbol/rxSubscriber';
88

9+
import {throwError} from './util/throwError';
10+
import {ObjectUnsubscribedError} from './util/ObjectUnsubscribedError';
11+
912
export class Subject<T> extends Observable<T> implements Observer<T>, Subscription {
1013

1114
static create: Function = <T>(destination: Observer<T>, source: Observable<T>): Subject<T> => {
@@ -53,10 +56,10 @@ export class Subject<T> extends Observable<T> implements Observer<T>, Subscripti
5356
return subscriber.error(this.errorValue);
5457
} else if (this.hasCompleted) {
5558
return subscriber.complete();
56-
} else if (this.isUnsubscribed) {
57-
throw new Error('Cannot subscribe to a disposed Subject.');
5859
}
5960

61+
this.throwIfUnsubscribed();
62+
6063
const subscription = new SubjectSubscription(this, subscriber);
6164

6265
this.observers.push(subscriber);
@@ -73,6 +76,8 @@ export class Subject<T> extends Observable<T> implements Observer<T>, Subscripti
7376
}
7477

7578
next(value: T): void {
79+
this.throwIfUnsubscribed();
80+
7681
if (this.isStopped) {
7782
return;
7883
}
@@ -89,6 +94,8 @@ export class Subject<T> extends Observable<T> implements Observer<T>, Subscripti
8994
}
9095

9196
error(err?: any): void {
97+
this.throwIfUnsubscribed();
98+
9299
if (this.isStopped) {
93100
return;
94101
}
@@ -105,6 +112,8 @@ export class Subject<T> extends Observable<T> implements Observer<T>, Subscripti
105112
}
106113

107114
complete(): void {
115+
this.throwIfUnsubscribed();
116+
108117
if (this.isStopped) {
109118
return;
110119
}
@@ -200,6 +209,12 @@ export class Subject<T> extends Observable<T> implements Observer<T>, Subscripti
200209
this.unsubscribe();
201210
}
202211

212+
private throwIfUnsubscribed(): void {
213+
if (this.isUnsubscribed) {
214+
throwError(new ObjectUnsubscribedError());
215+
}
216+
}
217+
203218
[rxSubscriber]() {
204219
return new Subscriber<T>(this);
205220
}

0 commit comments

Comments
 (0)