1
- /*! Raven.js 3.11.0 (c2f43d7 ) | github.com/getsentry/raven-js */
1
+ /*! Raven.js 3.11.0 (cb87941 ) | github.com/getsentry/raven-js */
2
2
3
3
/*
4
4
* Includes TraceKit
@@ -125,6 +125,7 @@ function Raven() {
125
125
this . _hasDocument = ! isUndefined ( _document ) ;
126
126
this . _hasNavigator = ! isUndefined ( _navigator ) ;
127
127
this . _lastCapturedException = null ;
128
+ this . _lastData = null ;
128
129
this . _lastEventId = null ;
129
130
this . _globalServer = null ;
130
131
this . _globalKey = null ;
@@ -840,14 +841,14 @@ Raven.prototype = {
840
841
return ;
841
842
842
843
self . _lastCapturedEvent = evt ;
843
- var elem = evt . target ;
844
844
845
+ // try/catch both:
846
+ // - accessing evt.target (see getsentry/raven-js#838, #768)
847
+ // - `htmlTreeAsString` because it's complex, and just accessing the DOM incorrectly
848
+ // can throw an exception in some circumstances.
845
849
var target ;
846
-
847
- // try/catch htmlTreeAsString because it's particularly complicated, and
848
- // just accessing the DOM incorrectly can throw an exception in some circumstances.
849
850
try {
850
- target = htmlTreeAsString ( elem ) ;
851
+ target = htmlTreeAsString ( evt . target ) ;
851
852
} catch ( e ) {
852
853
target = '<unknown>' ;
853
854
}
@@ -872,8 +873,15 @@ Raven.prototype = {
872
873
// debounce timeout is triggered, we will only capture
873
874
// a single breadcrumb from the FIRST target (acceptable?)
874
875
return function ( evt ) {
875
- var target = evt . target ,
876
- tagName = target && target . tagName ;
876
+ var target ;
877
+ try {
878
+ target = evt . target ;
879
+ } catch ( e ) {
880
+ // just accessing event properties can throw an exception in some rare circumstances
881
+ // see: https://github.com/getsentry/raven-js/issues/838
882
+ return ;
883
+ }
884
+ var tagName = target && target . tagName ;
877
885
878
886
// only consider keypress events on actual input elements
879
887
// this will disregard keypresses targeting body (e.g. tabbing
@@ -990,9 +998,17 @@ Raven.prototype = {
990
998
// see #724
991
999
if ( ! evt ) return ;
992
1000
993
- if ( evt . type === 'click' )
1001
+ var eventType ;
1002
+ try {
1003
+ eventType = evt . type
1004
+ } catch ( e ) {
1005
+ // just accessing event properties can throw an exception in some rare circumstances
1006
+ // see: https://github.com/getsentry/raven-js/issues/838
1007
+ return ;
1008
+ }
1009
+ if ( eventType === 'click' )
994
1010
return clickHandler ( evt ) ;
995
- else if ( evt . type === 'keypress' )
1011
+ else if ( eventType === 'keypress' )
996
1012
return keypressHandler ( evt ) ;
997
1013
} ;
998
1014
}
@@ -1428,6 +1444,35 @@ Raven.prototype = {
1428
1444
return this . _backoffDuration && now ( ) - this . _backoffStart < this . _backoffDuration ;
1429
1445
} ,
1430
1446
1447
+ /**
1448
+ * Returns true if the in-process data payload matches the signature
1449
+ * of the previously-sent data
1450
+ *
1451
+ * NOTE: This has to be done at this level because TraceKit can generate
1452
+ * data from window.onerror WITHOUT an exception object (IE8, IE9,
1453
+ * other old browsers). This can take the form of an "exception"
1454
+ * data object with a single frame (derived from the onerror args).
1455
+ */
1456
+ _isRepeatData : function ( current ) {
1457
+ var last = this . _lastData ;
1458
+
1459
+ if ( ! last ||
1460
+ current . message !== last . message || // defined for captureMessage
1461
+ current . culprit !== last . culprit ) // defined for captureException/onerror
1462
+ return false ;
1463
+
1464
+ // Stacktrace interface (i.e. from captureMessage)
1465
+ if ( current . stacktrace || last . stacktrace ) {
1466
+ return isSameStacktrace ( current . stacktrace , last . stacktrace ) ;
1467
+ }
1468
+ // Exception interface (i.e. from captureException/onerror)
1469
+ else if ( current . exception || last . exception ) {
1470
+ return isSameException ( current . exception , last . exception ) ;
1471
+ }
1472
+
1473
+ return true ;
1474
+ } ,
1475
+
1431
1476
_setBackoffState : function ( request ) {
1432
1477
// If we are already in a backoff state, don't change anything
1433
1478
if ( this . _shouldBackoff ( ) ) {
@@ -1447,7 +1492,7 @@ Raven.prototype = {
1447
1492
// If Retry-After is not in Access-Control-Expose-Headers, most
1448
1493
// browsers will throw an exception trying to access it
1449
1494
retry = request . getResponseHeader ( 'Retry-After' ) ;
1450
- retry = parseInt ( retry , 10 ) ;
1495
+ retry = parseInt ( retry , 10 ) * 1000 ; // Retry-After is returned in seconds
1451
1496
} catch ( e ) {
1452
1497
/* eslint no-empty:0 */
1453
1498
}
@@ -1554,6 +1599,17 @@ Raven.prototype = {
1554
1599
// Try and clean up the packet before sending by truncating long values
1555
1600
data = this . _trimPacket ( data ) ;
1556
1601
1602
+ // ideally duplicate error testing should occur *before* dataCallback/shouldSendCallback,
1603
+ // but this would require copying an un-truncated copy of the data packet, which can be
1604
+ // arbitrarily deep (extra_data) -- could be worthwhile? will revisit
1605
+ if ( ! this . _globalOptions . allowDuplicates && this . _isRepeatData ( data ) ) {
1606
+ this . _logDebug ( 'warn' , 'Raven dropped repeat event: ' , data ) ;
1607
+ return ;
1608
+ }
1609
+
1610
+ // Store outbound payload after trim
1611
+ this . _lastData = data ;
1612
+
1557
1613
this . _logDebug ( 'debug' , 'Raven about to send:' , data ) ;
1558
1614
1559
1615
var auth = {
@@ -1915,6 +1971,58 @@ function htmlElementAsString(elem) {
1915
1971
return out . join ( '' ) ;
1916
1972
}
1917
1973
1974
+ /**
1975
+ * Returns true if either a OR b is truthy, but not both
1976
+ */
1977
+ function isOnlyOneTruthy ( a , b ) {
1978
+ return ! ! ( ! ! a ^ ! ! b ) ;
1979
+ }
1980
+
1981
+ /**
1982
+ * Returns true if the two input exception interfaces have the same content
1983
+ */
1984
+ function isSameException ( ex1 , ex2 ) {
1985
+ if ( isOnlyOneTruthy ( ex1 , ex2 ) )
1986
+ return false ;
1987
+
1988
+ ex1 = ex1 . values [ 0 ] ;
1989
+ ex2 = ex2 . values [ 0 ] ;
1990
+
1991
+ if ( ex1 . type !== ex2 . type ||
1992
+ ex1 . value !== ex2 . value )
1993
+ return false ;
1994
+
1995
+ return isSameStacktrace ( ex1 . stacktrace , ex2 . stacktrace ) ;
1996
+ }
1997
+
1998
+ /**
1999
+ * Returns true if the two input stack trace interfaces have the same content
2000
+ */
2001
+ function isSameStacktrace ( stack1 , stack2 ) {
2002
+ if ( isOnlyOneTruthy ( stack1 , stack2 ) )
2003
+ return false ;
2004
+
2005
+ var frames1 = stack1 . frames ;
2006
+ var frames2 = stack2 . frames ;
2007
+
2008
+ // Exit early if frame count differs
2009
+ if ( frames1 . length !== frames2 . length )
2010
+ return false ;
2011
+
2012
+ // Iterate through every frame; bail out if anything differs
2013
+ var a , b ;
2014
+ for ( var i = 0 ; i < frames1 . length ; i ++ ) {
2015
+ a = frames1 [ i ] ;
2016
+ b = frames2 [ i ] ;
2017
+ if ( a . filename !== b . filename ||
2018
+ a . lineno !== b . lineno ||
2019
+ a . colno !== b . colno ||
2020
+ a [ 'function' ] !== b [ 'function' ] )
2021
+ return false ;
2022
+ }
2023
+ return true ;
2024
+ }
2025
+
1918
2026
/**
1919
2027
* Polyfill a method
1920
2028
* @param obj object e.g. `document`
0 commit comments