@@ -658,8 +658,12 @@ Raven.prototype = {
658658
659659 function wrapTimeFn ( orig ) {
660660 return function ( fn , t ) { // preserve arity
661- // Make a copy of the arguments
662- var args = [ ] . slice . call ( arguments ) ;
661+ // Make a copy of the arguments to prevent deoptimization
662+ // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments
663+ var args = new Array ( arguments . length ) ;
664+ for ( var i = 0 ; i < args . length ; ++ i ) {
665+ args [ i ] = arguments [ i ] ;
666+ }
663667 var originalCallback = args [ 0 ] ;
664668 if ( isFunction ( originalCallback ) ) {
665669 args [ 0 ] = self . wrap ( originalCallback ) ;
@@ -676,26 +680,7 @@ Raven.prototype = {
676680 } ;
677681 }
678682
679- fill ( window , 'setTimeout' , wrapTimeFn ) ;
680- fill ( window , 'setInterval' , wrapTimeFn ) ;
681- if ( window . requestAnimationFrame ) {
682- fill ( window , 'requestAnimationFrame' , function ( orig ) {
683- return function ( cb ) {
684- return orig ( self . wrap ( cb ) ) ;
685- } ;
686- } ) ;
687- }
688-
689- // Capture breadcrubms from any click that is unhandled / bubbled up all the way
690- // to the document. Do this before we instrument addEventListener.
691- if ( this . _hasDocument ) {
692- document . addEventListener ( 'click' , self . _breadcrumbEventHandler ( 'click' ) ) ;
693-
694- }
695-
696- // event targets borrowed from bugsnag-js:
697- // https://github.com/bugsnag/bugsnag-js/blob/master/src/bugsnag.js#L666
698- 'EventTarget Window Node ApplicationCache AudioTrackList ChannelMergerNode CryptoOperation EventSource FileReader HTMLUnknownElement IDBDatabase IDBRequest IDBTransaction KeyOperation MediaController MessagePort ModalWindow Notification SVGElementInstance Screen TextTrack TextTrackCue TextTrackList WebSocket WebSocketWorker Worker XMLHttpRequest XMLHttpRequestEventTarget XMLHttpRequestUpload' . replace ( / \w + / g, function ( global ) {
683+ function wrapEventTarget ( global ) {
699684 var proto = window [ global ] && window [ global ] . prototype ;
700685 if ( proto && proto . hasOwnProperty && proto . hasOwnProperty ( 'addEventListener' ) ) {
701686 fill ( proto , 'addEventListener' , function ( orig ) {
@@ -724,7 +709,38 @@ Raven.prototype = {
724709 } ;
725710 } ) ;
726711 }
727- } ) ;
712+ }
713+
714+ function wrapProp ( prop , xhr ) {
715+ if ( prop in xhr && isFunction ( xhr [ prop ] ) ) {
716+ fill ( xhr , prop , function ( orig ) {
717+ return self . wrap ( orig ) ;
718+ } , true /* noUndo */ ) ; // don't track filled methods on XHR instances
719+ }
720+ }
721+
722+ fill ( window , 'setTimeout' , wrapTimeFn ) ;
723+ fill ( window , 'setInterval' , wrapTimeFn ) ;
724+ if ( window . requestAnimationFrame ) {
725+ fill ( window , 'requestAnimationFrame' , function ( orig ) {
726+ return function ( cb ) {
727+ return orig ( self . wrap ( cb ) ) ;
728+ } ;
729+ } ) ;
730+ }
731+
732+ // Capture breadcrubms from any click that is unhandled / bubbled up all the way
733+ // to the document. Do this before we instrument addEventListener.
734+ if ( this . _hasDocument ) {
735+ document . addEventListener ( 'click' , self . _breadcrumbEventHandler ( 'click' ) ) ;
736+ }
737+
738+ // event targets borrowed from bugsnag-js:
739+ // https://github.com/bugsnag/bugsnag-js/blob/master/src/bugsnag.js#L666
740+ var eventTargets = [ 'EventTarget' , 'Window' , 'Node' , 'ApplicationCache' , 'AudioTrackList' , 'ChannelMergerNode' , 'CryptoOperation' , 'EventSource' , 'FileReader' , 'HTMLUnknownElement' , 'IDBDatabase' , 'IDBRequest' , 'IDBTransaction' , 'KeyOperation' , 'MediaController' , 'MessagePort' , 'ModalWindow' , 'Notification' , 'SVGElementInstance' , 'Screen' , 'TextTrack' , 'TextTrackCue' , 'TextTrackList' , 'WebSocket' , 'WebSocketWorker' , 'Worker' , 'XMLHttpRequest' , 'XMLHttpRequestEventTarget' , 'XMLHttpRequestUpload' ] ;
741+ for ( var i = 0 ; i < eventTargets . length ; i ++ ) {
742+ wrapEventTarget ( eventTargets [ i ] ) ;
743+ }
728744
729745 if ( 'XMLHttpRequest' in window ) {
730746 var xhrproto = XMLHttpRequest . prototype ;
@@ -754,13 +770,10 @@ Raven.prototype = {
754770 }
755771 }
756772
757- 'onload onerror onprogress' . replace ( / \w + / g, function ( prop ) {
758- if ( prop in xhr && isFunction ( xhr [ prop ] ) ) {
759- fill ( xhr , prop , function ( orig ) {
760- return self . wrap ( orig ) ;
761- } , true /* noUndo */ ) ; // don't track filled methods on XHR instances
762- }
763- } ) ;
773+ var props = [ 'onload' , 'onerror' , 'onprogress' ] ;
774+ for ( var j = 0 ; j < props . length ; j ++ ) {
775+ wrapProp ( props [ j ] , xhr ) ;
776+ }
764777
765778 if ( 'onreadystatechange' in xhr && isFunction ( xhr . onreadystatechange ) ) {
766779 fill ( xhr , 'onreadystatechange' , function ( orig ) {
0 commit comments