From 9d1ba1479b098c2761a25c7ae7d83b497e98dc53 Mon Sep 17 00:00:00 2001 From: Michal Skvely Date: Thu, 3 May 2018 18:26:39 +0200 Subject: [PATCH] fix(delay): fix memory leak (#3605) * test(delay): failing test * fix(delay): fix memory leak --- spec/operators/delay-spec.ts | 34 +++++++++++++++++++++++++++++++++- src/operators/delay.ts | 1 + 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/spec/operators/delay-spec.ts b/spec/operators/delay-spec.ts index 499a24d846..2889f553d8 100644 --- a/spec/operators/delay-spec.ts +++ b/spec/operators/delay-spec.ts @@ -1,4 +1,7 @@ +import { expect } from 'chai'; +import * as sinon from 'sinon'; import * as Rx from '../../dist/package/Rx'; +import { delay, repeatWhen, skip, take, tap } from '../../dist/package/operators'; import marbleTestingSignature = require('../helpers/marble-testing'); // tslint:disable-line:no-require-imports declare const { asDiagram, time }; @@ -147,4 +150,33 @@ describe('Observable.prototype.delay', () => { expectObservable(result).toBe(expected); }); -}); \ No newline at end of file + + it('should unsubscribe scheduled actions after execution', () => { + let subscribeSpy: any = null; + const counts: number[] = []; + + const e1 = cold('a|'); + const expected = '--a-(a|)'; + const duration = time('-|'); + const result = e1.pipe( + repeatWhen(notifications => { + const delayed = notifications.pipe(delay(duration, rxTestScheduler)); + subscribeSpy = sinon.spy(delayed['source'], 'subscribe'); + return delayed; + }), + skip(1), + take(2), + tap({ + next() { + const [[subscriber]] = subscribeSpy.args; + counts.push(subscriber._subscriptions.length); + }, + complete() { + expect(counts).to.deep.equal([1, 1]); + } + }) + ); + + expectObservable(result).toBe(expected); + }); +}); diff --git a/src/operators/delay.ts b/src/operators/delay.ts index 25d21eef12..86c5cf5c56 100644 --- a/src/operators/delay.ts +++ b/src/operators/delay.ts @@ -96,6 +96,7 @@ class DelaySubscriber extends Subscriber { const delay = Math.max(0, queue[0].time - scheduler.now()); this.schedule(state, delay); } else { + this.unsubscribe(); source.active = false; } }