From a047e7aa1d4630225d19bf99d4419197032fddd0 Mon Sep 17 00:00:00 2001 From: Ben Lesh Date: Sat, 5 Nov 2016 14:22:58 -0700 Subject: [PATCH] fix(first): will now only emit one value in recursive cases (#2100) adds guard after first emitted value to prevent reentrant behavior fixes #2098 --- spec/operators/first-spec.ts | 14 ++++++++++++++ src/operator/first.ts | 10 +++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/spec/operators/first-spec.ts b/spec/operators/first-spec.ts index b00dc591e3..6abad29eee 100644 --- a/spec/operators/first-spec.ts +++ b/spec/operators/first-spec.ts @@ -42,6 +42,20 @@ describe('Observable.prototype.first', () => { expectSubscriptions(e1.subscriptions).toBe(sub); }); + it('should only emit one value in recursive cases', () => { + const subject = new Rx.Subject(); + const results = []; + + subject.first().subscribe(x => { + results.push(x); + subject.next(x + 1); + }); + + subject.next(0); + + expect(results).to.deep.equal([0]); + }); + it('should propagate error from the source observable', () => { const e1 = hot('---^---#'); const expected = '----#'; diff --git a/src/operator/first.ts b/src/operator/first.ts index 73fdf00583..80d442820c 100644 --- a/src/operator/first.ts +++ b/src/operator/first.ts @@ -85,6 +85,7 @@ class FirstOperator implements Operator { class FirstSubscriber extends Subscriber { private index: number = 0; private hasCompleted: boolean = false; + private _emitted: boolean = false; constructor(destination: Subscriber, private predicate?: (value: T, index: number, source: Observable) => boolean, @@ -137,9 +138,12 @@ class FirstSubscriber extends Subscriber { private _emitFinal(value: any) { const destination = this.destination; - destination.next(value); - destination.complete(); - this.hasCompleted = true; + if (!this._emitted) { + this._emitted = true; + destination.next(value); + destination.complete(); + this.hasCompleted = true; + } } protected _complete(): void {