diff --git a/src/js/chrome/chrome_shim.js b/src/js/chrome/chrome_shim.js index 2eecce0e..a6c39503 100644 --- a/src/js/chrome/chrome_shim.js +++ b/src/js/chrome/chrome_shim.js @@ -34,7 +34,7 @@ export function shimOnTrack(window) { const origSetRemoteDescription = window.RTCPeerConnection.prototype.setRemoteDescription; window.RTCPeerConnection.prototype.setRemoteDescription = - function setRemoteDescription() { + function setRemoteDescription(description, ...args) { if (!this._ontrackpoly) { this._ontrackpoly = (e) => { // onaddstream does not fire when a track is added to an existing @@ -73,7 +73,7 @@ export function shimOnTrack(window) { }; this.addEventListener('addstream', this._ontrackpoly); } - return origSetRemoteDescription.apply(this, arguments); + return origSetRemoteDescription.apply(this, [description, ...args]); }; } else { // even if RTCRtpTransceiver is in window, it is only used and @@ -119,8 +119,8 @@ export function shimGetSendersWithDtmf(window) { }; const origAddTrack = window.RTCPeerConnection.prototype.addTrack; window.RTCPeerConnection.prototype.addTrack = - function addTrack(track, stream) { - let sender = origAddTrack.apply(this, arguments); + function addTrack(track, ...args) { + let sender = origAddTrack.apply(this, [track, ...args]); if (!sender) { sender = shimSenderWithDtmf(this, track); this._senders.push(sender); @@ -130,8 +130,8 @@ export function shimGetSendersWithDtmf(window) { const origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack; window.RTCPeerConnection.prototype.removeTrack = - function removeTrack(sender) { - origRemoveTrack.apply(this, arguments); + function removeTrack(sender, ...args) { + origRemoveTrack.apply(this, [sender, ...args]); const idx = this._senders.indexOf(sender); if (idx !== -1) { this._senders.splice(idx, 1); @@ -206,11 +206,12 @@ export function shimSenderReceiverGetStats(window) { const origAddTrack = window.RTCPeerConnection.prototype.addTrack; if (origAddTrack) { - window.RTCPeerConnection.prototype.addTrack = function addTrack() { - const sender = origAddTrack.apply(this, arguments); - sender._pc = this; - return sender; - }; + window.RTCPeerConnection.prototype.addTrack = + function addTrack(track, ...args) { + const sender = origAddTrack.apply(this, [track, ...args]); + sender._pc = this; + return sender; + }; } window.RTCRtpSender.prototype.getStats = function getStats() { const sender = this; @@ -252,10 +253,10 @@ export function shimSenderReceiverGetStats(window) { // shim RTCPeerConnection.getStats(track). const origGetStats = window.RTCPeerConnection.prototype.getStats; - window.RTCPeerConnection.prototype.getStats = function getStats() { - if (arguments.length > 0 && - arguments[0] instanceof window.MediaStreamTrack) { - const track = arguments[0]; + window.RTCPeerConnection.prototype.getStats = function getStats(...args) { + if (args.length > 0 && + args[0] instanceof window.MediaStreamTrack) { + const track = args[0]; let sender; let receiver; let err; @@ -291,7 +292,7 @@ export function shimSenderReceiverGetStats(window) { 'There is no sender or receiver for the track.', 'InvalidAccessError')); } - return origGetStats.apply(this, arguments); + return origGetStats.apply(this, args); }; } @@ -308,13 +309,14 @@ export function shimAddTrackRemoveTrackWithNative(window) { const origAddTrack = window.RTCPeerConnection.prototype.addTrack; window.RTCPeerConnection.prototype.addTrack = - function addTrack(track, stream) { + function addTrack(track, ...args) { + const stream = args[0]; if (!stream) { - return origAddTrack.apply(this, arguments); + return origAddTrack.apply(this, [track, ...args]); } this._shimmedLocalStreams = this._shimmedLocalStreams || {}; - const sender = origAddTrack.apply(this, arguments); + const sender = origAddTrack.apply(this, [track, ...args]); if (!this._shimmedLocalStreams[stream.id]) { this._shimmedLocalStreams[stream.id] = [stream, sender]; } else if (this._shimmedLocalStreams[stream.id].indexOf(sender) === -1) { @@ -324,34 +326,35 @@ export function shimAddTrackRemoveTrackWithNative(window) { }; const origAddStream = window.RTCPeerConnection.prototype.addStream; - window.RTCPeerConnection.prototype.addStream = function addStream(stream) { - this._shimmedLocalStreams = this._shimmedLocalStreams || {}; + window.RTCPeerConnection.prototype.addStream = + function addStream(stream, ...args) { + this._shimmedLocalStreams = this._shimmedLocalStreams || {}; - stream.getTracks().forEach(track => { - const alreadyExists = this.getSenders().find(s => s.track === track); - if (alreadyExists) { - throw new DOMException('Track already exists.', - 'InvalidAccessError'); - } - }); - const existingSenders = this.getSenders(); - origAddStream.apply(this, arguments); - const newSenders = this.getSenders() - .filter(newSender => existingSenders.indexOf(newSender) === -1); - this._shimmedLocalStreams[stream.id] = [stream].concat(newSenders); - }; + stream.getTracks().forEach(track => { + const alreadyExists = this.getSenders().find(s => s.track === track); + if (alreadyExists) { + throw new DOMException('Track already exists.', + 'InvalidAccessError'); + } + }); + const existingSenders = this.getSenders(); + origAddStream.apply(this, [stream, ...args]); + const newSenders = this.getSenders() + .filter(newSender => existingSenders.indexOf(newSender) === -1); + this._shimmedLocalStreams[stream.id] = [stream].concat(newSenders); + }; const origRemoveStream = window.RTCPeerConnection.prototype.removeStream; window.RTCPeerConnection.prototype.removeStream = - function removeStream(stream) { + function removeStream(stream, ...args) { this._shimmedLocalStreams = this._shimmedLocalStreams || {}; delete this._shimmedLocalStreams[stream.id]; - return origRemoveStream.apply(this, arguments); + return origRemoveStream.apply(this, [stream, ...args]); }; const origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack; window.RTCPeerConnection.prototype.removeTrack = - function removeTrack(sender) { + function removeTrack(sender, ...args) { this._shimmedLocalStreams = this._shimmedLocalStreams || {}; if (sender) { Object.keys(this._shimmedLocalStreams).forEach(streamId => { @@ -364,7 +367,7 @@ export function shimAddTrackRemoveTrackWithNative(window) { } }); } - return origRemoveTrack.apply(this, arguments); + return origRemoveTrack.apply(this, [sender, ...args]); }; } @@ -390,48 +393,49 @@ export function shimAddTrackRemoveTrack(window, browserDetails) { }; const origAddStream = window.RTCPeerConnection.prototype.addStream; - window.RTCPeerConnection.prototype.addStream = function addStream(stream) { - this._streams = this._streams || {}; - this._reverseStreams = this._reverseStreams || {}; + window.RTCPeerConnection.prototype.addStream = + function addStream(stream, ...args) { + this._streams = this._streams || {}; + this._reverseStreams = this._reverseStreams || {}; - stream.getTracks().forEach(track => { - const alreadyExists = this.getSenders().find(s => s.track === track); - if (alreadyExists) { - throw new DOMException('Track already exists.', - 'InvalidAccessError'); - } - }); - // Add identity mapping for consistency with addTrack. - // Unless this is being used with a stream from addTrack. - if (!this._reverseStreams[stream.id]) { - const newStream = new window.MediaStream(stream.getTracks()); - this._streams[stream.id] = newStream; - this._reverseStreams[newStream.id] = stream; - stream = newStream; - } - origAddStream.apply(this, [stream]); - }; + stream.getTracks().forEach(track => { + const alreadyExists = this.getSenders().find(s => s.track === track); + if (alreadyExists) { + throw new DOMException('Track already exists.', + 'InvalidAccessError'); + } + }); + // Add identity mapping for consistency with addTrack. + // Unless this is being used with a stream from addTrack. + if (!this._reverseStreams[stream.id]) { + const newStream = new window.MediaStream(stream.getTracks()); + this._streams[stream.id] = newStream; + this._reverseStreams[newStream.id] = stream; + stream = newStream; + } + origAddStream.apply(this, [stream, ...args]); + }; const origRemoveStream = window.RTCPeerConnection.prototype.removeStream; window.RTCPeerConnection.prototype.removeStream = - function removeStream(stream) { + function removeStream(stream, ...args) { this._streams = this._streams || {}; this._reverseStreams = this._reverseStreams || {}; - origRemoveStream.apply(this, [(this._streams[stream.id] || stream)]); + origRemoveStream.apply(this, [(this._streams[stream.id] || stream), + ...args]); delete this._reverseStreams[(this._streams[stream.id] ? this._streams[stream.id].id : stream.id)]; delete this._streams[stream.id]; }; window.RTCPeerConnection.prototype.addTrack = - function addTrack(track, stream) { + function addTrack(track, ...streams) { if (this.signalingState === 'closed') { throw new DOMException( 'The RTCPeerConnection\'s signalingState is \'closed\'.', 'InvalidStateError'); } - const streams = [].slice.call(arguments, 1); if (streams.length !== 1 || !streams[0].getTracks().find(t => t === track)) { // this is not fully correct but all we can manage without @@ -450,6 +454,7 @@ export function shimAddTrackRemoveTrack(window, browserDetails) { this._streams = this._streams || {}; this._reverseStreams = this._reverseStreams || {}; + const stream = streams[0]; const oldStream = this._streams[stream.id]; if (oldStream) { // this is using odd Chrome behaviour, use with caution: @@ -501,10 +506,9 @@ export function shimAddTrackRemoveTrack(window, browserDetails) { } ['createOffer', 'createAnswer'].forEach(function(method) { const nativeMethod = window.RTCPeerConnection.prototype[method]; - const methodObj = {[method]() { - const args = arguments; - const isLegacyCall = arguments.length && - typeof arguments[0] === 'function'; + const methodObj = {[method](...args) { + const isLegacyCall = args.length && + typeof args[0] === 'function'; if (isLegacyCall) { return nativeMethod.apply(this, [ (description) => { @@ -515,10 +519,10 @@ export function shimAddTrackRemoveTrack(window, browserDetails) { if (args[1]) { args[1].apply(null, err); } - }, arguments[2] + }, args[2] ]); } - return nativeMethod.apply(this, arguments) + return nativeMethod.apply(this, args) .then(description => replaceInternalStreamId(this, description)); }}; window.RTCPeerConnection.prototype[method] = methodObj[method]; @@ -527,12 +531,14 @@ export function shimAddTrackRemoveTrack(window, browserDetails) { const origSetLocalDescription = window.RTCPeerConnection.prototype.setLocalDescription; window.RTCPeerConnection.prototype.setLocalDescription = - function setLocalDescription() { - if (!arguments.length || !arguments[0].type) { - return origSetLocalDescription.apply(this, arguments); + function setLocalDescription(...args) { + let description = args[0]; + if (!args.length || !description.type) { + return origSetLocalDescription.apply(this, args); } - arguments[0] = replaceExternalStreamId(this, arguments[0]); - return origSetLocalDescription.apply(this, arguments); + description = replaceExternalStreamId(this, description); + return origSetLocalDescription.apply(this, [description, + ...args.slice(1)]); }; // TODO: mangle getStats: https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamstats-streamidentifier @@ -608,11 +614,12 @@ export function shimPeerConnection(window, browserDetails) { ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'] .forEach(function(method) { const nativeMethod = window.RTCPeerConnection.prototype[method]; - const methodObj = {[method]() { - arguments[0] = new ((method === 'addIceCandidate') ? + const methodObj = {[method](...args) { + let description = args[0]; + description = new ((method === 'addIceCandidate') ? window.RTCIceCandidate : - window.RTCSessionDescription)(arguments[0]); - return nativeMethod.apply(this, arguments); + window.RTCSessionDescription)(description); + return nativeMethod.apply(this, [description, ...args.slice(1)]); }}; window.RTCPeerConnection.prototype[method] = methodObj[method]; }); diff --git a/src/js/common_shim.js b/src/js/common_shim.js index bff69706..db70e724 100644 --- a/src/js/common_shim.js +++ b/src/js/common_shim.js @@ -191,7 +191,7 @@ export function shimMaxMessageSize(window, browserDetails) { const origSetRemoteDescription = window.RTCPeerConnection.prototype.setRemoteDescription; window.RTCPeerConnection.prototype.setRemoteDescription = - function setRemoteDescription() { + function setRemoteDescription(description, ...args) { this._sctp = null; // Chrome decided to not expose .sctp in plan-b mode. // As usual, adapter.js has to do an 'ugly worakaround' @@ -209,15 +209,15 @@ export function shimMaxMessageSize(window, browserDetails) { } } - if (sctpInDescription(arguments[0])) { + if (sctpInDescription(description)) { // Check if the remote is FF. - const isFirefox = getRemoteFirefoxVersion(arguments[0]); + const isFirefox = getRemoteFirefoxVersion(description); // Get the maximum message size the local peer is capable of sending const canSendMMS = getCanSendMaxMessageSize(isFirefox); // Get the maximum message size of the remote peer. - const remoteMMS = getMaxMessageSize(arguments[0], isFirefox); + const remoteMMS = getMaxMessageSize(description, isFirefox); // Determine final maximum message size let maxMessageSize; @@ -240,7 +240,7 @@ export function shimMaxMessageSize(window, browserDetails) { this._sctp = sctp; } - return origSetRemoteDescription.apply(this, arguments); + return origSetRemoteDescription.apply(this, [description, ...args]); }; } @@ -256,22 +256,21 @@ export function shimSendThrowTypeError(window) { function wrapDcSend(dc, pc) { const origDataChannelSend = dc.send; - dc.send = function send() { - const data = arguments[0]; + dc.send = function send(data, ...args) { const length = data.length || data.size || data.byteLength; if (dc.readyState === 'open' && pc.sctp && length > pc.sctp.maxMessageSize) { throw new TypeError('Message too large (can send a maximum of ' + pc.sctp.maxMessageSize + ' bytes)'); } - return origDataChannelSend.apply(dc, arguments); + return origDataChannelSend.apply(dc, [data, ...args]); }; } const origCreateDataChannel = window.RTCPeerConnection.prototype.createDataChannel; window.RTCPeerConnection.prototype.createDataChannel = - function createDataChannel() { - const dataChannel = origCreateDataChannel.apply(this, arguments); + function createDataChannel(label, ...args) { + const dataChannel = origCreateDataChannel.apply(this, [label, ...args]); wrapDcSend(dataChannel, this); return dataChannel; }; @@ -326,7 +325,7 @@ export function shimConnectionState(window) { ['setLocalDescription', 'setRemoteDescription'].forEach((method) => { const origMethod = proto[method]; - proto[method] = function() { + proto[method] = function(...args) { if (!this._connectionstatechangepoly) { this._connectionstatechangepoly = e => { const pc = e.target; @@ -340,7 +339,7 @@ export function shimConnectionState(window) { this.addEventListener('iceconnectionstatechange', this._connectionstatechangepoly); } - return origMethod.apply(this, arguments); + return origMethod.apply(this, args); }; }); } @@ -359,23 +358,24 @@ export function removeExtmapAllowMixed(window, browserDetails) { } const nativeSRD = window.RTCPeerConnection.prototype.setRemoteDescription; window.RTCPeerConnection.prototype.setRemoteDescription = - function setRemoteDescription(desc) { - if (desc && desc.sdp && desc.sdp.indexOf('\na=extmap-allow-mixed') !== -1) { - const sdp = desc.sdp.split('\n').filter((line) => { + function setRemoteDescription(description, ...args) { + if (description && description.sdp && + description.sdp.indexOf('\na=extmap-allow-mixed') !== -1) { + const sdp = description.sdp.split('\n').filter((line) => { return line.trim() !== 'a=extmap-allow-mixed'; }).join('\n'); // Safari enforces read-only-ness of RTCSessionDescription fields. if (window.RTCSessionDescription && - desc instanceof window.RTCSessionDescription) { - arguments[0] = new window.RTCSessionDescription({ - type: desc.type, + description instanceof window.RTCSessionDescription) { + description = new window.RTCSessionDescription({ + type: description.type, sdp, }); } else { - desc.sdp = sdp; + description.sdp = sdp; } } - return nativeSRD.apply(this, arguments); + return nativeSRD.apply(this, [description, ...args]); }; } @@ -393,10 +393,11 @@ export function shimAddIceCandidateNullOrEmpty(window, browserDetails) { return; } window.RTCPeerConnection.prototype.addIceCandidate = - function addIceCandidate() { - if (!arguments[0]) { - if (arguments[1]) { - arguments[1].apply(null); + function addIceCandidate(...args) { + const candidate = args[0]; + if (!candidate) { + if (args[1]) { + args[1].apply(null); } return Promise.resolve(); } @@ -409,10 +410,10 @@ export function shimAddIceCandidateNullOrEmpty(window, browserDetails) { || (browserDetails.browser === 'firefox' && browserDetails.version < 68) || (browserDetails.browser === 'safari')) - && arguments[0] && arguments[0].candidate === '') { + && candidate && candidate.candidate === '') { return Promise.resolve(); } - return nativeAddIceCandidate.apply(this, arguments); + return nativeAddIceCandidate.apply(this, args); }; } @@ -428,10 +429,10 @@ export function shimParameterlessSetLocalDescription(window, browserDetails) { return; } window.RTCPeerConnection.prototype.setLocalDescription = - function setLocalDescription() { - let desc = arguments[0] || {}; + function setLocalDescription(...args) { + let desc = args[0] || {}; if (typeof desc !== 'object' || (desc.type && desc.sdp)) { - return nativeSetLocalDescription.apply(this, arguments); + return nativeSetLocalDescription.apply(this, args); } // The remaining steps should technically happen when SLD comes off the // RTCPeerConnection's operations chain (not ahead of going on it), but diff --git a/src/js/firefox/firefox_shim.js b/src/js/firefox/firefox_shim.js index 4b9852b8..6598a352 100644 --- a/src/js/firefox/firefox_shim.js +++ b/src/js/firefox/firefox_shim.js @@ -39,11 +39,12 @@ export function shimPeerConnection(window, browserDetails) { ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'] .forEach(function(method) { const nativeMethod = window.RTCPeerConnection.prototype[method]; - const methodObj = {[method]() { - arguments[0] = new ((method === 'addIceCandidate') ? + const methodObj = {[method](...args) { + let description = args[0]; + description = new ((method === 'addIceCandidate') ? window.RTCIceCandidate : - window.RTCSessionDescription)(arguments[0]); - return nativeMethod.apply(this, arguments); + window.RTCSessionDescription)(description); + return nativeMethod.apply(this, [description, ...args.slice(1)]); }}; window.RTCPeerConnection.prototype[method] = methodObj[method]; }); @@ -58,8 +59,8 @@ export function shimPeerConnection(window, browserDetails) { }; const nativeGetStats = window.RTCPeerConnection.prototype.getStats; - window.RTCPeerConnection.prototype.getStats = function getStats() { - const [selector, onSucc, onErr] = arguments; + window.RTCPeerConnection.prototype.getStats = function getStats(...args) { + const [selector, onSucc, onErr] = args; return nativeGetStats.apply(this, [selector || null]) .then(stats => { if (browserDetails.version < 53 && !onSucc) { @@ -106,11 +107,12 @@ export function shimSenderGetStats(window) { const origAddTrack = window.RTCPeerConnection.prototype.addTrack; if (origAddTrack) { - window.RTCPeerConnection.prototype.addTrack = function addTrack() { - const sender = origAddTrack.apply(this, arguments); - sender._pc = this; - return sender; - }; + window.RTCPeerConnection.prototype.addTrack = + function addTrack(track, ...args) { + const sender = origAddTrack.apply(this, [track, ...args]); + sender._pc = this; + return sender; + }; } window.RTCRtpSender.prototype.getStats = function getStats() { return this.track ? this._pc.getStats(this.track) : @@ -177,10 +179,10 @@ export function shimAddTransceiver(window) { const origAddTransceiver = window.RTCPeerConnection.prototype.addTransceiver; if (origAddTransceiver) { window.RTCPeerConnection.prototype.addTransceiver = - function addTransceiver() { + function addTransceiver(trackOrKind, ...args) { this.setParametersPromises = []; // WebIDL input coercion and validation - let sendEncodings = arguments[1] && arguments[1].sendEncodings; + let sendEncodings = args[0] && args[0].sendEncodings; if (sendEncodings === undefined) { sendEncodings = []; } @@ -207,7 +209,8 @@ export function shimAddTransceiver(window) { } }); } - const transceiver = origAddTransceiver.apply(this, arguments); + const transceiver = origAddTransceiver.apply(this, + [trackOrKind, ...args]); if (shouldPerformCheck) { // Check if the init options were applied. If not we do this in an // asynchronous way and save the promise reference in a global object. @@ -245,8 +248,8 @@ export function shimGetParameters(window) { const origGetParameters = window.RTCRtpSender.prototype.getParameters; if (origGetParameters) { window.RTCRtpSender.prototype.getParameters = - function getParameters() { - const params = origGetParameters.apply(this, arguments); + function getParameters(...args) { + const params = origGetParameters.apply(this, args); if (!('encodings' in params)) { params.encodings = [].concat(this.sendEncodings || [{}]); } @@ -263,18 +266,19 @@ export function shimCreateOffer(window) { return; } const origCreateOffer = window.RTCPeerConnection.prototype.createOffer; - window.RTCPeerConnection.prototype.createOffer = function createOffer() { - if (this.setParametersPromises && this.setParametersPromises.length) { - return Promise.all(this.setParametersPromises) - .then(() => { - return origCreateOffer.apply(this, arguments); - }) - .finally(() => { - this.setParametersPromises = []; - }); - } - return origCreateOffer.apply(this, arguments); - }; + window.RTCPeerConnection.prototype.createOffer = + function createOffer(...args) { + if (this.setParametersPromises && this.setParametersPromises.length) { + return Promise.all(this.setParametersPromises) + .then(() => { + return origCreateOffer.apply(this, args); + }) + .finally(() => { + this.setParametersPromises = []; + }); + } + return origCreateOffer.apply(this, args); + }; } export function shimCreateAnswer(window) { @@ -285,16 +289,17 @@ export function shimCreateAnswer(window) { return; } const origCreateAnswer = window.RTCPeerConnection.prototype.createAnswer; - window.RTCPeerConnection.prototype.createAnswer = function createAnswer() { - if (this.setParametersPromises && this.setParametersPromises.length) { - return Promise.all(this.setParametersPromises) - .then(() => { - return origCreateAnswer.apply(this, arguments); - }) - .finally(() => { - this.setParametersPromises = []; - }); - } - return origCreateAnswer.apply(this, arguments); - }; + window.RTCPeerConnection.prototype.createAnswer = + function createAnswer(...args) { + if (this.setParametersPromises && this.setParametersPromises.length) { + return Promise.all(this.setParametersPromises) + .then(() => { + return origCreateAnswer.apply(this, args); + }) + .finally(() => { + this.setParametersPromises = []; + }); + } + return origCreateAnswer.apply(this, args); + }; } diff --git a/src/js/firefox/getusermedia.js b/src/js/firefox/getusermedia.js index 6b7d87b7..24921190 100644 --- a/src/js/firefox/getusermedia.js +++ b/src/js/firefox/getusermedia.js @@ -43,8 +43,8 @@ export function shimGetUserMedia(window, browserDetails) { if (MediaStreamTrack && MediaStreamTrack.prototype.getSettings) { const nativeGetSettings = MediaStreamTrack.prototype.getSettings; - MediaStreamTrack.prototype.getSettings = function() { - const obj = nativeGetSettings.apply(this, arguments); + MediaStreamTrack.prototype.getSettings = function(...args) { + const obj = nativeGetSettings.apply(this, args); remap(obj, 'mozAutoGainControl', 'autoGainControl'); remap(obj, 'mozNoiseSuppression', 'noiseSuppression'); return obj; diff --git a/src/js/safari/safari_shim.js b/src/js/safari/safari_shim.js index cfd09a33..73b09647 100644 --- a/src/js/safari/safari_shim.js +++ b/src/js/safari/safari_shim.js @@ -49,7 +49,7 @@ export function shimLocalStreamsAPI(window) { } }); } - return _addTrack.apply(this, arguments); + return _addTrack.apply(this, [track, ...streams]); }; } if (!('removeStream' in window.RTCPeerConnection.prototype)) { @@ -113,7 +113,7 @@ export function shimRemoteStreamsAPI(window) { const origSetRemoteDescription = window.RTCPeerConnection.prototype.setRemoteDescription; window.RTCPeerConnection.prototype.setRemoteDescription = - function setRemoteDescription() { + function setRemoteDescription(description, ...args) { const pc = this; if (!this._onaddstreampoly) { this.addEventListener('track', this._onaddstreampoly = function(e) { @@ -131,7 +131,7 @@ export function shimRemoteStreamsAPI(window) { }); }); } - return origSetRemoteDescription.apply(pc, arguments); + return origSetRemoteDescription.apply(pc, [description, ...args]); }; } } @@ -140,16 +140,13 @@ export function shimCallbacksAPI(window) { if (typeof window !== 'object' || !window.RTCPeerConnection) { return; } - const prototype = window.RTCPeerConnection.prototype; - const origCreateOffer = prototype.createOffer; - const origCreateAnswer = prototype.createAnswer; - const setLocalDescription = prototype.setLocalDescription; - const setRemoteDescription = prototype.setRemoteDescription; - const addIceCandidate = prototype.addIceCandidate; - prototype.createOffer = - function createOffer(successCallback, failureCallback) { - const options = (arguments.length >= 2) ? arguments[2] : arguments[0]; + const origCreateOffer = window.RTCPeerConnection.prototype.createOffer; + window.RTCPeerConnection.prototype.createOffer = + function createOffer(...args) { + const successCallback = args[0]; + const failureCallback = args[1]; + const options = (args.length >= 2) ? args[2] : args[0]; const promise = origCreateOffer.apply(this, [options]); if (!failureCallback) { return promise; @@ -158,9 +155,12 @@ export function shimCallbacksAPI(window) { return Promise.resolve(); }; - prototype.createAnswer = - function createAnswer(successCallback, failureCallback) { - const options = (arguments.length >= 2) ? arguments[2] : arguments[0]; + const origCreateAnswer = window.RTCPeerConnection.prototype.createAnswer; + window.RTCPeerConnection.prototype.createAnswer = + function createAnswer(...args) { + const successCallback = args[0]; + const failureCallback = args[1]; + const options = (args.length >= 2) ? args[2] : args[0]; const promise = origCreateAnswer.apply(this, [options]); if (!failureCallback) { return promise; @@ -169,35 +169,43 @@ export function shimCallbacksAPI(window) { return Promise.resolve(); }; - let withCallback = function(description, successCallback, failureCallback) { - const promise = setLocalDescription.apply(this, [description]); - if (!failureCallback) { - return promise; - } - promise.then(successCallback, failureCallback); - return Promise.resolve(); - }; - prototype.setLocalDescription = withCallback; + const origSetLocalDescription = + window.RTCPeerConnection.prototype.setLocalDescription; + window.RTCPeerConnection.prototype.setLocalDescription = + function(...args) { + const [description, successCallback, failureCallback] = args; + const promise = origSetLocalDescription.apply(this, [description]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; - withCallback = function(description, successCallback, failureCallback) { - const promise = setRemoteDescription.apply(this, [description]); - if (!failureCallback) { - return promise; - } - promise.then(successCallback, failureCallback); - return Promise.resolve(); - }; - prototype.setRemoteDescription = withCallback; + const origSetRemoteDescription = + window.RTCPeerConnection.prototype.setRemoteDescription; + window.RTCPeerConnection.prototype.setRemoteDescription = + function(description, ...args) { + const [successCallback, failureCallback] = args; + const promise = origSetRemoteDescription.apply(this, [description]); + if (!failureCallback) { + return promise; + } + promise.then(successCallback, failureCallback); + return Promise.resolve(); + }; - withCallback = function(candidate, successCallback, failureCallback) { - const promise = addIceCandidate.apply(this, [candidate]); + const origAddIceCandidate = + window.RTCPeerConnection.prototype.addIceCandidate; + window.RTCPeerConnection.prototype.addIceCandidate = function(...args) { + const [candidate, successCallback, failureCallback] = args; + const promise = origAddIceCandidate.apply(this, [candidate]); if (!failureCallback) { return promise; } promise.then(successCallback, failureCallback); return Promise.resolve(); }; - prototype.addIceCandidate = withCallback; } export function shimGetUserMedia(window) { @@ -239,11 +247,11 @@ export function shimRTCIceServerUrls(window) { // migrate from non-spec RTCIceServer.url to RTCIceServer.urls const OrigPeerConnection = window.RTCPeerConnection; window.RTCPeerConnection = - function RTCPeerConnection(pcConfig, pcConstraints) { - if (pcConfig && pcConfig.iceServers) { + function RTCPeerConnection(config, ...args) { + if (config && config.iceServers) { const newIceServers = []; - for (let i = 0; i < pcConfig.iceServers.length; i++) { - let server = pcConfig.iceServers[i]; + for (let i = 0; i < config.iceServers.length; i++) { + let server = config.iceServers[i]; if (server.urls === undefined && server.url) { utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls'); server = JSON.parse(JSON.stringify(server)); @@ -251,12 +259,12 @@ export function shimRTCIceServerUrls(window) { delete server.url; newIceServers.push(server); } else { - newIceServers.push(pcConfig.iceServers[i]); + newIceServers.push(config.iceServers[i]); } } - pcConfig.iceServers = newIceServers; + config.iceServers = newIceServers; } - return new OrigPeerConnection(pcConfig, pcConstraints); + return new OrigPeerConnection(config, [...args]); }; window.RTCPeerConnection.prototype = OrigPeerConnection.prototype; // wrap static methods. Currently just generateCertificate. @@ -285,7 +293,8 @@ export function shimTrackEventTransceiver(window) { export function shimCreateOfferLegacy(window) { const origCreateOffer = window.RTCPeerConnection.prototype.createOffer; window.RTCPeerConnection.prototype.createOffer = - function createOffer(offerOptions) { + function createOffer(...args) { + const offerOptions = args[0]; if (offerOptions) { if (typeof offerOptions.offerToReceiveAudio !== 'undefined') { // support bit values @@ -339,7 +348,7 @@ export function shimCreateOfferLegacy(window) { this.addTransceiver('video', {direction: 'recvonly'}); } } - return origCreateOffer.apply(this, arguments); + return origCreateOffer.apply(this, args); }; } diff --git a/src/js/utils.js b/src/js/utils.js index 11bb46f0..d6f4ce12 100644 --- a/src/js/utils.js +++ b/src/js/utils.js @@ -33,9 +33,9 @@ export function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) { } const proto = window.RTCPeerConnection.prototype; const nativeAddEventListener = proto.addEventListener; - proto.addEventListener = function(nativeEventName, cb) { + proto.addEventListener = function(nativeEventName, cb, ...args) { if (nativeEventName !== eventNameToWrap) { - return nativeAddEventListener.apply(this, arguments); + return nativeAddEventListener.apply(this, [nativeEventName, cb, ...args]); } const wrappedCallback = (e) => { const modifiedEvent = wrapper(e); @@ -53,17 +53,19 @@ export function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) { } this._eventMap[eventNameToWrap].set(cb, wrappedCallback); return nativeAddEventListener.apply(this, [nativeEventName, - wrappedCallback]); + wrappedCallback, ...args]); }; const nativeRemoveEventListener = proto.removeEventListener; - proto.removeEventListener = function(nativeEventName, cb) { + proto.removeEventListener = function(nativeEventName, cb, ...args) { if (nativeEventName !== eventNameToWrap || !this._eventMap || !this._eventMap[eventNameToWrap]) { - return nativeRemoveEventListener.apply(this, arguments); + return nativeRemoveEventListener.apply(this, [nativeEventName, cb, + ...args]); } if (!this._eventMap[eventNameToWrap].has(cb)) { - return nativeRemoveEventListener.apply(this, arguments); + return nativeRemoveEventListener.apply(this, [nativeEventName, cb, + ...args]); } const unwrappedCb = this._eventMap[eventNameToWrap].get(cb); this._eventMap[eventNameToWrap].delete(cb); @@ -74,7 +76,7 @@ export function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) { delete this._eventMap; } return nativeRemoveEventListener.apply(this, [nativeEventName, - unwrappedCb]); + unwrappedCb, ...args]); }; Object.defineProperty(proto, 'on' + eventNameToWrap, { @@ -120,13 +122,13 @@ export function disableWarnings(bool) { return 'adapter.js deprecation warnings ' + (bool ? 'disabled' : 'enabled'); } -export function log() { +export function log(...args) { if (typeof window === 'object') { if (logDisabled_) { return; } if (typeof console !== 'undefined' && typeof console.log === 'function') { - console.log.apply(console, arguments); + console.log(...args); } } } diff --git a/test/e2e/rtcpeerconnection.js b/test/e2e/rtcpeerconnection.js index 811a1f37..0762e071 100644 --- a/test/e2e/rtcpeerconnection.js +++ b/test/e2e/rtcpeerconnection.js @@ -61,4 +61,38 @@ describe('RTCPeerConnection', () => { .then(offer => pc.setLocalDescription(offer)); }); }); + + it('has the correct number of arguments for shimmed methods', () => { + // createOffer(optional RTCOfferOptions options = {}) + expect(RTCPeerConnection.prototype.createOffer.length).to.equal(0); + + // createAnswer(optional RTCAnswerOptions options = {}) + expect(RTCPeerConnection.prototype.createAnswer.length).to.equal(0); + + // setLocalDescription(optional RTCSessionDescriptionInit description = {}) + expect(RTCPeerConnection.prototype.setLocalDescription.length).to.equal(0); + + // setRemoteDescription(RTCSessionDescriptionInit description) + expect(RTCPeerConnection.prototype.setRemoteDescription.length).to.equal(1); + + // addIceCandidate(optional RTCIceCandidateInit candidate = {}) + expect(RTCPeerConnection.prototype.addIceCandidate.length).to.equal(0); + + // getStats(optional MediaStreamTrack? selector = null) + expect(RTCPeerConnection.prototype.getStats.length).to.equal(0); + + // addTransceiver((MediaStreamTrack or DOMString) trackOrKind, + // optional RTCRtpTransceiverInit init = {}) + expect(RTCPeerConnection.prototype.addTransceiver.length).to.equal(1); + + // addTrack(MediaStreamTrack track, MediaStream... streams) + expect(RTCPeerConnection.prototype.addTrack.length).to.equal(1); + + // removeTrack(RTCRtpSender sender) + expect(RTCPeerConnection.prototype.removeTrack.length).to.equal(1); + + // createDataChannel(USVString label, + // optional RTCDataChannelInit dataChannelDict = {}) + expect(RTCPeerConnection.prototype.createDataChannel.length).to.equal(1); + }); }); diff --git a/test/unit/safari.test.js b/test/unit/safari.test.js index d3ca5436..b9cb7a79 100644 --- a/test/unit/safari.test.js +++ b/test/unit/safari.test.js @@ -23,12 +23,12 @@ describe('Safari shim', () => { }); it('shimStreamsAPI existence', () => { - const prototype = window.RTCPeerConnection.prototype; - expect(prototype.addTrack.length).toBe(1); - expect(prototype.addStream.length).toBe(1); - expect(prototype.removeStream.length).toBe(1); - expect(prototype.getLocalStreams.length).toBe(0); - expect(prototype.getRemoteStreams.length).toBe(0); + expect(window.RTCPeerConnection.prototype.addTrack.length).toBe(1); + expect(window.RTCPeerConnection.prototype.addStream.length).toBe(1); + expect(window.RTCPeerConnection.prototype.removeStream.length).toBe(1); + expect(window.RTCPeerConnection.prototype.getLocalStreams.length).toBe(0); + expect(window.RTCPeerConnection.prototype.getRemoteStreams.length) + .toBe(0); }); it('local streams API', () => { const pc = new window.RTCPeerConnection(); @@ -72,12 +72,13 @@ describe('Safari shim', () => { describe('shimCallbacksAPI', () => { it('shimCallbacksAPI existence', () => { shim.shimCallbacksAPI(window); - const prototype = window.RTCPeerConnection.prototype; - expect(prototype.createOffer.length).toBe(2); - expect(prototype.createAnswer.length).toBe(2); - expect(prototype.setLocalDescription.length).toBe(3); - expect(prototype.setRemoteDescription.length).toBe(3); - expect(prototype.addIceCandidate.length).toBe(3); + expect(window.RTCPeerConnection.prototype.createOffer.length).toBe(0); + expect(window.RTCPeerConnection.prototype.createAnswer.length).toBe(0); + expect(window.RTCPeerConnection.prototype.setLocalDescription.length) + .toBe(0); + expect(window.RTCPeerConnection.prototype.setRemoteDescription.length) + .toBe(1); + expect(window.RTCPeerConnection.prototype.addIceCandidate.length).toBe(0); }); });