From f35c808c8483397760f15ca07413cd1b0be3f135 Mon Sep 17 00:00:00 2001 From: charliesantos Date: Fri, 31 Mar 2023 10:27:04 -0700 Subject: [PATCH 1/2] Remove unnecessary bind --- lib/twilio/call.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/twilio/call.ts b/lib/twilio/call.ts index ad304885..13d9cbbf 100644 --- a/lib/twilio/call.ts +++ b/lib/twilio/call.ts @@ -636,13 +636,13 @@ class Call extends EventEmitter { if (this._direction === Call.CallDirection.Incoming) { this._isAnswered = true; - this._pstream.on('answer', this._onAnswer.bind(this)); + this._pstream.on('answer', this._onAnswer); this._mediaHandler.answerIncomingCall(this.parameters.CallSid, this._options.offerSdp, rtcConstraints, rtcConfiguration, onAnswer); } else { const params = Array.from(this.customParameters.entries()).map(pair => `${encodeURIComponent(pair[0])}=${encodeURIComponent(pair[1])}`).join('&'); - this._pstream.on('answer', this._onAnswer.bind(this)); + this._pstream.on('answer', this._onAnswer); this._mediaHandler.makeOutgoingCall(this._pstream.token, params, this.outboundConnectionId, rtcConstraints, rtcConfiguration, onAnswer); } From d8d7ca28c63bf0c968af3be6497035ce11fdd4da Mon Sep 17 00:00:00 2001 From: charliesantos Date: Fri, 31 Mar 2023 12:55:06 -0700 Subject: [PATCH 2/2] Tests and changelog --- CHANGELOG.md | 2 ++ tests/unit/call.ts | 71 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 51 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 629d70cf..12daea25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ Bug Fixes - Fixed an [issue](https://github.com/twilio/twilio-voice.js/issues/100) where a `TypeError` is thrown after rejecting a call then invoking `updateToken`. +- Fixed an issue (https://github.com/twilio/twilio-voice.js/issues/87, https://github.com/twilio/twilio-voice.js/issues/145) where the `PeerConnection` object is not properly disposed. + 2.3.2 (February 27, 2023) =================== diff --git a/tests/unit/call.ts b/tests/unit/call.ts index 63018f92..823a7811 100644 --- a/tests/unit/call.ts +++ b/tests/unit/call.ts @@ -1706,45 +1706,72 @@ describe('Call', function() { describe('pstream.answer event', () => { let pStreamAnswerPayload: any; - beforeEach(async () => { + beforeEach(() => { pStreamAnswerPayload = { edge: 'foobar-edge', reconnect: 'foobar-reconnect-token', }; - conn = new Call(config, options); - conn.accept(); - await clock.tickAsync(0); }); - it('should set the call to "answered"', () => { - pstream.emit('answer', pStreamAnswerPayload); - assert(conn['_isAnswered']); - }); + describe('for incoming calls', () => { + beforeEach(async () => { + // With a CallSid, this becomes an incoming call + const callParameters = { CallSid: 'CA1234' }; + conn = new Call(config, Object.assign(options, { callParameters })); + conn.accept(); + await clock.tickAsync(0); + }); - it('should save the reconnect token', () => { - pstream.emit('answer', pStreamAnswerPayload); - assert.equal(conn['_signalingReconnectToken'], pStreamAnswerPayload.reconnect); + it('should remove event handler after disconnect for an incoming call', () => { + pstream.emit('answer', pStreamAnswerPayload); + conn.disconnect(); + assert.strictEqual(pstream.listenerCount('answer'), 0); + }); }); - describe('if raised multiple times', () => { - it('should save the reconnect token multiple times', () => { - pstream.emit('answer', pStreamAnswerPayload); - assert.equal(conn['_signalingReconnectToken'], pStreamAnswerPayload.reconnect); + describe('for outgoing calls', () => { + beforeEach(async () => { + conn = new Call(config, options); + conn.accept(); + await clock.tickAsync(0); + }); - pStreamAnswerPayload.reconnect = 'biffbazz-reconnect-token'; + it('should set the call to "answered"', () => { + pstream.emit('answer', pStreamAnswerPayload); + assert(conn['_isAnswered']); + }); + it('should save the reconnect token', () => { pstream.emit('answer', pStreamAnswerPayload); assert.equal(conn['_signalingReconnectToken'], pStreamAnswerPayload.reconnect); }); - it('should not invoke "call._maybeTransitionToOpen" more than once', () => { - const spy = conn['_maybeTransitionToOpen'] = sinon.spy(conn['_maybeTransitionToOpen']); - + it('should remove event handler after disconnect for an outgoing call', () => { pstream.emit('answer', pStreamAnswerPayload); - sinon.assert.calledOnce(spy); + conn.disconnect(); + assert.strictEqual(pstream.listenerCount('answer'), 0); + }); - pstream.emit('answer', pStreamAnswerPayload); - sinon.assert.calledOnce(spy); + describe('if raised multiple times', () => { + it('should save the reconnect token multiple times', () => { + pstream.emit('answer', pStreamAnswerPayload); + assert.equal(conn['_signalingReconnectToken'], pStreamAnswerPayload.reconnect); + + pStreamAnswerPayload.reconnect = 'biffbazz-reconnect-token'; + + pstream.emit('answer', pStreamAnswerPayload); + assert.equal(conn['_signalingReconnectToken'], pStreamAnswerPayload.reconnect); + }); + + it('should not invoke "call._maybeTransitionToOpen" more than once', () => { + const spy = conn['_maybeTransitionToOpen'] = sinon.spy(conn['_maybeTransitionToOpen']); + + pstream.emit('answer', pStreamAnswerPayload); + sinon.assert.calledOnce(spy); + + pstream.emit('answer', pStreamAnswerPayload); + sinon.assert.calledOnce(spy); + }); }); }); });