ravenjs-gem 1.0.7.0 → 1.1.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,54 +1,34 @@
1
- /*! Raven.js 1.0.7 | github.com/getsentry/raven-js */
1
+ /*! Raven.js 1.1.14 (f9803bd) | github.com/getsentry/raven-js */
2
2
 
3
3
  /*
4
4
  * Includes TraceKit
5
5
  * https://github.com/getsentry/TraceKit
6
6
  *
7
- * Copyright 2013 Matt Robenolt and other contributors
7
+ * Copyright 2014 Matt Robenolt and other contributors
8
8
  * Released under the BSD license
9
9
  * https://github.com/getsentry/raven-js/blob/master/LICENSE
10
10
  *
11
11
  */
12
+ ;(function(window, undefined){
13
+ 'use strict';
14
+
12
15
  /*
13
16
  TraceKit - Cross brower stack traces - github.com/occ/TraceKit
14
17
  MIT license
15
18
  */
16
19
 
17
- ;(function(window, undefined) {
18
-
19
-
20
- var TraceKit = {};
21
- var _oldTraceKit = window.TraceKit;
20
+ var TraceKit = {
21
+ remoteFetching: false,
22
+ collectWindowErrors: true,
23
+ // 3 lines before, the offending line, 3 lines after
24
+ linesOfContext: 7
25
+ };
22
26
 
23
27
  // global reference to slice
24
28
  var _slice = [].slice;
25
29
  var UNKNOWN_FUNCTION = '?';
26
30
 
27
31
 
28
- /**
29
- * _has, a better form of hasOwnProperty
30
- * Example: _has(MainHostObject, property) === true/false
31
- *
32
- * @param {Object} host object to check property
33
- * @param {string} key to check
34
- */
35
- function _has(object, key) {
36
- return Object.prototype.hasOwnProperty.call(object, key);
37
- }
38
-
39
- function _isUndefined(what) {
40
- return typeof what === 'undefined';
41
- }
42
-
43
- /**
44
- * TraceKit.noConflict: Export TraceKit out to another variable
45
- * Example: var TK = TraceKit.noConflict()
46
- */
47
- TraceKit.noConflict = function noConflict() {
48
- window.TraceKit = _oldTraceKit;
49
- return TraceKit;
50
- };
51
-
52
32
  /**
53
33
  * TraceKit.wrap: Wrap any function in a TraceKit reporter
54
34
  * Example: func = TraceKit.wrap(func);
@@ -109,6 +89,7 @@ TraceKit.wrap = function traceKitWrapper(func) {
109
89
  */
110
90
  TraceKit.report = (function reportModuleWrapper() {
111
91
  var handlers = [],
92
+ lastArgs = null,
112
93
  lastException = null,
113
94
  lastExceptionStack = null;
114
95
 
@@ -117,6 +98,7 @@ TraceKit.report = (function reportModuleWrapper() {
117
98
  * @param {Function} handler
118
99
  */
119
100
  function subscribe(handler) {
101
+ installGlobalHandler();
120
102
  handlers.push(handler);
121
103
  }
122
104
 
@@ -132,17 +114,25 @@ TraceKit.report = (function reportModuleWrapper() {
132
114
  }
133
115
  }
134
116
 
117
+ /**
118
+ * Remove all crash handlers.
119
+ */
120
+ function unsubscribeAll() {
121
+ uninstallGlobalHandler();
122
+ handlers = [];
123
+ }
124
+
135
125
  /**
136
126
  * Dispatch stack information to all handlers.
137
127
  * @param {Object.<string, *>} stack
138
128
  */
139
- function notifyHandlers(stack, windowError) {
129
+ function notifyHandlers(stack, isWindowError) {
140
130
  var exception = null;
141
- if (windowError && !TraceKit.collectWindowErrors) {
131
+ if (isWindowError && !TraceKit.collectWindowErrors) {
142
132
  return;
143
133
  }
144
134
  for (var i in handlers) {
145
- if (_has(handlers, i)) {
135
+ if (hasKey(handlers, i)) {
146
136
  try {
147
137
  handlers[i].apply(null, [stack].concat(_slice.call(arguments, 2)));
148
138
  } catch (inner) {
@@ -156,7 +146,7 @@ TraceKit.report = (function reportModuleWrapper() {
156
146
  }
157
147
  }
158
148
 
159
- var _oldOnerrorHandler = window.onerror;
149
+ var _oldOnerrorHandler, _onErrorHandlerInstalled;
160
150
 
161
151
  /**
162
152
  * Ensures all global unhandled exceptions are recorded.
@@ -165,60 +155,95 @@ TraceKit.report = (function reportModuleWrapper() {
165
155
  * @param {string} url URL of script that generated the exception.
166
156
  * @param {(number|string)} lineNo The line number at which the error
167
157
  * occurred.
158
+ * @param {?(number|string)} colNo The column number at which the error
159
+ * occurred.
160
+ * @param {?Error} ex The actual Error object.
168
161
  */
169
- window.onerror = function traceKitWindowOnError(message, url, lineNo) {
162
+ function traceKitWindowOnError(message, url, lineNo, colNo, ex) {
170
163
  var stack = null;
171
164
 
172
165
  if (lastExceptionStack) {
173
166
  TraceKit.computeStackTrace.augmentStackTraceWithInitialElement(lastExceptionStack, url, lineNo, message);
174
- stack = lastExceptionStack;
175
- lastExceptionStack = null;
176
- lastException = null;
167
+ processLastException();
168
+ } else if (ex) {
169
+ // New chrome and blink send along a real error object
170
+ // Let's just report that like a normal error.
171
+ // See: https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror
172
+ stack = TraceKit.computeStackTrace(ex);
173
+ notifyHandlers(stack, true);
177
174
  } else {
178
175
  var location = {
179
176
  'url': url,
180
- 'line': lineNo
177
+ 'line': lineNo,
178
+ 'column': colNo
181
179
  };
182
180
  location.func = TraceKit.computeStackTrace.guessFunctionName(location.url, location.line);
183
181
  location.context = TraceKit.computeStackTrace.gatherContext(location.url, location.line);
184
182
  stack = {
185
- 'mode': 'onerror',
186
183
  'message': message,
187
184
  'url': document.location.href,
188
- 'stack': [location],
189
- 'useragent': navigator.userAgent
185
+ 'stack': [location]
190
186
  };
187
+ notifyHandlers(stack, true);
191
188
  }
192
189
 
193
- notifyHandlers(stack, 'from window.onerror');
194
-
195
190
  if (_oldOnerrorHandler) {
196
191
  return _oldOnerrorHandler.apply(this, arguments);
197
192
  }
198
193
 
199
194
  return false;
200
- };
195
+ }
196
+
197
+ function installGlobalHandler ()
198
+ {
199
+ if (_onErrorHandlerInstalled) {
200
+ return;
201
+ }
202
+ _oldOnerrorHandler = window.onerror;
203
+ window.onerror = traceKitWindowOnError;
204
+ _onErrorHandlerInstalled = true;
205
+ }
206
+
207
+ function uninstallGlobalHandler ()
208
+ {
209
+ if (!_onErrorHandlerInstalled) {
210
+ return;
211
+ }
212
+ window.onerror = _oldOnerrorHandler;
213
+ _onErrorHandlerInstalled = false;
214
+ _oldOnerrorHandler = undefined;
215
+ }
216
+
217
+ function processLastException() {
218
+ var _lastExceptionStack = lastExceptionStack,
219
+ _lastArgs = lastArgs;
220
+ lastArgs = null;
221
+ lastExceptionStack = null;
222
+ lastException = null;
223
+ notifyHandlers.apply(null, [_lastExceptionStack, false].concat(_lastArgs));
224
+ }
201
225
 
202
226
  /**
203
227
  * Reports an unhandled Error to TraceKit.
204
228
  * @param {Error} ex
229
+ * @param {?boolean} rethrow If false, do not re-throw the exception.
230
+ * Only used for window.onerror to not cause an infinite loop of
231
+ * rethrowing.
205
232
  */
206
- function report(ex) {
233
+ function report(ex, rethrow) {
207
234
  var args = _slice.call(arguments, 1);
208
235
  if (lastExceptionStack) {
209
236
  if (lastException === ex) {
210
237
  return; // already caught by an inner catch block, ignore
211
238
  } else {
212
- var s = lastExceptionStack;
213
- lastExceptionStack = null;
214
- lastException = null;
215
- notifyHandlers.apply(null, [s, null].concat(args));
239
+ processLastException();
216
240
  }
217
241
  }
218
242
 
219
243
  var stack = TraceKit.computeStackTrace(ex);
220
244
  lastExceptionStack = stack;
221
245
  lastException = ex;
246
+ lastArgs = args;
222
247
 
223
248
  // If the stack trace is incomplete, wait for 2 seconds for
224
249
  // slow slow IE to see if onerror occurs or not before reporting
@@ -226,17 +251,18 @@ TraceKit.report = (function reportModuleWrapper() {
226
251
  // stack trace
227
252
  window.setTimeout(function () {
228
253
  if (lastException === ex) {
229
- lastExceptionStack = null;
230
- lastException = null;
231
- notifyHandlers.apply(null, [stack, null].concat(args));
254
+ processLastException();
232
255
  }
233
256
  }, (stack.incomplete ? 2000 : 0));
234
257
 
235
- throw ex; // re-throw to propagate to the top level (and cause window.onerror)
258
+ if (rethrow !== false) {
259
+ throw ex; // re-throw to propagate to the top level (and cause window.onerror)
260
+ }
236
261
  }
237
262
 
238
263
  report.subscribe = subscribe;
239
264
  report.unsubscribe = unsubscribe;
265
+ report.uninstall = unsubscribeAll;
240
266
  return report;
241
267
  }());
242
268
 
@@ -255,7 +281,6 @@ TraceKit.report = (function reportModuleWrapper() {
255
281
  * s.stack[i].line - line number, if known
256
282
  * s.stack[i].column - column number, if known
257
283
  * s.stack[i].context - an array of source code lines; the middle element corresponds to the correct line#
258
- * s.mode - 'stack', 'stacktrace', 'multiline', 'callers', 'onerror', or 'failed' -- method used to collect the stack trace
259
284
  *
260
285
  * Supports:
261
286
  * - Firefox: full stack trace with line numbers and unreliable column
@@ -322,14 +347,14 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
322
347
  return '';
323
348
  }
324
349
  try {
325
- function getXHR() {
350
+ var getXHR = function() {
326
351
  try {
327
352
  return new window.XMLHttpRequest();
328
353
  } catch (e) {
329
354
  // explicitly bubble up the exception if not found
330
355
  return new window.ActiveXObject('Microsoft.XMLHTTP');
331
356
  }
332
- }
357
+ };
333
358
 
334
359
  var request = getXHR();
335
360
  request.open('GET', url, false);
@@ -346,7 +371,8 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
346
371
  * @return {Array.<string>} Source contents.
347
372
  */
348
373
  function getSource(url) {
349
- if (!_has(sourceCache, url)) {
374
+ if (!isString(url)) return [];
375
+ if (!hasKey(sourceCache, url)) {
350
376
  // URL needs to be able to fetched within the acceptable domain. Otherwise,
351
377
  // cross-domain errors will be triggered.
352
378
  var source = '';
@@ -384,7 +410,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
384
410
  for (var i = 0; i < maxLines; ++i) {
385
411
  line = source[lineNo - i] + line;
386
412
 
387
- if (!_isUndefined(line)) {
413
+ if (!isUndefined(line)) {
388
414
  if ((m = reGuessFunction.exec(line))) {
389
415
  return m[1];
390
416
  } else if ((m = reFunctionArgNames.exec(line))) {
@@ -423,7 +449,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
423
449
  line -= 1; // convert to 0-based index
424
450
 
425
451
  for (var i = start; i < end; ++i) {
426
- if (!_isUndefined(source[i])) {
452
+ if (!isUndefined(source[i])) {
427
453
  context.push(source[i]);
428
454
  }
429
455
  }
@@ -533,7 +559,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
533
559
  re = new RegExp(escapeRegExp(code).replace(/\s+/g, '\\s+'));
534
560
  }
535
561
 
536
- // not sure if this is really necessary, but I dont have a test
562
+ // not sure if this is really necessary, but I don’t have a test
537
563
  // corpus large enough to confirm that and it was in the original.
538
564
  else {
539
565
  var name = parts[1] ? '\\s+' + parts[1] : '',
@@ -587,6 +613,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
587
613
  // ex.message = qq is not defined
588
614
  // ex.fileName = http://...
589
615
  // ex.lineNumber = 59
616
+ // ex.columnNumber = 69
590
617
  // ex.stack = ...stack trace... (see the example below)
591
618
  // ex.name = ReferenceError
592
619
  //
@@ -618,8 +645,8 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
618
645
  return null;
619
646
  }
620
647
 
621
- var chrome = /^\s*at (?:((?:\[object object\])?\S+) )?\(?((?:file|http|https):.*?):(\d+)(?::(\d+))?\)?\s*$/i,
622
- gecko = /^\s*(\S*)(?:\((.*?)\))?@((?:file|http|https).*?):(\d+)(?::(\d+))?\s*$/i,
648
+ var chrome = /^\s*at (?:((?:\[object object\])?\S+(?: \[as \S+\])?) )?\(?((?:file|https?):.*?):(\d+)(?::(\d+))?\)?\s*$/i,
649
+ gecko = /^\s*(\S*)(?:\((.*?)\))?@((?:file|https?).*?):(\d+)(?::(\d+))?\s*$/i,
623
650
  lines = ex.stack.split('\n'),
624
651
  stack = [],
625
652
  parts,
@@ -657,21 +684,24 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
657
684
  stack.push(element);
658
685
  }
659
686
 
660
- if (stack[0] && stack[0].line && !stack[0].column && reference) {
661
- stack[0].column = findSourceInLine(reference[1], stack[0].url, stack[0].line);
662
- }
663
-
664
687
  if (!stack.length) {
665
688
  return null;
666
689
  }
667
690
 
691
+ if (stack[0].line && !stack[0].column && reference) {
692
+ stack[0].column = findSourceInLine(reference[1], stack[0].url, stack[0].line);
693
+ } else if (!stack[0].column && !isUndefined(ex.columnNumber)) {
694
+ // FireFox uses this awesome columnNumber property for its top frame
695
+ // Also note, Firefox's column number is 0-based and everything else expects 1-based,
696
+ // so adding 1
697
+ stack[0].column = ex.columnNumber + 1;
698
+ }
699
+
668
700
  return {
669
- 'mode': 'stack',
670
701
  'name': ex.name,
671
702
  'message': ex.message,
672
703
  'url': document.location.href,
673
- 'stack': stack,
674
- 'useragent': navigator.userAgent
704
+ 'stack': stack
675
705
  };
676
706
  }
677
707
 
@@ -724,12 +754,10 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
724
754
  }
725
755
 
726
756
  return {
727
- 'mode': 'stacktrace',
728
757
  'name': ex.name,
729
758
  'message': ex.message,
730
759
  'url': document.location.href,
731
- 'stack': stack,
732
- 'useragent': navigator.userAgent
760
+ 'stack': stack
733
761
  };
734
762
  }
735
763
 
@@ -762,8 +790,8 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
762
790
  return null;
763
791
  }
764
792
 
765
- var lineRE1 = /^\s*Line (\d+) of linked script ((?:file|http|https)\S+)(?:: in function (\S+))?\s*$/i,
766
- lineRE2 = /^\s*Line (\d+) of inline#(\d+) script in ((?:file|http|https)\S+)(?:: in function (\S+))?\s*$/i,
793
+ var lineRE1 = /^\s*Line (\d+) of linked script ((?:file|https?)\S+)(?:: in function (\S+))?\s*$/i,
794
+ lineRE2 = /^\s*Line (\d+) of inline#(\d+) script in ((?:file|https?)\S+)(?:: in function (\S+))?\s*$/i,
767
795
  lineRE3 = /^\s*Line (\d+) of function script\s*$/i,
768
796
  stack = [],
769
797
  scripts = document.getElementsByTagName('script'),
@@ -774,7 +802,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
774
802
  source;
775
803
 
776
804
  for (i in scripts) {
777
- if (_has(scripts, i) && !scripts[i].src) {
805
+ if (hasKey(scripts, i) && !scripts[i].src) {
778
806
  inlineScriptBlocks.push(scripts[i]);
779
807
  }
780
808
  }
@@ -836,12 +864,10 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
836
864
  }
837
865
 
838
866
  return {
839
- 'mode': 'multiline',
840
867
  'name': ex.name,
841
868
  'message': lines[0],
842
869
  'url': document.location.href,
843
- 'stack': stack,
844
- 'useragent': navigator.userAgent
870
+ 'stack': stack
845
871
  };
846
872
  }
847
873
 
@@ -969,12 +995,10 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
969
995
  }
970
996
 
971
997
  var result = {
972
- 'mode': 'callers',
973
998
  'name': ex.name,
974
999
  'message': ex.message,
975
1000
  'url': document.location.href,
976
- 'stack': stack,
977
- 'useragent': navigator.userAgent
1001
+ 'stack': stack
978
1002
  };
979
1003
  augmentStackTraceWithInitialElement(result, ex.sourceURL || ex.fileName, ex.line || ex.lineNumber, ex.message || ex.description);
980
1004
  return result;
@@ -1036,9 +1060,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
1036
1060
  }
1037
1061
  }
1038
1062
 
1039
- return {
1040
- 'mode': 'failed'
1041
- };
1063
+ return {};
1042
1064
  }
1043
1065
 
1044
1066
  /**
@@ -1053,8 +1075,6 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
1053
1075
  } catch (ex) {
1054
1076
  return computeStackTrace(ex, depth + 1);
1055
1077
  }
1056
-
1057
- return null;
1058
1078
  }
1059
1079
 
1060
1080
  computeStackTrace.augmentStackTraceWithInitialElement = augmentStackTraceWithInitialElement;
@@ -1065,133 +1085,15 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
1065
1085
  return computeStackTrace;
1066
1086
  }());
1067
1087
 
1068
- /**
1069
- * Extends support for global error handling for asynchronous browser
1070
- * functions. Adopted from Closure Library's errorhandler.js
1071
- */
1072
- (function extendToAsynchronousCallbacks() {
1073
- var _helper = function _helper(fnName) {
1074
- var originalFn = window[fnName];
1075
- window[fnName] = function traceKitAsyncExtension() {
1076
- // Make a copy of the arguments
1077
- var args = _slice.call(arguments);
1078
- var originalCallback = args[0];
1079
- if (typeof (originalCallback) === 'function') {
1080
- args[0] = TraceKit.wrap(originalCallback);
1081
- }
1082
- // IE < 9 doesn't support .call/.apply on setInterval/setTimeout, but it
1083
- // also only supports 2 argument and doesn't care what "this" is, so we
1084
- // can just call the original function directly.
1085
- if (originalFn.apply) {
1086
- return originalFn.apply(this, args);
1087
- } else {
1088
- return originalFn(args[0], args[1]);
1089
- }
1090
- };
1091
- };
1092
-
1093
- _helper('setTimeout');
1094
- _helper('setInterval');
1095
- }());
1096
-
1097
- /**
1098
- * Extended support for backtraces and global error handling for most
1099
- * asynchronous jQuery functions.
1100
- */
1101
- (function traceKitAsyncForjQuery($) {
1102
-
1103
- // quit if jQuery isn't on the page
1104
- if (!$) {
1105
- return;
1106
- }
1107
-
1108
- var _oldEventAdd = $.event.add;
1109
- $.event.add = function traceKitEventAdd(elem, types, handler, data, selector) {
1110
- var _handler;
1111
-
1112
- if (handler.handler) {
1113
- _handler = handler.handler;
1114
- handler.handler = TraceKit.wrap(handler.handler);
1115
- } else {
1116
- _handler = handler;
1117
- handler = TraceKit.wrap(handler);
1118
- }
1119
-
1120
- // If the handler we are attaching doesn’t have the same guid as
1121
- // the original, it will never be removed when someone tries to
1122
- // unbind the original function later. Technically as a result of
1123
- // this our guids are no longer globally unique, but whatever, that
1124
- // never hurt anybody RIGHT?!
1125
- if (_handler.guid) {
1126
- handler.guid = _handler.guid;
1127
- } else {
1128
- handler.guid = _handler.guid = $.guid++;
1129
- }
1130
-
1131
- return _oldEventAdd.call(this, elem, types, handler, data, selector);
1132
- };
1133
-
1134
- var _oldReady = $.fn.ready;
1135
- $.fn.ready = function traceKitjQueryReadyWrapper(fn) {
1136
- return _oldReady.call(this, TraceKit.wrap(fn));
1137
- };
1138
-
1139
- var _oldAjax = $.ajax;
1140
- $.ajax = function traceKitAjaxWrapper(url, options) {
1141
- var keys = ['complete', 'error', 'success'], key;
1142
-
1143
- // Taken from https://github.com/jquery/jquery/blob/eee2eaf1d7a189d99106423a4206c224ebd5b848/src/ajax.js#L311-L318
1144
- // If url is an object, simulate pre-1.5 signature
1145
- if (typeof url === 'object') {
1146
- options = url;
1147
- url = undefined;
1148
- }
1149
-
1150
- // Force options to be an object
1151
- options = options || {};
1152
-
1153
- while(key = keys.pop()) {
1154
- if ($.isFunction(options[key])) {
1155
- options[key] = TraceKit.wrap(options[key]);
1156
- }
1157
- }
1158
-
1159
- try {
1160
- return _oldAjax.call(this, url, options);
1161
- } catch (e) {
1162
- TraceKit.report(e);
1163
- throw e;
1164
- }
1165
- };
1166
-
1167
- }(window.jQuery));
1168
-
1169
- //Default options:
1170
- if (!TraceKit.remoteFetching) {
1171
- TraceKit.remoteFetching = true;
1172
- }
1173
- if (!TraceKit.collectWindowErrors) {
1174
- TraceKit.collectWindowErrors = true;
1175
- }
1176
- if (!TraceKit.linesOfContext || TraceKit.linesOfContext < 1) {
1177
- // 5 lines before, the offending line, 5 lines after
1178
- TraceKit.linesOfContext = 11;
1179
- }
1180
-
1181
-
1182
-
1183
- // Export to global object
1184
- window.TraceKit = TraceKit;
1185
-
1186
- }(window));
1187
- ;(function(window, undefined){
1188
1088
  'use strict';
1189
1089
 
1190
1090
  // First, check for JSON support
1191
1091
  // If there is no JSON, we no-op the core features of Raven
1192
1092
  // since JSON is required to encode the payload
1193
1093
  var _Raven = window.Raven,
1194
- hasJSON = !isUndefined(window.JSON),
1094
+ hasJSON = !!(window.JSON && window.JSON.stringify),
1095
+ lastCapturedException,
1096
+ lastEventId,
1195
1097
  globalServer,
1196
1098
  globalUser,
1197
1099
  globalKey,
@@ -1199,13 +1101,14 @@ var _Raven = window.Raven,
1199
1101
  globalOptions = {
1200
1102
  logger: 'javascript',
1201
1103
  ignoreErrors: [],
1202
- ignoreUrls: []
1203
- };
1204
-
1205
- var TK = TraceKit.noConflict();
1206
-
1207
- // Disable Tracekit's remote fetching by default
1208
- TK.remoteFetching = false;
1104
+ ignoreUrls: [],
1105
+ whitelistUrls: [],
1106
+ includePaths: [],
1107
+ collectWindowErrors: true,
1108
+ tags: {},
1109
+ extra: {}
1110
+ },
1111
+ authQueryString;
1209
1112
 
1210
1113
  /*
1211
1114
  * The core Raven singleton
@@ -1213,7 +1116,7 @@ TK.remoteFetching = false;
1213
1116
  * @this {Raven}
1214
1117
  */
1215
1118
  var Raven = {
1216
- VERSION: '1.0.7',
1119
+ VERSION: '1.1.14',
1217
1120
 
1218
1121
  /*
1219
1122
  * Allow multiple versions of Raven to be installed.
@@ -1234,14 +1137,12 @@ var Raven = {
1234
1137
  * @return {Raven}
1235
1138
  */
1236
1139
  config: function(dsn, options) {
1237
- var uri = parseUri(dsn),
1140
+ if (!dsn) return Raven;
1141
+
1142
+ var uri = parseDSN(dsn),
1238
1143
  lastSlash = uri.path.lastIndexOf('/'),
1239
1144
  path = uri.path.substr(1, lastSlash);
1240
1145
 
1241
- if (options && options.ignoreErrors && window.console && console.warn) {
1242
- console.warn('DeprecationWarning: `ignoreErrors` is going to be removed soon.');
1243
- }
1244
-
1245
1146
  // merge in options
1246
1147
  if (options) {
1247
1148
  each(options, function(key, value){
@@ -1252,9 +1153,16 @@ var Raven = {
1252
1153
  // "Script error." is hard coded into browsers for errors that it can't read.
1253
1154
  // this is the result of a script being pulled in from an external domain and CORS.
1254
1155
  globalOptions.ignoreErrors.push('Script error.');
1156
+ globalOptions.ignoreErrors.push('Script error');
1157
+
1158
+ // join regexp rules into one big rule
1159
+ globalOptions.ignoreErrors = joinRegExp(globalOptions.ignoreErrors);
1160
+ globalOptions.ignoreUrls = globalOptions.ignoreUrls.length ? joinRegExp(globalOptions.ignoreUrls) : false;
1161
+ globalOptions.whitelistUrls = globalOptions.whitelistUrls.length ? joinRegExp(globalOptions.whitelistUrls) : false;
1162
+ globalOptions.includePaths = joinRegExp(globalOptions.includePaths);
1255
1163
 
1256
1164
  globalKey = uri.user;
1257
- globalProject = ~~uri.path.substr(lastSlash + 1);
1165
+ globalProject = uri.path.substr(lastSlash + 1);
1258
1166
 
1259
1167
  // assemble the endpoint from the uri pieces
1260
1168
  globalServer = '//' + uri.host +
@@ -1266,9 +1174,17 @@ var Raven = {
1266
1174
  }
1267
1175
 
1268
1176
  if (globalOptions.fetchContext) {
1269
- TK.remoteFetching = true;
1177
+ TraceKit.remoteFetching = true;
1270
1178
  }
1271
1179
 
1180
+ if (globalOptions.linesOfContext) {
1181
+ TraceKit.linesOfContext = globalOptions.linesOfContext;
1182
+ }
1183
+
1184
+ TraceKit.collectWindowErrors = !!globalOptions.collectWindowErrors;
1185
+
1186
+ setAuthQueryString();
1187
+
1272
1188
  // return for chaining
1273
1189
  return Raven;
1274
1190
  },
@@ -1282,9 +1198,9 @@ var Raven = {
1282
1198
  * @return {Raven}
1283
1199
  */
1284
1200
  install: function() {
1285
- if (!isSetup()) return;
1286
-
1287
- TK.report.subscribe(handleStackInfo);
1201
+ if (isSetup()) {
1202
+ TraceKit.report.subscribe(handleStackInfo);
1203
+ }
1288
1204
 
1289
1205
  return Raven;
1290
1206
  },
@@ -1304,7 +1220,7 @@ var Raven = {
1304
1220
  options = undefined;
1305
1221
  }
1306
1222
 
1307
- Raven.wrap(options, func).apply(this, args);
1223
+ return Raven.wrap(options, func).apply(this, args);
1308
1224
  },
1309
1225
 
1310
1226
  /*
@@ -1315,20 +1231,59 @@ var Raven = {
1315
1231
  * @return {function} The newly wrapped functions with a context
1316
1232
  */
1317
1233
  wrap: function(options, func) {
1234
+ // 1 argument has been passed, and it's not a function
1235
+ // so just return it
1236
+ if (isUndefined(func) && !isFunction(options)) {
1237
+ return options;
1238
+ }
1239
+
1318
1240
  // options is optional
1319
1241
  if (isFunction(options)) {
1320
1242
  func = options;
1321
1243
  options = undefined;
1322
1244
  }
1323
1245
 
1324
- return function() {
1246
+ // At this point, we've passed along 2 arguments, and the second one
1247
+ // is not a function either, so we'll just return the second argument.
1248
+ if (!isFunction(func)) {
1249
+ return func;
1250
+ }
1251
+
1252
+ // We don't wanna wrap it twice!
1253
+ if (func.__raven__) {
1254
+ return func;
1255
+ }
1256
+
1257
+ function wrapped() {
1258
+ var args = [], i = arguments.length,
1259
+ deep = !options || options && options.deep !== false;
1260
+ // Recursively wrap all of a function's arguments that are
1261
+ // functions themselves.
1262
+
1263
+ while(i--) args[i] = deep ? Raven.wrap(options, arguments[i]) : arguments[i];
1264
+
1325
1265
  try {
1326
- func.apply(this, arguments);
1266
+ /*jshint -W040*/
1267
+ return func.apply(this, args);
1327
1268
  } catch(e) {
1328
1269
  Raven.captureException(e, options);
1329
1270
  throw e;
1330
1271
  }
1331
- };
1272
+ }
1273
+
1274
+ // copy over properties of the old function
1275
+ for (var property in func) {
1276
+ if (func.hasOwnProperty(property)) {
1277
+ wrapped[property] = func[property];
1278
+ }
1279
+ }
1280
+
1281
+ // Signal that this function has been wrapped already
1282
+ // for both debugging and to prevent it to being wrapped twice
1283
+ wrapped.__raven__ = true;
1284
+ wrapped.__inner__ = func;
1285
+
1286
+ return wrapped;
1332
1287
  },
1333
1288
 
1334
1289
  /*
@@ -1337,7 +1292,7 @@ var Raven = {
1337
1292
  * @return {Raven}
1338
1293
  */
1339
1294
  uninstall: function() {
1340
- TK.report.unsubscribe(handleStackInfo);
1295
+ TraceKit.report.uninstall();
1341
1296
 
1342
1297
  return Raven;
1343
1298
  },
@@ -1351,9 +1306,10 @@ var Raven = {
1351
1306
  */
1352
1307
  captureException: function(ex, options) {
1353
1308
  // If a string is passed through, recall as a message
1354
- if (typeof ex === 'string') {
1355
- return Raven.captureMessage(ex, options);
1356
- }
1309
+ if (isString(ex)) return Raven.captureMessage(ex, options);
1310
+
1311
+ // Store the raw exception object for potential debugging and introspection
1312
+ lastCapturedException = ex;
1357
1313
 
1358
1314
  // TraceKit.report will re-raise any exception passed to it,
1359
1315
  // which means you have to wrap it in try/catch. Instead, we
@@ -1361,7 +1317,7 @@ var Raven = {
1361
1317
  // raises an exception different from the one we asked to
1362
1318
  // report on.
1363
1319
  try {
1364
- TK.report(ex, options);
1320
+ TraceKit.report(ex, options);
1365
1321
  } catch(ex1) {
1366
1322
  if(ex !== ex1) {
1367
1323
  throw ex1;
@@ -1381,7 +1337,7 @@ var Raven = {
1381
1337
  captureMessage: function(msg, options) {
1382
1338
  // Fire away!
1383
1339
  send(
1384
- arrayMerge({
1340
+ objectMerge({
1385
1341
  message: msg
1386
1342
  }, options)
1387
1343
  );
@@ -1399,21 +1355,84 @@ var Raven = {
1399
1355
  globalUser = user;
1400
1356
 
1401
1357
  return Raven;
1358
+ },
1359
+
1360
+ /*
1361
+ * Get the latest raw exception that was captured by Raven.
1362
+ *
1363
+ * @return {error}
1364
+ */
1365
+ lastException: function() {
1366
+ return lastCapturedException;
1367
+ },
1368
+
1369
+ /*
1370
+ * Get the last event id
1371
+ *
1372
+ * @return {string}
1373
+ */
1374
+ lastEventId: function() {
1375
+ return lastEventId;
1402
1376
  }
1403
1377
  };
1404
1378
 
1405
- var uriKeys = 'source protocol authority userInfo user password host port relative path directory file query anchor'.split(' '),
1406
- uriPattern = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
1379
+ function triggerEvent(eventType, options) {
1380
+ var event, key;
1381
+
1382
+ options = options || {};
1383
+
1384
+ eventType = 'raven' + eventType.substr(0,1).toUpperCase() + eventType.substr(1);
1385
+
1386
+ if (document.createEvent) {
1387
+ event = document.createEvent('HTMLEvents');
1388
+ event.initEvent(eventType, true, true);
1389
+ } else {
1390
+ event = document.createEventObject();
1391
+ event.eventType = eventType;
1392
+ }
1393
+
1394
+ for (key in options) if (options.hasOwnProperty(key)) {
1395
+ event[key] = options[key];
1396
+ }
1397
+
1398
+ if (document.createEvent) {
1399
+ // IE9 if standards
1400
+ document.dispatchEvent(event);
1401
+ } else {
1402
+ // IE8 regardless of Quirks or Standards
1403
+ // IE9 if quirks
1404
+ try {
1405
+ document.fireEvent('on' + event.eventType.toLowerCase(), event);
1406
+ } catch(e) {}
1407
+ }
1408
+ }
1409
+
1410
+ var dsnKeys = 'source protocol user pass host port path'.split(' '),
1411
+ dsnPattern = /^(?:(\w+):)?\/\/(\w+)(:\w+)?@([\w\.-]+)(?::(\d+))?(\/.*)/;
1412
+
1413
+ function RavenConfigError(message) {
1414
+ this.name = 'RavenConfigError';
1415
+ this.message = message;
1416
+ }
1417
+ RavenConfigError.prototype = new Error();
1418
+ RavenConfigError.prototype.constructor = RavenConfigError;
1407
1419
 
1408
1420
  /**** Private functions ****/
1409
- function parseUri(str) {
1410
- var m = uriPattern.exec(str),
1411
- uri = {},
1412
- i = 14;
1421
+ function parseDSN(str) {
1422
+ var m = dsnPattern.exec(str),
1423
+ dsn = {},
1424
+ i = 7;
1425
+
1426
+ try {
1427
+ while (i--) dsn[dsnKeys[i]] = m[i] || '';
1428
+ } catch(e) {
1429
+ throw new RavenConfigError('Invalid DSN: ' + str);
1430
+ }
1413
1431
 
1414
- while (i--) uri[uriKeys[i]] = m[i] || '';
1432
+ if (dsn.pass)
1433
+ throw new RavenConfigError('Do not specify your private key in the DSN!');
1415
1434
 
1416
- return uri;
1435
+ return dsn;
1417
1436
  }
1418
1437
 
1419
1438
  function isUndefined(what) {
@@ -1424,6 +1443,26 @@ function isFunction(what) {
1424
1443
  return typeof what === 'function';
1425
1444
  }
1426
1445
 
1446
+ function isString(what) {
1447
+ return typeof what === 'string';
1448
+ }
1449
+
1450
+ function isEmptyObject(what) {
1451
+ for (var k in what) return false;
1452
+ return true;
1453
+ }
1454
+
1455
+ /**
1456
+ * hasKey, a better form of hasOwnProperty
1457
+ * Example: hasKey(MainHostObject, property) === true/false
1458
+ *
1459
+ * @param {Object} host object to check property
1460
+ * @param {string} key to check
1461
+ */
1462
+ function hasKey(object, key) {
1463
+ return Object.prototype.hasOwnProperty.call(object, key);
1464
+ }
1465
+
1427
1466
  function each(obj, callback) {
1428
1467
  var i, j;
1429
1468
 
@@ -1434,43 +1473,41 @@ function each(obj, callback) {
1434
1473
  }
1435
1474
  }
1436
1475
  } else {
1437
- for (i = 0, j = obj.length; i < j; i++) {
1438
- callback.call(null, i, obj[i]);
1476
+ j = obj.length;
1477
+ if (j) {
1478
+ for (i = 0; i < j; i++) {
1479
+ callback.call(null, i, obj[i]);
1480
+ }
1439
1481
  }
1440
1482
  }
1441
1483
  }
1442
1484
 
1443
- var cachedAuth;
1444
-
1445
- function getAuthQueryString() {
1446
- if (cachedAuth) return cachedAuth;
1447
1485
 
1448
- var qs = [
1449
- 'sentry_version=2.0',
1450
- 'sentry_client=raven-js/' + Raven.VERSION
1451
- ];
1452
- if (globalKey) {
1453
- qs.push('sentry_key=' + globalKey);
1454
- }
1455
-
1456
- cachedAuth = '?' + qs.join('&');
1457
- return cachedAuth;
1486
+ function setAuthQueryString() {
1487
+ authQueryString =
1488
+ '?sentry_version=4' +
1489
+ '&sentry_client=raven-js/' + Raven.VERSION +
1490
+ '&sentry_key=' + globalKey;
1458
1491
  }
1459
1492
 
1493
+
1460
1494
  function handleStackInfo(stackInfo, options) {
1461
- var frames = [],
1462
- i = 0,
1463
- j, frame;
1495
+ var frames = [];
1464
1496
 
1465
- if (stackInfo.stack && (j = stackInfo.stack.length)) {
1466
- for (; i < j; i++) {
1467
- frame = normalizeFrame(stackInfo.stack[i]);
1497
+ if (stackInfo.stack && stackInfo.stack.length) {
1498
+ each(stackInfo.stack, function(i, stack) {
1499
+ var frame = normalizeFrame(stack);
1468
1500
  if (frame) {
1469
1501
  frames.push(frame);
1470
1502
  }
1471
- }
1503
+ });
1472
1504
  }
1473
1505
 
1506
+ triggerEvent('handle', {
1507
+ stackInfo: stackInfo,
1508
+ options: options
1509
+ });
1510
+
1474
1511
  processException(
1475
1512
  stackInfo.name,
1476
1513
  stackInfo.message,
@@ -1490,14 +1527,22 @@ function normalizeFrame(frame) {
1490
1527
  lineno: frame.line,
1491
1528
  colno: frame.column,
1492
1529
  'function': frame.func || '?'
1493
- }, context = extractContextFromFrame(frame);
1530
+ }, context = extractContextFromFrame(frame), i;
1494
1531
 
1495
1532
  if (context) {
1496
- var i = 3, keys = ['pre_context', 'context_line', 'post_context'];
1533
+ var keys = ['pre_context', 'context_line', 'post_context'];
1534
+ i = 3;
1497
1535
  while (i--) normalized[keys[i]] = context[i];
1498
1536
  }
1499
1537
 
1500
- normalized.in_app = !/(Raven|TraceKit)\./.test(normalized['function']);
1538
+ normalized.in_app = !( // determine if an exception came from outside of our app
1539
+ // first we check the global includePaths list.
1540
+ !globalOptions.includePaths.test(normalized.filename) ||
1541
+ // Now we check for fun, if the function name is Raven or TraceKit
1542
+ /(Raven|TraceKit)\./.test(normalized['function']) ||
1543
+ // finally, we do a last ditch effort and check for raven.min.js
1544
+ /raven\.(min\.)js$/.test(normalized.filename)
1545
+ );
1501
1546
 
1502
1547
  return normalized;
1503
1548
  }
@@ -1544,70 +1589,79 @@ function extractContextFromFrame(frame) {
1544
1589
  function processException(type, message, fileurl, lineno, frames, options) {
1545
1590
  var stacktrace, label, i;
1546
1591
 
1547
- // IE8 really doesn't have Array.prototype.indexOf
1548
- // Filter out a message that matches our ignore list
1549
- i = globalOptions.ignoreErrors.length;
1550
- while (i--) {
1551
- if (message === globalOptions.ignoreErrors[i]) {
1552
- return;
1553
- }
1554
- }
1592
+ // Sometimes an exception is getting logged in Sentry as
1593
+ // <no message value>
1594
+ // This can only mean that the message was falsey since this value
1595
+ // is hardcoded into Sentry itself.
1596
+ // At this point, if the message is falsey, we bail since it's useless
1597
+ if (type === 'Error' && !message) return;
1598
+
1599
+ if (globalOptions.ignoreErrors.test(message)) return;
1555
1600
 
1556
1601
  if (frames && frames.length) {
1602
+ fileurl = frames[0].filename || fileurl;
1603
+ // Sentry expects frames oldest to newest
1604
+ // and JS sends them as newest to oldest
1605
+ frames.reverse();
1557
1606
  stacktrace = {frames: frames};
1558
- fileurl = fileurl || frames[0].filename;
1559
1607
  } else if (fileurl) {
1560
1608
  stacktrace = {
1561
1609
  frames: [{
1562
1610
  filename: fileurl,
1563
- lineno: lineno
1611
+ lineno: lineno,
1612
+ in_app: true
1564
1613
  }]
1565
1614
  };
1566
1615
  }
1567
1616
 
1568
- i = globalOptions.ignoreUrls.length;
1569
- while (i--) {
1570
- if (globalOptions.ignoreUrls[i].test(fileurl)) {
1571
- return;
1572
- }
1573
- }
1617
+ // Truncate the message to a max of characters
1618
+ message = truncate(message, 100);
1619
+
1620
+ if (globalOptions.ignoreUrls && globalOptions.ignoreUrls.test(fileurl)) return;
1621
+ if (globalOptions.whitelistUrls && !globalOptions.whitelistUrls.test(fileurl)) return;
1574
1622
 
1575
1623
  label = lineno ? message + ' at ' + lineno : message;
1576
1624
 
1577
1625
  // Fire away!
1578
1626
  send(
1579
- arrayMerge({
1580
- 'sentry.interfaces.Exception': {
1627
+ objectMerge({
1628
+ // sentry.interfaces.Exception
1629
+ exception: {
1581
1630
  type: type,
1582
1631
  value: message
1583
1632
  },
1584
- 'sentry.interfaces.Stacktrace': stacktrace,
1633
+ // sentry.interfaces.Stacktrace
1634
+ stacktrace: stacktrace,
1585
1635
  culprit: fileurl,
1586
1636
  message: label
1587
1637
  }, options)
1588
1638
  );
1589
1639
  }
1590
1640
 
1591
- function arrayMerge(arr1, arr2) {
1592
- if (!arr2) {
1593
- return arr1;
1641
+ function objectMerge(obj1, obj2) {
1642
+ if (!obj2) {
1643
+ return obj1;
1594
1644
  }
1595
- each(arr2, function(key, value){
1596
- arr1[key] = value;
1645
+ each(obj2, function(key, value){
1646
+ obj1[key] = value;
1597
1647
  });
1598
- return arr1;
1648
+ return obj1;
1649
+ }
1650
+
1651
+ function truncate(str, max) {
1652
+ return str.length <= max ? str : str.substr(0, max) + '\u2026';
1599
1653
  }
1600
1654
 
1601
1655
  function getHttpData() {
1602
1656
  var http = {
1603
- url: window.location.href,
1657
+ url: document.location.href,
1604
1658
  headers: {
1605
1659
  'User-Agent': navigator.userAgent
1606
1660
  }
1607
1661
  };
1608
1662
 
1609
- if (window.document.referrer) {
1610
- http.headers.Referer = window.document.referrer;
1663
+ if (document.referrer) {
1664
+ http.headers.Referer = document.referrer;
1611
1665
  }
1612
1666
 
1613
1667
  return http;
@@ -1616,25 +1670,63 @@ function getHttpData() {
1616
1670
  function send(data) {
1617
1671
  if (!isSetup()) return;
1618
1672
 
1619
- data = arrayMerge({
1673
+ data = objectMerge({
1620
1674
  project: globalProject,
1621
1675
  logger: globalOptions.logger,
1622
1676
  site: globalOptions.site,
1623
1677
  platform: 'javascript',
1624
- 'sentry.interfaces.Http': getHttpData()
1678
+ // sentry.interfaces.Http
1679
+ request: getHttpData()
1625
1680
  }, data);
1626
1681
 
1627
- if (globalUser) data['sentry.interfaces.User'] = globalUser;
1682
+ // Merge in the tags and extra separately since objectMerge doesn't handle a deep merge
1683
+ data.tags = objectMerge(globalOptions.tags, data.tags);
1684
+ data.extra = objectMerge(globalOptions.extra, data.extra);
1685
+
1686
+ // If there are no tags/extra, strip the key from the payload alltogther.
1687
+ if (isEmptyObject(data.tags)) delete data.tags;
1688
+ if (isEmptyObject(data.extra)) delete data.extra;
1689
+
1690
+ if (globalUser) {
1691
+ // sentry.interfaces.User
1692
+ data.user = globalUser;
1693
+ }
1628
1694
 
1629
1695
  if (isFunction(globalOptions.dataCallback)) {
1630
1696
  data = globalOptions.dataCallback(data);
1631
1697
  }
1632
1698
 
1699
+ // Check if the request should be filtered or not
1700
+ if (isFunction(globalOptions.shouldSendCallback) && !globalOptions.shouldSendCallback(data)) {
1701
+ return;
1702
+ }
1703
+
1704
+ // Send along an event_id if not explicitly passed.
1705
+ // This event_id can be used to reference the error within Sentry itself.
1706
+ // Set lastEventId after we know the error should actually be sent
1707
+ lastEventId = data.event_id || (data.event_id = uuid4());
1708
+
1633
1709
  makeRequest(data);
1634
1710
  }
1635
1711
 
1712
+
1636
1713
  function makeRequest(data) {
1637
- new Image().src = globalServer + getAuthQueryString() + '&sentry_data=' + encodeURIComponent(JSON.stringify(data));
1714
+ var img = new Image(),
1715
+ src = globalServer + authQueryString + '&sentry_data=' + encodeURIComponent(JSON.stringify(data));
1716
+
1717
+ img.onload = function success() {
1718
+ triggerEvent('success', {
1719
+ data: data,
1720
+ src: src
1721
+ });
1722
+ };
1723
+ img.onerror = img.onabort = function failure() {
1724
+ triggerEvent('failure', {
1725
+ data: data,
1726
+ src: src
1727
+ });
1728
+ };
1729
+ img.src = src;
1638
1730
  }
1639
1731
 
1640
1732
  function isSetup() {
@@ -1648,12 +1740,86 @@ function isSetup() {
1648
1740
  return true;
1649
1741
  }
1650
1742
 
1743
+ function joinRegExp(patterns) {
1744
+ // Combine an array of regular expressions and strings into one large regexp
1745
+ // Be mad.
1746
+ var sources = [],
1747
+ i = 0, len = patterns.length,
1748
+ pattern;
1749
+
1750
+ for (; i < len; i++) {
1751
+ pattern = patterns[i];
1752
+ if (isString(pattern)) {
1753
+ // If it's a string, we need to escape it
1754
+ // Taken from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
1755
+ sources.push(pattern.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"));
1756
+ } else if (pattern && pattern.source) {
1757
+ // If it's a regexp already, we want to extract the source
1758
+ sources.push(pattern.source);
1759
+ }
1760
+ // Intentionally skip other cases
1761
+ }
1762
+ return new RegExp(sources.join('|'), 'i');
1763
+ }
1764
+
1765
+ // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
1766
+ function uuid4() {
1767
+ return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
1768
+ var r = Math.random()*16|0,
1769
+ v = c == 'x' ? r : (r&0x3|0x8);
1770
+ return v.toString(16);
1771
+ });
1772
+ }
1773
+
1774
+ function afterLoad() {
1775
+ // Attempt to initialize Raven on load
1776
+ var RavenConfig = window.RavenConfig;
1777
+ if (RavenConfig) {
1778
+ Raven.config(RavenConfig.dsn, RavenConfig.config).install();
1779
+ }
1780
+ }
1781
+ afterLoad();
1782
+
1651
1783
  // Expose Raven to the world
1652
1784
  window.Raven = Raven;
1653
1785
 
1654
1786
  // AMD
1655
1787
  if (typeof define === 'function' && define.amd) {
1656
- define(function() { return Raven; });
1788
+ define('raven', [], function() { return Raven; });
1657
1789
  }
1658
1790
 
1659
- })(window);
1791
+ })(this);
1792
+
1793
+ /**
1794
+ * native plugin
1795
+ *
1796
+ * Extends support for global error handling for asynchronous browser
1797
+ * functions. Adopted from Closure Library's errorhandler.js
1798
+ */
1799
+ ;(function extendToAsynchronousCallbacks(window, Raven) {
1800
+ "use strict";
1801
+
1802
+ var _helper = function _helper(fnName) {
1803
+ var originalFn = window[fnName];
1804
+ window[fnName] = function ravenAsyncExtension() {
1805
+ // Make a copy of the arguments
1806
+ var args = [].slice.call(arguments);
1807
+ var originalCallback = args[0];
1808
+ if (typeof (originalCallback) === 'function') {
1809
+ args[0] = Raven.wrap(originalCallback);
1810
+ }
1811
+ // IE < 9 doesn't support .call/.apply on setInterval/etTimeout, but it
1812
+ // also only supports 2 argument and doesn't care what this" is, so we
1813
+ // can just call the original function directly.
1814
+ if (originalFn.apply) {
1815
+ return originalFn.apply(this, args);
1816
+ } else {
1817
+ return originalFn(args[0], args[1]);
1818
+ }
1819
+ };
1820
+ };
1821
+
1822
+ _helper('setTimeout');
1823
+ _helper('setInterval');
1824
+
1825
+ }(this, Raven));