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.
- checksums.yaml +15 -0
- data/lib/ravenjs-gem/version.rb +1 -1
- data/vendor/assets/javascripts/1.1.14/raven.js +1825 -0
- data/vendor/assets/javascripts/raven.js +471 -305
- metadata +10 -23
- data/vendor/assets/javascripts/raven.min.js +0 -5
- data/vendor/assets/javascripts/raven.min.map +0 -1
@@ -1,54 +1,34 @@
|
|
1
|
-
/*! Raven.js 1.
|
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
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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,
|
129
|
+
function notifyHandlers(stack, isWindowError) {
|
140
130
|
var exception = null;
|
141
|
-
if (
|
131
|
+
if (isWindowError && !TraceKit.collectWindowErrors) {
|
142
132
|
return;
|
143
133
|
}
|
144
134
|
for (var i in handlers) {
|
145
|
-
if (
|
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
|
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
|
-
|
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
|
-
|
175
|
-
|
176
|
-
|
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
|
-
|
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
|
-
|
230
|
-
lastException = null;
|
231
|
-
notifyHandlers.apply(null, [stack, null].concat(args));
|
254
|
+
processLastException();
|
232
255
|
}
|
233
256
|
}, (stack.incomplete ? 2000 : 0));
|
234
257
|
|
235
|
-
|
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
|
-
|
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 (!
|
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 (!
|
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 (!
|
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 don
|
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|
|
622
|
-
gecko = /^\s*(\S*)(?:\((.*?)\))?@((?:file|
|
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|
|
766
|
-
lineRE2 = /^\s*Line (\d+) of inline#(\d+) script in ((?:file|
|
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 (
|
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 =
|
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
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
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.
|
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
|
-
|
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 =
|
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
|
-
|
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 (
|
1286
|
-
|
1287
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 (
|
1355
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1406
|
-
|
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
|
1410
|
-
var m =
|
1411
|
-
|
1412
|
-
i =
|
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
|
-
|
1432
|
+
if (dsn.pass)
|
1433
|
+
throw new RavenConfigError('Do not specify your private key in the DSN!');
|
1415
1434
|
|
1416
|
-
return
|
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
|
-
|
1438
|
-
|
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
|
-
|
1449
|
-
|
1450
|
-
'
|
1451
|
-
|
1452
|
-
|
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 &&
|
1466
|
-
|
1467
|
-
frame = normalizeFrame(
|
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
|
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 =
|
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
|
-
//
|
1548
|
-
//
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
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
|
-
|
1569
|
-
|
1570
|
-
|
1571
|
-
|
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
|
-
|
1580
|
-
|
1627
|
+
objectMerge({
|
1628
|
+
// sentry.interfaces.Exception
|
1629
|
+
exception: {
|
1581
1630
|
type: type,
|
1582
1631
|
value: message
|
1583
1632
|
},
|
1584
|
-
|
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
|
1592
|
-
if (!
|
1593
|
-
return
|
1641
|
+
function objectMerge(obj1, obj2) {
|
1642
|
+
if (!obj2) {
|
1643
|
+
return obj1;
|
1594
1644
|
}
|
1595
|
-
each(
|
1596
|
-
|
1645
|
+
each(obj2, function(key, value){
|
1646
|
+
obj1[key] = value;
|
1597
1647
|
});
|
1598
|
-
return
|
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:
|
1657
|
+
url: document.location.href,
|
1604
1658
|
headers: {
|
1605
1659
|
'User-Agent': navigator.userAgent
|
1606
1660
|
}
|
1607
1661
|
};
|
1608
1662
|
|
1609
|
-
if (
|
1610
|
-
http.headers.Referer =
|
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 =
|
1673
|
+
data = objectMerge({
|
1620
1674
|
project: globalProject,
|
1621
1675
|
logger: globalOptions.logger,
|
1622
1676
|
site: globalOptions.site,
|
1623
1677
|
platform: 'javascript',
|
1624
|
-
|
1678
|
+
// sentry.interfaces.Http
|
1679
|
+
request: getHttpData()
|
1625
1680
|
}, data);
|
1626
1681
|
|
1627
|
-
|
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
|
-
|
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
|
-
})(
|
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));
|