ravenjs-gem 1.0.7.0 → 1.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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));