History

Update Raven/Sentry

Thibaut committed 12 years ago

Commit bc95cfd1 parent 76763e62 files · +9 −1588Browse files

Showing the changes to assets/javascripts (2 of 2 files). Show all

Unified · Split

2 files
  1. assets/javascripts/app/app.coffee +6 −1
  2. assets/javascripts/vendor/raven.js +3 −1587
assets/javascripts/app/app.coffee+6−1
@@ -44,7 +44,12 @@ · 43 unmodified lines
4444 if @isInvalidLocation()
4545 new app.views.Notif 'InvalidLocation'
4646 else
47− Raven.config(@config.sentry_dsn).install() if @config.sentry_dsn
47+ if @config.sentry_dsn
48+ Raven.config @config.sentry_dsn,
49+ whitelistUrls: [/devdocs/]
50+ includePaths: [/devdocs/]
51+ ignoreErrors: [/dpQuery/]
52+ .install()
4853 @previousErrorHandler = onerror
4954 window.onerror = @onWindowError.bind(@)
5055 return
assets/javascripts/vendor/raven.js+3−1587
@@ -1,1587 +1,3 @@
1−/*! Raven.js 1.0.8 | github.com/getsentry/raven-js */
2−
3−/*
4− * Includes TraceKit
5− * https://github.com/getsentry/TraceKit
6− *
7− * Copyright 2013 Matt Robenolt and other contributors
8− * Released under the BSD license
9− * https://github.com/getsentry/raven-js/blob/master/LICENSE
10− *
11− */
12−/*
13− TraceKit - Cross brower stack traces - github.com/occ/TraceKit
14− MIT license
15−*/
16−
17−;(function(window, undefined) {
18−
19−
20−var TraceKit = {};
21−var _oldTraceKit = window.TraceKit;
22−
23−// global reference to slice
24−var _slice = [].slice;
25−var UNKNOWN_FUNCTION = '?';
26−
27−
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−/**
53− * TraceKit.wrap: Wrap any function in a TraceKit reporter
54− * Example: func = TraceKit.wrap(func);
55− *
56− * @param {Function} func Function to be wrapped
57− * @return {Function} The wrapped func
58− */
59−TraceKit.wrap = function traceKitWrapper(func) {
60− function wrapped() {
61− try {
62− return func.apply(this, arguments);
63− } catch (e) {
64− TraceKit.report(e);
65− throw e;
66− }
67− }
68− return wrapped;
69−};
70−
71−/**
72− * TraceKit.report: cross-browser processing of unhandled exceptions
73− *
74− * Syntax:
75− * TraceKit.report.subscribe(function(stackInfo) { ... })
76− * TraceKit.report.unsubscribe(function(stackInfo) { ... })
77− * TraceKit.report(exception)
78− * try { ...code... } catch(ex) { TraceKit.report(ex); }
79− *
80− * Supports:
81− * - Firefox: full stack trace with line numbers, plus column number
82− * on top frame; column number is not guaranteed
83− * - Opera: full stack trace with line and column numbers
84− * - Chrome: full stack trace with line and column numbers
85− * - Safari: line and column number for the top frame only; some frames
86− * may be missing, and column number is not guaranteed
87− * - IE: line and column number for the top frame only; some frames
88− * may be missing, and column number is not guaranteed
89− *
90− * In theory, TraceKit should work on all of the following versions:
91− * - IE5.5+ (only 8.0 tested)
92− * - Firefox 0.9+ (only 3.5+ tested)
93− * - Opera 7+ (only 10.50 tested; versions 9 and earlier may require
94− * Exceptions Have Stacktrace to be enabled in opera:config)
95− * - Safari 3+ (only 4+ tested)
96− * - Chrome 1+ (only 5+ tested)
97− * - Konqueror 3.5+ (untested)
98− *
99− * Requires TraceKit.computeStackTrace.
100− *
101− * Tries to catch all unhandled exceptions and report them to the
102− * subscribed handlers. Please note that TraceKit.report will rethrow the
103− * exception. This is REQUIRED in order to get a useful stack trace in IE.
104− * If the exception does not reach the top of the browser, you will only
105− * get a stack trace from the point where TraceKit.report was called.
106− *
107− * Handlers receive a stackInfo object as described in the
108− * TraceKit.computeStackTrace docs.
109− */
110−TraceKit.report = (function reportModuleWrapper() {
111− var handlers = [],
112− lastException = null,
113− lastExceptionStack = null;
114−
115− /**
116− * Add a crash handler.
117− * @param {Function} handler
118− */
119− function subscribe(handler) {
120− handlers.push(handler);
121− }
122−
123− /**
124− * Remove a crash handler.
125− * @param {Function} handler
126− */
127− function unsubscribe(handler) {
128− for (var i = handlers.length - 1; i >= 0; --i) {
129− if (handlers[i] === handler) {
130− handlers.splice(i, 1);
131− }
132− }
133− }
134−
135− /**
136− * Dispatch stack information to all handlers.
137− * @param {Object.<string, *>} stack
138− */
139− function notifyHandlers(stack, windowError) {
140− var exception = null;
141− if (windowError && !TraceKit.collectWindowErrors) {
142− return;
143− }
144− for (var i in handlers) {
145− if (_has(handlers, i)) {
146− try {
147− handlers[i].apply(null, [stack].concat(_slice.call(arguments, 2)));
148− } catch (inner) {
149− exception = inner;
150− }
151− }
152− }
153−
154− if (exception) {
155− throw exception;
156− }
157− }
158−
159− var _oldOnerrorHandler = window.onerror;
160−
161− /**
162− * Ensures all global unhandled exceptions are recorded.
163− * Supported by Gecko and IE.
164− * @param {string} message Error message.
165− * @param {string} url URL of script that generated the exception.
166− * @param {(number|string)} lineNo The line number at which the error
167− * occurred.
168− */
169− window.onerror = function traceKitWindowOnError(message, url, lineNo) {
170− var stack = null;
171−
172− if (lastExceptionStack) {
173− TraceKit.computeStackTrace.augmentStackTraceWithInitialElement(lastExceptionStack, url, lineNo, message);
174− stack = lastExceptionStack;
175− lastExceptionStack = null;
176− lastException = null;
177− } else {
178− var location = {
179− 'url': url,
180− 'line': lineNo
181− };
182− location.func = TraceKit.computeStackTrace.guessFunctionName(location.url, location.line);
183− location.context = TraceKit.computeStackTrace.gatherContext(location.url, location.line);
184− stack = {
185− 'mode': 'onerror',
186− 'message': message,
187− 'url': document.location.href,
188− 'stack': [location],
189− 'useragent': navigator.userAgent
190− };
191− }
192−
193− notifyHandlers(stack, 'from window.onerror');
194−
195− if (_oldOnerrorHandler) {
196− return _oldOnerrorHandler.apply(this, arguments);
197− }
198−
199− return false;
200− };
201−
202− /**
203− * Reports an unhandled Error to TraceKit.
204− * @param {Error} ex
205− */
206− function report(ex) {
207− var args = _slice.call(arguments, 1);
208− if (lastExceptionStack) {
209− if (lastException === ex) {
210− return; // already caught by an inner catch block, ignore
211− } else {
212− var s = lastExceptionStack;
213− lastExceptionStack = null;
214− lastException = null;
215− notifyHandlers.apply(null, [s, null].concat(args));
216− }
217− }
218−
219− var stack = TraceKit.computeStackTrace(ex);
220− lastExceptionStack = stack;
221− lastException = ex;
222−
223− // If the stack trace is incomplete, wait for 2 seconds for
224− // slow slow IE to see if onerror occurs or not before reporting
225− // this exception; otherwise, we will end up with an incomplete
226− // stack trace
227− window.setTimeout(function () {
228− if (lastException === ex) {
229− lastExceptionStack = null;
230− lastException = null;
231− notifyHandlers.apply(null, [stack, null].concat(args));
232− }
233− }, (stack.incomplete ? 2000 : 0));
234−
235− throw ex; // re-throw to propagate to the top level (and cause window.onerror)
236− }
237−
238− report.subscribe = subscribe;
239− report.unsubscribe = unsubscribe;
240− return report;
241−}());
242−
243−/**
244− * TraceKit.computeStackTrace: cross-browser stack traces in JavaScript
245− *
246− * Syntax:
247− * s = TraceKit.computeStackTrace.ofCaller([depth])
248− * s = TraceKit.computeStackTrace(exception) // consider using TraceKit.report instead (see below)
249− * Returns:
250− * s.name - exception name
251− * s.message - exception message
252− * s.stack[i].url - JavaScript or HTML file URL
253− * s.stack[i].func - function name, or empty for anonymous functions (if guessing did not work)
254− * s.stack[i].args - arguments passed to the function, if known
255− * s.stack[i].line - line number, if known
256− * s.stack[i].column - column number, if known
257− * 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− *
260− * Supports:
261− * - Firefox: full stack trace with line numbers and unreliable column
262− * number on top frame
263− * - Opera 10: full stack trace with line and column numbers
264− * - Opera 9-: full stack trace with line numbers
265− * - Chrome: full stack trace with line and column numbers
266− * - Safari: line and column number for the topmost stacktrace element
267− * only
268− * - IE: no line numbers whatsoever
269− *
270− * Tries to guess names of anonymous functions by looking for assignments
271− * in the source code. In IE and Safari, we have to guess source file names
272− * by searching for function bodies inside all page scripts. This will not
273− * work for scripts that are loaded cross-domain.
274− * Here be dragons: some function names may be guessed incorrectly, and
275− * duplicate functions may be mismatched.
276− *
277− * TraceKit.computeStackTrace should only be used for tracing purposes.
278− * Logging of unhandled exceptions should be done with TraceKit.report,
279− * which builds on top of TraceKit.computeStackTrace and provides better
280− * IE support by utilizing the window.onerror event to retrieve information
281− * about the top of the stack.
282− *
283− * Note: In IE and Safari, no stack trace is recorded on the Error object,
284− * so computeStackTrace instead walks its *own* chain of callers.
285− * This means that:
286− * * in Safari, some methods may be missing from the stack trace;
287− * * in IE, the topmost function in the stack trace will always be the
288− * caller of computeStackTrace.
289− *
290− * This is okay for tracing (because you are likely to be calling
291− * computeStackTrace from the function you want to be the topmost element
292− * of the stack trace anyway), but not okay for logging unhandled
293− * exceptions (because your catch block will likely be far away from the
294− * inner function that actually caused the exception).
295− *
296− * Tracing example:
297− * function trace(message) {
298− * var stackInfo = TraceKit.computeStackTrace.ofCaller();
299− * var data = message + "\n";
300− * for(var i in stackInfo.stack) {
301− * var item = stackInfo.stack[i];
302− * data += (item.func || '[anonymous]') + "() in " + item.url + ":" + (item.line || '0') + "\n";
303− * }
304− * if (window.console)
305− * console.info(data);
306− * else
307− * alert(data);
308− * }
309− */
310−TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
311− var debug = false,
312− sourceCache = {};
313−
314− /**
315− * Attempts to retrieve source code via XMLHttpRequest, which is used
316− * to look up anonymous function names.
317− * @param {string} url URL of source code.
318− * @return {string} Source contents.
319− */
320− function loadSource(url) {
321− if (!TraceKit.remoteFetching) { //Only attempt request if remoteFetching is on.
322− return '';
323− }
324− try {
325− function getXHR() {
326− try {
327− return new window.XMLHttpRequest();
328− } catch (e) {
329− // explicitly bubble up the exception if not found
330− return new window.ActiveXObject('Microsoft.XMLHTTP');
331− }
332− }
333−
334− var request = getXHR();
335− request.open('GET', url, false);
336− request.send('');
337− return request.responseText;
338− } catch (e) {
339− return '';
340− }
341− }
342−
343− /**
344− * Retrieves source code from the source code cache.
345− * @param {string} url URL of source code.
346− * @return {Array.<string>} Source contents.
347− */
348− function getSource(url) {
349− if (!_has(sourceCache, url)) {
350− // URL needs to be able to fetched within the acceptable domain. Otherwise,
351− // cross-domain errors will be triggered.
352− var source = '';
353− if (url.indexOf(document.domain) !== -1) {
354− source = loadSource(url);
355− }
356− sourceCache[url] = source ? source.split('\n') : [];
357− }
358−
359− return sourceCache[url];
360− }
361−
362− /**
363− * Tries to use an externally loaded copy of source code to determine
364− * the name of a function by looking at the name of the variable it was
365− * assigned to, if any.
366− * @param {string} url URL of source code.
367− * @param {(string|number)} lineNo Line number in source code.
368− * @return {string} The function name, if discoverable.
369− */
370− function guessFunctionName(url, lineNo) {
371− var reFunctionArgNames = /function ([^(]*)\(([^)]*)\)/,
372− reGuessFunction = /['"]?([0-9A-Za-z$_]+)['"]?\s*[:=]\s*(function|eval|new Function)/,
373− line = '',
374− maxLines = 10,
375− source = getSource(url),
376− m;
377−
378− if (!source.length) {
379− return UNKNOWN_FUNCTION;
380− }
381−
382− // Walk backwards from the first line in the function until we find the line which
383− // matches the pattern above, which is the function definition
384− for (var i = 0; i < maxLines; ++i) {
385− line = source[lineNo - i] + line;
386−
387− if (!_isUndefined(line)) {
388− if ((m = reGuessFunction.exec(line))) {
389− return m[1];
390− } else if ((m = reFunctionArgNames.exec(line))) {
391− return m[1];
392− }
393− }
394− }
395−
396− return UNKNOWN_FUNCTION;
397− }
398−
399− /**
400− * Retrieves the surrounding lines from where an exception occurred.
401− * @param {string} url URL of source code.
402− * @param {(string|number)} line Line number in source code to centre
403− * around for context.
404− * @return {?Array.<string>} Lines of source code.
405− */
406− function gatherContext(url, line) {
407− var source = getSource(url);
408−
409− if (!source.length) {
410− return null;
411− }
412−
413− var context = [],
414− // linesBefore & linesAfter are inclusive with the offending line.
415− // if linesOfContext is even, there will be one extra line
416− // *before* the offending line.
417− linesBefore = Math.floor(TraceKit.linesOfContext / 2),
418− // Add one extra line if linesOfContext is odd
419− linesAfter = linesBefore + (TraceKit.linesOfContext % 2),
420− start = Math.max(0, line - linesBefore - 1),
421− end = Math.min(source.length, line + linesAfter - 1);
422−
423− line -= 1; // convert to 0-based index
424−
425− for (var i = start; i < end; ++i) {
426− if (!_isUndefined(source[i])) {
427− context.push(source[i]);
428− }
429− }
430−
431− return context.length > 0 ? context : null;
432− }
433−
434− /**
435− * Escapes special characters, except for whitespace, in a string to be
436− * used inside a regular expression as a string literal.
437− * @param {string} text The string.
438− * @return {string} The escaped string literal.
439− */
440− function escapeRegExp(text) {
441− return text.replace(/[\-\[\]{}()*+?.,\\\^$|#]/g, '\\$&');
442− }
443−
444− /**
445− * Escapes special characters in a string to be used inside a regular
446− * expression as a string literal. Also ensures that HTML entities will
447− * be matched the same as their literal friends.
448− * @param {string} body The string.
449− * @return {string} The escaped string.
450− */
451− function escapeCodeAsRegExpForMatchingInsideHTML(body) {
452− return escapeRegExp(body).replace('<', '(?:<|&lt;)').replace('>', '(?:>|&gt;)').replace('&', '(?:&|&amp;)').replace('"', '(?:"|&quot;)').replace(/\s+/g, '\\s+');
453− }
454−
455− /**
456− * Determines where a code fragment occurs in the source code.
457− * @param {RegExp} re The function definition.
458− * @param {Array.<string>} urls A list of URLs to search.
459− * @return {?Object.<string, (string|number)>} An object containing
460− * the url, line, and column number of the defined function.
461− */
462− function findSourceInUrls(re, urls) {
463− var source, m;
464− for (var i = 0, j = urls.length; i < j; ++i) {
465− // console.log('searching', urls[i]);
466− if ((source = getSource(urls[i])).length) {
467− source = source.join('\n');
468− if ((m = re.exec(source))) {
469− // console.log('Found function in ' + urls[i]);
470−
471− return {
472− 'url': urls[i],
473− 'line': source.substring(0, m.index).split('\n').length,
474− 'column': m.index - source.lastIndexOf('\n', m.index) - 1
475− };
476− }
477− }
478− }
479−
480− // console.log('no match');
481−
482− return null;
483− }
484−
485− /**
486− * Determines at which column a code fragment occurs on a line of the
487− * source code.
488− * @param {string} fragment The code fragment.
489− * @param {string} url The URL to search.
490− * @param {(string|number)} line The line number to examine.
491− * @return {?number} The column number.
492− */
493− function findSourceInLine(fragment, url, line) {
494− var source = getSource(url),
495− re = new RegExp('\\b' + escapeRegExp(fragment) + '\\b'),
496− m;
497−
498− line -= 1;
499−
500− if (source && source.length > line && (m = re.exec(source[line]))) {
501− return m.index;
502− }
503−
504− return null;
505− }
506−
507− /**
508− * Determines where a function was defined within the source code.
509− * @param {(Function|string)} func A function reference or serialized
510− * function definition.
511− * @return {?Object.<string, (string|number)>} An object containing
512− * the url, line, and column number of the defined function.
513− */
514− function findSourceByFunctionBody(func) {
515− var urls = [window.location.href],
516− scripts = document.getElementsByTagName('script'),
517− body,
518− code = '' + func,
519− codeRE = /^function(?:\s+([\w$]+))?\s*\(([\w\s,]*)\)\s*\{\s*(\S[\s\S]*\S)\s*\}\s*$/,
520− eventRE = /^function on([\w$]+)\s*\(event\)\s*\{\s*(\S[\s\S]*\S)\s*\}\s*$/,
521− re,
522− parts,
523− result;
524−
525− for (var i = 0; i < scripts.length; ++i) {
526− var script = scripts[i];
527− if (script.src) {
528− urls.push(script.src);
529− }
530− }
531−
532− if (!(parts = codeRE.exec(code))) {
533− re = new RegExp(escapeRegExp(code).replace(/\s+/g, '\\s+'));
534− }
535−
536− // not sure if this is really necessary, but I don’t have a test
537− // corpus large enough to confirm that and it was in the original.
538− else {
539− var name = parts[1] ? '\\s+' + parts[1] : '',
540− args = parts[2].split(',').join('\\s*,\\s*');
541−
542− body = escapeRegExp(parts[3]).replace(/;$/, ';?'); // semicolon is inserted if the function ends with a comment.replace(/\s+/g, '\\s+');
543− re = new RegExp('function' + name + '\\s*\\(\\s*' + args + '\\s*\\)\\s*{\\s*' + body + '\\s*}');
544− }
545−
546− // look for a normal function definition
547− if ((result = findSourceInUrls(re, urls))) {
548− return result;
549− }
550−
551− // look for an old-school event handler function
552− if ((parts = eventRE.exec(code))) {
553− var event = parts[1];
554− body = escapeCodeAsRegExpForMatchingInsideHTML(parts[2]);
555−
556− // look for a function defined in HTML as an onXXX handler
557− re = new RegExp('on' + event + '=[\\\'"]\\s*' + body + '\\s*[\\\'"]', 'i');
558−
559− if ((result = findSourceInUrls(re, urls[0]))) {
560− return result;
561− }
562−
563− // look for ???
564− re = new RegExp(body);
565−
566− if ((result = findSourceInUrls(re, urls))) {
567− return result;
568− }
569− }
570−
571− return null;
572− }
573−
574− // Contents of Exception in various browsers.
575− //
576− // SAFARI:
577− // ex.message = Can't find variable: qq
578− // ex.line = 59
579− // ex.sourceId = 580238192
580− // ex.sourceURL = http://...
581− // ex.expressionBeginOffset = 96
582− // ex.expressionCaretOffset = 98
583− // ex.expressionEndOffset = 98
584− // ex.name = ReferenceError
585− //
586− // FIREFOX:
587− // ex.message = qq is not defined
588− // ex.fileName = http://...
589− // ex.lineNumber = 59
590− // ex.stack = ...stack trace... (see the example below)
591− // ex.name = ReferenceError
592− //
593− // CHROME:
594− // ex.message = qq is not defined
595− // ex.name = ReferenceError
596− // ex.type = not_defined
597− // ex.arguments = ['aa']
598− // ex.stack = ...stack trace...
599− //
600− // INTERNET EXPLORER:
601− // ex.message = ...
602− // ex.name = ReferenceError
603− //
604− // OPERA:
605− // ex.message = ...message... (see the example below)
606− // ex.name = ReferenceError
607− // ex.opera#sourceloc = 11 (pretty much useless, duplicates the info in ex.message)
608− // ex.stacktrace = n/a; see 'opera:config#UserPrefs|Exceptions Have Stacktrace'
609−
610− /**
611− * Computes stack trace information from the stack property.
612− * Chrome and Gecko use this property.
613− * @param {Error} ex
614− * @return {?Object.<string, *>} Stack trace information.
615− */
616− function computeStackTraceFromStackProp(ex) {
617− if (!ex.stack) {
618− return null;
619− }
620−
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,
623− lines = ex.stack.split('\n'),
624− stack = [],
625− parts,
626− element,
627− reference = /^(.*) is undefined$/.exec(ex.message);
628−
629− for (var i = 0, j = lines.length; i < j; ++i) {
630− if ((parts = gecko.exec(lines[i]))) {
631− element = {
632− 'url': parts[3],
633− 'func': parts[1] || UNKNOWN_FUNCTION,
634− 'args': parts[2] ? parts[2].split(',') : '',
635− 'line': +parts[4],
636− 'column': parts[5] ? +parts[5] : null
637− };
638− } else if ((parts = chrome.exec(lines[i]))) {
639− element = {
640− 'url': parts[2],
641− 'func': parts[1] || UNKNOWN_FUNCTION,
642− 'line': +parts[3],
643− 'column': parts[4] ? +parts[4] : null
644− };
645− } else {
646− continue;
647− }
648−
649− if (!element.func && element.line) {
650− element.func = guessFunctionName(element.url, element.line);
651− }
652−
653− if (element.line) {
654− element.context = gatherContext(element.url, element.line);
655− }
656−
657− stack.push(element);
658− }
659−
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− if (!stack.length) {
665− return null;
666− }
667−
668− return {
669− 'mode': 'stack',
670− 'name': ex.name,
671− 'message': ex.message,
672− 'url': document.location.href,
673− 'stack': stack,
674− 'useragent': navigator.userAgent
675− };
676− }
677−
678− /**
679− * Computes stack trace information from the stacktrace property.
680− * Opera 10 uses this property.
681− * @param {Error} ex
682− * @return {?Object.<string, *>} Stack trace information.
683− */
684− function computeStackTraceFromStacktraceProp(ex) {
685− // Access and store the stacktrace property before doing ANYTHING
686− // else to it because Opera is not very good at providing it
687− // reliably in other circumstances.
688− var stacktrace = ex.stacktrace;
689−
690− var testRE = / line (\d+), column (\d+) in (?:<anonymous function: ([^>]+)>|([^\)]+))\((.*)\) in (.*):\s*$/i,
691− lines = stacktrace.split('\n'),
692− stack = [],
693− parts;
694−
695− for (var i = 0, j = lines.length; i < j; i += 2) {
696− if ((parts = testRE.exec(lines[i]))) {
697− var element = {
698− 'line': +parts[1],
699− 'column': +parts[2],
700− 'func': parts[3] || parts[4],
701− 'args': parts[5] ? parts[5].split(',') : [],
702− 'url': parts[6]
703− };
704−
705− if (!element.func && element.line) {
706− element.func = guessFunctionName(element.url, element.line);
707− }
708− if (element.line) {
709− try {
710− element.context = gatherContext(element.url, element.line);
711− } catch (exc) {}
712− }
713−
714− if (!element.context) {
715− element.context = [lines[i + 1]];
716− }
717−
718− stack.push(element);
719− }
720− }
721−
722− if (!stack.length) {
723− return null;
724− }
725−
726− return {
727− 'mode': 'stacktrace',
728− 'name': ex.name,
729− 'message': ex.message,
730− 'url': document.location.href,
731− 'stack': stack,
732− 'useragent': navigator.userAgent
733− };
734− }
735−
736− /**
737− * NOT TESTED.
738− * Computes stack trace information from an error message that includes
739− * the stack trace.
740− * Opera 9 and earlier use this method if the option to show stack
741− * traces is turned on in opera:config.
742− * @param {Error} ex
743− * @return {?Object.<string, *>} Stack information.
744− */
745− function computeStackTraceFromOperaMultiLineMessage(ex) {
746− // Opera includes a stack trace into the exception message. An example is:
747− //
748− // Statement on line 3: Undefined variable: undefinedFunc
749− // Backtrace:
750− // Line 3 of linked script file://localhost/Users/andreyvit/Projects/TraceKit/javascript-client/sample.js: In function zzz
751− // undefinedFunc(a);
752− // Line 7 of inline#1 script in file://localhost/Users/andreyvit/Projects/TraceKit/javascript-client/sample.html: In function yyy
753− // zzz(x, y, z);
754− // Line 3 of inline#1 script in file://localhost/Users/andreyvit/Projects/TraceKit/javascript-client/sample.html: In function xxx
755− // yyy(a, a, a);
756− // Line 1 of function script
757− // try { xxx('hi'); return false; } catch(ex) { TraceKit.report(ex); }
758− // ...
759−
760− var lines = ex.message.split('\n');
761− if (lines.length < 4) {
762− return null;
763− }
764−
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,
767− lineRE3 = /^\s*Line (\d+) of function script\s*$/i,
768− stack = [],
769− scripts = document.getElementsByTagName('script'),
770− inlineScriptBlocks = [],
771− parts,
772− i,
773− len,
774− source;
775−
776− for (i in scripts) {
777− if (_has(scripts, i) && !scripts[i].src) {
778− inlineScriptBlocks.push(scripts[i]);
779− }
780− }
781−
782− for (i = 2, len = lines.length; i < len; i += 2) {
783− var item = null;
784− if ((parts = lineRE1.exec(lines[i]))) {
785− item = {
786− 'url': parts[2],
787− 'func': parts[3],
788− 'line': +parts[1]
789− };
790− } else if ((parts = lineRE2.exec(lines[i]))) {
791− item = {
792− 'url': parts[3],
793− 'func': parts[4]
794− };
795− var relativeLine = (+parts[1]); // relative to the start of the <SCRIPT> block
796− var script = inlineScriptBlocks[parts[2] - 1];
797− if (script) {
798− source = getSource(item.url);
799− if (source) {
800− source = source.join('\n');
801− var pos = source.indexOf(script.innerText);
802− if (pos >= 0) {
803− item.line = relativeLine + source.substring(0, pos).split('\n').length;
804− }
805− }
806− }
807− } else if ((parts = lineRE3.exec(lines[i]))) {
808− var url = window.location.href.replace(/#.*$/, ''),
809− line = parts[1];
810− var re = new RegExp(escapeCodeAsRegExpForMatchingInsideHTML(lines[i + 1]));
811− source = findSourceInUrls(re, [url]);
812− item = {
813− 'url': url,
814− 'line': source ? source.line : line,
815− 'func': ''
816− };
817− }
818−
819− if (item) {
820− if (!item.func) {
821− item.func = guessFunctionName(item.url, item.line);
822− }
823− var context = gatherContext(item.url, item.line);
824− var midline = (context ? context[Math.floor(context.length / 2)] : null);
825− if (context && midline.replace(/^\s*/, '') === lines[i + 1].replace(/^\s*/, '')) {
826− item.context = context;
827− } else {
828− // if (context) alert("Context mismatch. Correct midline:\n" + lines[i+1] + "\n\nMidline:\n" + midline + "\n\nContext:\n" + context.join("\n") + "\n\nURL:\n" + item.url);
829− item.context = [lines[i + 1]];
830− }
831− stack.push(item);
832− }
833− }
834− if (!stack.length) {
835− return null; // could not parse multiline exception message as Opera stack trace
836− }
837−
838− return {
839− 'mode': 'multiline',
840− 'name': ex.name,
841− 'message': lines[0],
842− 'url': document.location.href,
843− 'stack': stack,
844− 'useragent': navigator.userAgent
845− };
846− }
847−
848− /**
849− * Adds information about the first frame to incomplete stack traces.
850− * Safari and IE require this to get complete data on the first frame.
851− * @param {Object.<string, *>} stackInfo Stack trace information from
852− * one of the compute* methods.
853− * @param {string} url The URL of the script that caused an error.
854− * @param {(number|string)} lineNo The line number of the script that
855− * caused an error.
856− * @param {string=} message The error generated by the browser, which
857− * hopefully contains the name of the object that caused the error.
858− * @return {boolean} Whether or not the stack information was
859− * augmented.
860− */
861− function augmentStackTraceWithInitialElement(stackInfo, url, lineNo, message) {
862− var initial = {
863− 'url': url,
864− 'line': lineNo
865− };
866−
867− if (initial.url && initial.line) {
868− stackInfo.incomplete = false;
869−
870− if (!initial.func) {
871− initial.func = guessFunctionName(initial.url, initial.line);
872− }
873−
874− if (!initial.context) {
875− initial.context = gatherContext(initial.url, initial.line);
876− }
877−
878− var reference = / '([^']+)' /.exec(message);
879− if (reference) {
880− initial.column = findSourceInLine(reference[1], initial.url, initial.line);
881− }
882−
883− if (stackInfo.stack.length > 0) {
884− if (stackInfo.stack[0].url === initial.url) {
885− if (stackInfo.stack[0].line === initial.line) {
886− return false; // already in stack trace
887− } else if (!stackInfo.stack[0].line && stackInfo.stack[0].func === initial.func) {
888− stackInfo.stack[0].line = initial.line;
889− stackInfo.stack[0].context = initial.context;
890− return false;
891− }
892− }
893− }
894−
895− stackInfo.stack.unshift(initial);
896− stackInfo.partial = true;
897− return true;
898− } else {
899− stackInfo.incomplete = true;
900− }
901−
902− return false;
903− }
904−
905− /**
906− * Computes stack trace information by walking the arguments.caller
907− * chain at the time the exception occurred. This will cause earlier
908− * frames to be missed but is the only way to get any stack trace in
909− * Safari and IE. The top frame is restored by
910− * {@link augmentStackTraceWithInitialElement}.
911− * @param {Error} ex
912− * @return {?Object.<string, *>} Stack trace information.
913− */
914− function computeStackTraceByWalkingCallerChain(ex, depth) {
915− var functionName = /function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,
916− stack = [],
917− funcs = {},
918− recursion = false,
919− parts,
920− item,
921− source;
922−
923− for (var curr = computeStackTraceByWalkingCallerChain.caller; curr && !recursion; curr = curr.caller) {
924− if (curr === computeStackTrace || curr === TraceKit.report) {
925− // console.log('skipping internal function');
926− continue;
927− }
928−
929− item = {
930− 'url': null,
931− 'func': UNKNOWN_FUNCTION,
932− 'line': null,
933− 'column': null
934− };
935−
936− if (curr.name) {
937− item.func = curr.name;
938− } else if ((parts = functionName.exec(curr.toString()))) {
939− item.func = parts[1];
940− }
941−
942− if ((source = findSourceByFunctionBody(curr))) {
943− item.url = source.url;
944− item.line = source.line;
945−
946− if (item.func === UNKNOWN_FUNCTION) {
947− item.func = guessFunctionName(item.url, item.line);
948− }
949−
950− var reference = / '([^']+)' /.exec(ex.message || ex.description);
951− if (reference) {
952− item.column = findSourceInLine(reference[1], source.url, source.line);
953− }
954− }
955−
956− if (funcs['' + curr]) {
957− recursion = true;
958− }else{
959− funcs['' + curr] = true;
960− }
961−
962− stack.push(item);
963− }
964−
965− if (depth) {
966− // console.log('depth is ' + depth);
967− // console.log('stack is ' + stack.length);
968− stack.splice(0, depth);
969− }
970−
971− var result = {
972− 'mode': 'callers',
973− 'name': ex.name,
974− 'message': ex.message,
975− 'url': document.location.href,
976− 'stack': stack,
977− 'useragent': navigator.userAgent
978− };
979− augmentStackTraceWithInitialElement(result, ex.sourceURL || ex.fileName, ex.line || ex.lineNumber, ex.message || ex.description);
980− return result;
981− }
982−
983− /**
984− * Computes a stack trace for an exception.
985− * @param {Error} ex
986− * @param {(string|number)=} depth
987− */
988− function computeStackTrace(ex, depth) {
989− var stack = null;
990− depth = (depth == null ? 0 : +depth);
991−
992− try {
993− // This must be tried first because Opera 10 *destroys*
994− // its stacktrace property if you try to access the stack
995− // property first!!
996− stack = computeStackTraceFromStacktraceProp(ex);
997− if (stack) {
998− return stack;
999− }
1000− } catch (e) {
1001− if (debug) {
1002− throw e;
1003− }
1004− }
1005−
1006− try {
1007− stack = computeStackTraceFromStackProp(ex);
1008− if (stack) {
1009− return stack;
1010− }
1011− } catch (e) {
1012− if (debug) {
1013− throw e;
1014− }
1015− }
1016−
1017− try {
1018− stack = computeStackTraceFromOperaMultiLineMessage(ex);
1019− if (stack) {
1020− return stack;
1021− }
1022− } catch (e) {
1023− if (debug) {
1024− throw e;
1025− }
1026− }
1027−
1028− try {
1029− stack = computeStackTraceByWalkingCallerChain(ex, depth + 1);
1030− if (stack) {
1031− return stack;
1032− }
1033− } catch (e) {
1034− if (debug) {
1035− throw e;
1036− }
1037− }
1038−
1039− return {
1040− 'mode': 'failed'
1041− };
1042− }
1043−
1044− /**
1045− * Logs a stacktrace starting from the previous call and working down.
1046− * @param {(number|string)=} depth How many frames deep to trace.
1047− * @return {Object.<string, *>} Stack trace information.
1048− */
1049− function computeStackTraceOfCaller(depth) {
1050− depth = (depth == null ? 0 : +depth) + 1; // "+ 1" because "ofCaller" should drop one frame
1051− try {
1052− throw new Error();
1053− } catch (ex) {
1054− return computeStackTrace(ex, depth + 1);
1055− }
1056−
1057− return null;
1058− }
1059−
1060− computeStackTrace.augmentStackTraceWithInitialElement = augmentStackTraceWithInitialElement;
1061− computeStackTrace.guessFunctionName = guessFunctionName;
1062− computeStackTrace.gatherContext = gatherContext;
1063− computeStackTrace.ofCaller = computeStackTraceOfCaller;
1064−
1065− return computeStackTrace;
1066−}());
1067−
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−//Default options:
1098−if (!TraceKit.remoteFetching) {
1099− TraceKit.remoteFetching = true;
1100−}
1101−if (!TraceKit.collectWindowErrors) {
1102− TraceKit.collectWindowErrors = true;
1103−}
1104−if (!TraceKit.linesOfContext || TraceKit.linesOfContext < 1) {
1105− // 5 lines before, the offending line, 5 lines after
1106− TraceKit.linesOfContext = 11;
1107−}
1108−
1109−
1110−
1111−// Export to global object
1112−window.TraceKit = TraceKit;
1113−
1114−}(window));
1115−;(function(window, undefined){
1116−'use strict';
1117−
1118−// First, check for JSON support
1119−// If there is no JSON, we no-op the core features of Raven
1120−// since JSON is required to encode the payload
1121−var _Raven = window.Raven,
1122− hasJSON = !isUndefined(window.JSON),
1123− globalServer,
1124− globalUser,
1125− globalKey,
1126− globalProject,
1127− globalOptions = {
1128− logger: 'javascript',
1129− ignoreErrors: [],
1130− ignoreUrls: []
1131− };
1132−
1133−var TK = TraceKit.noConflict();
1134−
1135−// Disable Tracekit's remote fetching by default
1136−TK.remoteFetching = false;
1137−
1138−/*
1139− * The core Raven singleton
1140− *
1141− * @this {Raven}
1142− */
1143−var Raven = {
1144− VERSION: '1.0.8',
1145−
1146− /*
1147− * Allow multiple versions of Raven to be installed.
1148− * Strip Raven from the global context and returns the instance.
1149− *
1150− * @return {Raven}
1151− */
1152− noConflict: function() {
1153− window.Raven = _Raven;
1154− return Raven;
1155− },
1156−
1157− /*
1158− * Configure Raven with a DSN and extra options
1159− *
1160− * @param {string} dsn The public Sentry DSN
1161− * @param {object} options Optional set of of global options [optional]
1162− * @return {Raven}
1163− */
1164− config: function(dsn, options) {
1165− var uri = parseUri(dsn),
1166− lastSlash = uri.path.lastIndexOf('/'),
1167− path = uri.path.substr(1, lastSlash);
1168−
1169− if (options && options.ignoreErrors && window.console && console.warn) {
1170− console.warn('DeprecationWarning: `ignoreErrors` is going to be removed soon.');
1171− }
1172−
1173− // merge in options
1174− if (options) {
1175− each(options, function(key, value){
1176− globalOptions[key] = value;
1177− });
1178− }
1179−
1180− // "Script error." is hard coded into browsers for errors that it can't read.
1181− // this is the result of a script being pulled in from an external domain and CORS.
1182− globalOptions.ignoreErrors.push('Script error.');
1183−
1184− globalKey = uri.user;
1185− globalProject = ~~uri.path.substr(lastSlash + 1);
1186−
1187− // assemble the endpoint from the uri pieces
1188− globalServer = '//' + uri.host +
1189− (uri.port ? ':' + uri.port : '') +
1190− '/' + path + 'api/' + globalProject + '/store/';
1191−
1192− if (uri.protocol) {
1193− globalServer = uri.protocol + ':' + globalServer;
1194− }
1195−
1196− if (globalOptions.fetchContext) {
1197− TK.remoteFetching = true;
1198− }
1199−
1200− // return for chaining
1201− return Raven;
1202− },
1203−
1204− /*
1205− * Installs a global window.onerror error handler
1206− * to capture and report uncaught exceptions.
1207− * At this point, install() is required to be called due
1208− * to the way TraceKit is set up.
1209− *
1210− * @return {Raven}
1211− */
1212− install: function() {
1213− if (!isSetup()) return;
1214−
1215− TK.report.subscribe(handleStackInfo);
1216−
1217− return Raven;
1218− },
1219−
1220− /*
1221− * Wrap code within a context so Raven can capture errors
1222− * reliably across domains that is executed immediately.
1223− *
1224− * @param {object} options A specific set of options for this context [optional]
1225− * @param {function} func The callback to be immediately executed within the context
1226− * @param {array} args An array of arguments to be called with the callback [optional]
1227− */
1228− context: function(options, func, args) {
1229− if (isFunction(options)) {
1230− args = func || [];
1231− func = options;
1232− options = undefined;
1233− }
1234−
1235− Raven.wrap(options, func).apply(this, args);
1236− },
1237−
1238− /*
1239− * Wrap code within a context and returns back a new function to be executed
1240− *
1241− * @param {object} options A specific set of options for this context [optional]
1242− * @param {function} func The function to be wrapped in a new context
1243− * @return {function} The newly wrapped functions with a context
1244− */
1245− wrap: function(options, func) {
1246− // options is optional
1247− if (isFunction(options)) {
1248− func = options;
1249− options = undefined;
1250− }
1251−
1252− return function() {
1253− try {
1254− func.apply(this, arguments);
1255− } catch(e) {
1256− Raven.captureException(e, options);
1257− throw e;
1258− }
1259− };
1260− },
1261−
1262− /*
1263− * Uninstalls the global error handler.
1264− *
1265− * @return {Raven}
1266− */
1267− uninstall: function() {
1268− TK.report.unsubscribe(handleStackInfo);
1269−
1270− return Raven;
1271− },
1272−
1273− /*
1274− * Manually capture an exception and send it over to Sentry
1275− *
1276− * @param {error} ex An exception to be logged
1277− * @param {object} options A specific set of options for this error [optional]
1278− * @return {Raven}
1279− */
1280− captureException: function(ex, options) {
1281− // If a string is passed through, recall as a message
1282− if (typeof ex === 'string') {
1283− return Raven.captureMessage(ex, options);
1284− }
1285−
1286− // TraceKit.report will re-raise any exception passed to it,
1287− // which means you have to wrap it in try/catch. Instead, we
1288− // can wrap it here and only re-raise if TraceKit.report
1289− // raises an exception different from the one we asked to
1290− // report on.
1291− try {
1292− TK.report(ex, options);
1293− } catch(ex1) {
1294− if(ex !== ex1) {
1295− throw ex1;
1296− }
1297− }
1298−
1299− return Raven;
1300− },
1301−
1302− /*
1303− * Manually send a message to Sentry
1304− *
1305− * @param {string} msg A plain message to be captured in Sentry
1306− * @param {object} options A specific set of options for this message [optional]
1307− * @return {Raven}
1308− */
1309− captureMessage: function(msg, options) {
1310− // Fire away!
1311− send(
1312− arrayMerge({
1313− message: msg
1314− }, options)
1315− );
1316−
1317− return Raven;
1318− },
1319−
1320− /*
1321− * Set/clear a user to be sent along with the payload.
1322− *
1323− * @param {object} user An object representing user data [optional]
1324− * @return {Raven}
1325− */
1326− setUser: function(user) {
1327− globalUser = user;
1328−
1329− return Raven;
1330− }
1331−};
1332−
1333−var uriKeys = 'source protocol authority userInfo user password host port relative path directory file query anchor'.split(' '),
1334− uriPattern = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
1335−
1336−/**** Private functions ****/
1337−function parseUri(str) {
1338− var m = uriPattern.exec(str),
1339− uri = {},
1340− i = 14;
1341−
1342− while (i--) uri[uriKeys[i]] = m[i] || '';
1343−
1344− return uri;
1345−}
1346−
1347−function isUndefined(what) {
1348− return typeof what === 'undefined';
1349−}
1350−
1351−function isFunction(what) {
1352− return typeof what === 'function';
1353−}
1354−
1355−function each(obj, callback) {
1356− var i, j;
1357−
1358− if (isUndefined(obj.length)) {
1359− for (i in obj) {
1360− if (obj.hasOwnProperty(i)) {
1361− callback.call(null, i, obj[i]);
1362− }
1363− }
1364− } else {
1365− for (i = 0, j = obj.length; i < j; i++) {
1366− callback.call(null, i, obj[i]);
1367− }
1368− }
1369−}
1370−
1371−var cachedAuth;
1372−
1373−function getAuthQueryString() {
1374− if (cachedAuth) return cachedAuth;
1375−
1376− var qs = [
1377− 'sentry_version=2.0',
1378− 'sentry_client=raven-js/' + Raven.VERSION
1379− ];
1380− if (globalKey) {
1381− qs.push('sentry_key=' + globalKey);
1382− }
1383−
1384− cachedAuth = '?' + qs.join('&');
1385− return cachedAuth;
1386−}
1387−
1388−function handleStackInfo(stackInfo, options) {
1389− var frames = [],
1390− i = 0,
1391− j, frame;
1392−
1393− if (stackInfo.stack && (j = stackInfo.stack.length)) {
1394− for (; i < j; i++) {
1395− frame = normalizeFrame(stackInfo.stack[i]);
1396− if (frame) {
1397− frames.push(frame);
1398− }
1399− }
1400− }
1401−
1402− processException(
1403− stackInfo.name,
1404− stackInfo.message,
1405− stackInfo.url,
1406− stackInfo.lineno,
1407− frames,
1408− options
1409− );
1410−}
1411−
1412−function normalizeFrame(frame) {
1413− if (!frame.url) return;
1414−
1415− // normalize the frames data
1416− var normalized = {
1417− filename: frame.url,
1418− lineno: frame.line,
1419− colno: frame.column,
1420− 'function': frame.func || '?'
1421− }, context = extractContextFromFrame(frame);
1422−
1423− if (context) {
1424− var i = 3, keys = ['pre_context', 'context_line', 'post_context'];
1425− while (i--) normalized[keys[i]] = context[i];
1426− }
1427−
1428− normalized.in_app = !/(Raven|TraceKit)\./.test(normalized['function']);
1429−
1430− return normalized;
1431−}
1432−
1433−function extractContextFromFrame(frame) {
1434− // immediately check if we should even attempt to parse a context
1435− if (!frame.context || !globalOptions.fetchContext) return;
1436−
1437− var context = frame.context,
1438− pivot = ~~(context.length / 2),
1439− i = context.length, isMinified = false;
1440−
1441− while (i--) {
1442− // We're making a guess to see if the source is minified or not.
1443− // To do that, we make the assumption if *any* of the lines passed
1444− // in are greater than 300 characters long, we bail.
1445− // Sentry will see that there isn't a context
1446− if (context[i].length > 300) {
1447− isMinified = true;
1448− break;
1449− }
1450− }
1451−
1452− if (isMinified) {
1453− // The source is minified and we don't know which column. Fuck it.
1454− if (isUndefined(frame.column)) return;
1455−
1456− // If the source is minified and has a frame column
1457− // we take a chunk of the offending line to hopefully shed some light
1458− return [
1459− [], // no pre_context
1460− context[pivot].substr(frame.column, 50), // grab 50 characters, starting at the offending column
1461− [] // no post_context
1462− ];
1463− }
1464−
1465− return [
1466− context.slice(0, pivot), // pre_context
1467− context[pivot], // context_line
1468− context.slice(pivot + 1) // post_context
1469− ];
1470−}
1471−
1472−function processException(type, message, fileurl, lineno, frames, options) {
1473− var stacktrace, label, i;
1474−
1475− // IE8 really doesn't have Array.prototype.indexOf
1476− // Filter out a message that matches our ignore list
1477− i = globalOptions.ignoreErrors.length;
1478− while (i--) {
1479− if (message === globalOptions.ignoreErrors[i]) {
1480− return;
1481− }
1482− }
1483−
1484− if (frames && frames.length) {
1485− stacktrace = {frames: frames};
1486− fileurl = fileurl || frames[0].filename;
1487− } else if (fileurl) {
1488− stacktrace = {
1489− frames: [{
1490− filename: fileurl,
1491− lineno: lineno
1492− }]
1493− };
1494− }
1495−
1496− i = globalOptions.ignoreUrls.length;
1497− while (i--) {
1498− if (globalOptions.ignoreUrls[i].test(fileurl)) {
1499− return;
1500− }
1501− }
1502−
1503− label = lineno ? message + ' at ' + lineno : message;
1504−
1505− // Fire away!
1506− send(
1507− arrayMerge({
1508− 'sentry.interfaces.Exception': {
1509− type: type,
1510− value: message
1511− },
1512− 'sentry.interfaces.Stacktrace': stacktrace,
1513− culprit: fileurl,
1514− message: label
1515− }, options)
1516− );
1517−}
1518−
1519−function arrayMerge(arr1, arr2) {
1520− if (!arr2) {
1521− return arr1;
1522− }
1523− each(arr2, function(key, value){
1524− arr1[key] = value;
1525− });
1526− return arr1;
1527−}
1528−
1529−function getHttpData() {
1530− var http = {
1531− url: window.location.href,
1532− headers: {
1533− 'User-Agent': navigator.userAgent
1534− }
1535− };
1536−
1537− if (window.document.referrer) {
1538− http.headers.Referer = window.document.referrer;
1539− }
1540−
1541− return http;
1542−}
1543−
1544−function send(data) {
1545− if (!isSetup()) return;
1546−
1547− data = arrayMerge({
1548− project: globalProject,
1549− logger: globalOptions.logger,
1550− site: globalOptions.site,
1551− platform: 'javascript',
1552− 'sentry.interfaces.Http': getHttpData()
1553− }, data);
1554−
1555− if (globalUser) data['sentry.interfaces.User'] = globalUser;
1556−
1557− if (isFunction(globalOptions.dataCallback)) {
1558− data = globalOptions.dataCallback(data);
1559− }
1560−
1561− makeRequest(data);
1562−}
1563−
1564−function makeRequest(data) {
1565− new Image().src = globalServer + getAuthQueryString() + '&sentry_data=' + encodeURIComponent(JSON.stringify(data));
1566−}
1567−
1568−function isSetup() {
1569− if (!hasJSON) return false; // needs JSON support
1570− if (!globalServer) {
1571− if (window.console && console.error) {
1572− console.error("Error: Raven has not been configured.");
1573− }
1574− return false;
1575− }
1576− return true;
1577−}
1578−
1579−// Expose Raven to the world
1580−window.Raven = Raven;
1581−
1582−// AMD
1583−if (typeof define === 'function' && define.amd) {
1584− define('raven', [], function() { return Raven; });
1585−}
1586−
1587−})(window);
1+/*! Raven.js 1.1.10 (e96d774) | github.com/getsentry/raven-js */
2+!function(a,b){"use strict";function c(a,b){var c,d;b=b||{},a="raven"+a.substr(0,1).toUpperCase()+a.substr(1),document.createEvent?(c=document.createEvent("HTMLEvents"),c.initEvent(a,!0,!0)):(c=document.createEventObject(),c.eventType=a);for(d in b)b.hasOwnProperty(d)&&(c[d]=b[d]);if(document.createEvent)document.dispatchEvent(c);else try{document.fireEvent("on"+c.eventType.toLowerCase(),c)}catch(e){}}function d(a){this.name="RavenConfigError",this.message=a}function e(a){var b=L.exec(a),c={},e=7;try{for(;e--;)c[K[e]]=b[e]||""}catch(f){throw new d("Invalid DSN: "+a)}if(c.pass)throw new d("Do not specify your private key in the DSN!");return c}function f(a){return"undefined"==typeof a}function g(a){return"function"==typeof a}function h(a){return"string"==typeof a}function i(a){for(var b in a)return!1;return!0}function j(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function k(a,b){var c,d;if(f(a.length))for(c in a)a.hasOwnProperty(c)&&b.call(null,c,a[c]);else if(d=a.length)for(c=0;d>c;c++)b.call(null,c,a[c])}function l(){if(M)return M;var a=["sentry_version=4","sentry_client=raven-js/"+J.VERSION];return E&&a.push("sentry_key="+E),M="?"+a.join("&")}function m(a,b){var d=[];a.stack&&a.stack.length&&k(a.stack,function(a,b){var c=n(b);c&&d.push(c)}),c("handle",{stackInfo:a,options:b}),p(a.name,a.message,a.url,a.lineno,d,b)}function n(a){if(a.url){var b,c={filename:a.url,lineno:a.line,colno:a.column,"function":a.func||"?"},d=o(a);if(d){var e=["pre_context","context_line","post_context"];for(b=3;b--;)c[e[b]]=d[b]}return c.in_app=!(!I.includePaths.test(c.filename)||/(Raven|TraceKit)\./.test(c["function"])||/raven\.(min\.)js$/.test(c.filename)),c}}function o(a){if(a.context&&I.fetchContext){for(var b=a.context,c=~~(b.length/2),d=b.length,e=!1;d--;)if(b[d].length>300){e=!0;break}if(e){if(f(a.column))return;return[[],b[c].substr(a.column,50),[]]}return[b.slice(0,c),b[c],b.slice(c+1)]}}function p(a,b,c,d,e,f){var g,h;b&&(I.ignoreErrors.test(b)||(e&&e.length?(c=e[0].filename||c,e.reverse(),g={frames:e}):c&&(g={frames:[{filename:c,lineno:d}]}),I.ignoreUrls&&I.ignoreUrls.test(c)||(!I.whitelistUrls||I.whitelistUrls.test(c))&&(h=d?b+" at "+d:b,s(q({exception:{type:a,value:b},stacktrace:g,culprit:c,message:h},f)))))}function q(a,b){return b?(k(b,function(b,c){a[b]=c}),a):a}function r(){var a={url:document.location.href,headers:{"User-Agent":navigator.userAgent}};return document.referrer&&(a.headers.Referer=document.referrer),a}function s(a){u()&&(a=q({project:F,logger:I.logger,site:I.site,platform:"javascript",request:r()},a),a.tags=q(I.tags,a.tags),a.extra=q(I.extra,a.extra),i(a.tags)&&delete a.tags,i(a.extra)&&delete a.extra,D&&(a.user=D),g(I.dataCallback)&&(a=I.dataCallback(a)),(!g(I.shouldSendCallback)||I.shouldSendCallback(a))&&(B=a.event_id||(a.event_id=w()),t(a)))}function t(a){var b=new Image,d=C+l()+"&sentry_data="+encodeURIComponent(JSON.stringify(a));b.onload=function(){c("success",{data:a,src:d})},b.onerror=b.onabort=function(){c("failure",{data:a,src:d})},b.src=d}function u(){return H?C?!0:(a.console&&console.error&&console.error("Error: Raven has not been configured."),!1):!1}function v(a){for(var b,c=[],d=0,e=a.length;e>d;d++)b=a[d],h(b)?c.push(b.replace(/([.*+?^=!:${}()|\[\]\/\\])/g,"\\$1")):b&&b.source&&c.push(b.source);return new RegExp(c.join("|"),"i")}function w(){return"xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g,function(a){var b=16*Math.random()|0,c="x"==a?b:3&b|8;return c.toString(16)})}var x={remoteFetching:!1,collectWindowErrors:!0,linesOfContext:7},y=[].slice,z="?";x.wrap=function(a){function b(){try{return a.apply(this,arguments)}catch(b){throw x.report(b),b}}return b},x.report=function(){function c(a){i(),o.push(a)}function d(a){for(var b=o.length-1;b>=0;--b)o[b]===a&&o.splice(b,1)}function e(){k(),o=[]}function g(a,b){var c=null;if(!b||x.collectWindowErrors){for(var d in o)if(j(o,d))try{o[d].apply(null,[a].concat(y.call(arguments,2)))}catch(e){c=e}if(c)throw c}}function h(a,b,c,d,e){var h=null,i=!1;if(f(e))if(q)x.computeStackTrace.augmentStackTraceWithInitialElement(q,b,c,a),h=q,q=null,p=null;else{var j={url:b,line:c,column:d};j.func=x.computeStackTrace.guessFunctionName(j.url,j.line),j.context=x.computeStackTrace.gatherContext(j.url,j.line),h={mode:"onerror",message:a,url:document.location.href,stack:[j],useragent:navigator.userAgent}}else l(e,!1),i=!0;return i||g(h,"from window.onerror"),m?m.apply(this,arguments):!1}function i(){n||(m=a.onerror,a.onerror=h,n=!0)}function k(){n&&(a.onerror=m,n=!1,m=b)}function l(b,c){var d=y.call(arguments,1);if(q){if(p===b)return;var e=q;q=null,p=null,g.apply(null,[e,null].concat(d))}var f=x.computeStackTrace(b);if(q=f,p=b,a.setTimeout(function(){p===b&&(q=null,p=null,g.apply(null,[f,null].concat(d)))},f.incomplete?2e3:0),c!==!1)throw b}var m,n,o=[],p=null,q=null;return l.subscribe=c,l.unsubscribe=d,l.uninstall=e,l}(),x.computeStackTrace=function(){function b(b){if(!x.remoteFetching)return"";try{var c=function(){try{return new a.XMLHttpRequest}catch(b){return new a.ActiveXObject("Microsoft.XMLHTTP")}},d=c();return d.open("GET",b,!1),d.send(""),d.responseText}catch(e){return""}}function c(a){if(!j(u,a)){var c="";-1!==a.indexOf(document.domain)&&(c=b(a)),u[a]=c?c.split("\n"):[]}return u[a]}function d(a,b){var d,e=/function ([^(]*)\(([^)]*)\)/,g=/['"]?([0-9A-Za-z$_]+)['"]?\s*[:=]\s*(function|eval|new Function)/,h="",i=10,j=c(a);if(!j.length)return z;for(var k=0;i>k;++k)if(h=j[b-k]+h,!f(h)){if(d=g.exec(h))return d[1];if(d=e.exec(h))return d[1]}return z}function e(a,b){var d=c(a);if(!d.length)return null;var e=[],g=Math.floor(x.linesOfContext/2),h=g+x.linesOfContext%2,i=Math.max(0,b-g-1),j=Math.min(d.length,b+h-1);b-=1;for(var k=i;j>k;++k)f(d[k])||e.push(d[k]);return e.length>0?e:null}function g(a){return a.replace(/[\-\[\]{}()*+?.,\\\^$|#]/g,"\\$&")}function h(a){return g(a).replace("<","(?:<|&lt;)").replace(">","(?:>|&gt;)").replace("&","(?:&|&amp;)").replace('"','(?:"|&quot;)').replace(/\s+/g,"\\s+")}function i(a,b){for(var d,e,f=0,g=b.length;g>f;++f)if((d=c(b[f])).length&&(d=d.join("\n"),e=a.exec(d)))return{url:b[f],line:d.substring(0,e.index).split("\n").length,column:e.index-d.lastIndexOf("\n",e.index)-1};return null}function k(a,b,d){var e,f=c(b),h=new RegExp("\\b"+g(a)+"\\b");return d-=1,f&&f.length>d&&(e=h.exec(f[d]))?e.index:null}function l(b){for(var c,d,e,f,j=[a.location.href],k=document.getElementsByTagName("script"),l=""+b,m=/^function(?:\s+([\w$]+))?\s*\(([\w\s,]*)\)\s*\{\s*(\S[\s\S]*\S)\s*\}\s*$/,n=/^function on([\w$]+)\s*\(event\)\s*\{\s*(\S[\s\S]*\S)\s*\}\s*$/,o=0;o<k.length;++o){var p=k[o];p.src&&j.push(p.src)}if(e=m.exec(l)){var q=e[1]?"\\s+"+e[1]:"",r=e[2].split(",").join("\\s*,\\s*");c=g(e[3]).replace(/;$/,";?"),d=new RegExp("function"+q+"\\s*\\(\\s*"+r+"\\s*\\)\\s*{\\s*"+c+"\\s*}")}else d=new RegExp(g(l).replace(/\s+/g,"\\s+"));if(f=i(d,j))return f;if(e=n.exec(l)){var s=e[1];if(c=h(e[2]),d=new RegExp("on"+s+"=[\\'\"]\\s*"+c+"\\s*[\\'\"]","i"),f=i(d,j[0]))return f;if(d=new RegExp(c),f=i(d,j))return f}return null}function m(a){if(!a.stack)return null;for(var b,c,f=/^\s*at (?:((?:\[object object\])?\S+(?: \[as \S+\])?) )?\(?((?:file|https?):.*?):(\d+)(?::(\d+))?\)?\s*$/i,g=/^\s*(\S*)(?:\((.*?)\))?@((?:file|https?).*?):(\d+)(?::(\d+))?\s*$/i,h=a.stack.split("\n"),i=[],j=/^(.*) is undefined$/.exec(a.message),l=0,m=h.length;m>l;++l){if(b=g.exec(h[l]))c={url:b[3],func:b[1]||z,args:b[2]?b[2].split(","):"",line:+b[4],column:b[5]?+b[5]:null};else{if(!(b=f.exec(h[l])))continue;c={url:b[2],func:b[1]||z,line:+b[3],column:b[4]?+b[4]:null}}!c.func&&c.line&&(c.func=d(c.url,c.line)),c.line&&(c.context=e(c.url,c.line)),i.push(c)}return i[0]&&i[0].line&&!i[0].column&&j&&(i[0].column=k(j[1],i[0].url,i[0].line)),i.length?{mode:"stack",name:a.name,message:a.message,url:document.location.href,stack:i,useragent:navigator.userAgent}:null}function n(a){for(var b,c=a.stacktrace,f=/ line (\d+), column (\d+) in (?:<anonymous function: ([^>]+)>|([^\)]+))\((.*)\) in (.*):\s*$/i,g=c.split("\n"),h=[],i=0,j=g.length;j>i;i+=2)if(b=f.exec(g[i])){var k={line:+b[1],column:+b[2],func:b[3]||b[4],args:b[5]?b[5].split(","):[],url:b[6]};if(!k.func&&k.line&&(k.func=d(k.url,k.line)),k.line)try{k.context=e(k.url,k.line)}catch(l){}k.context||(k.context=[g[i+1]]),h.push(k)}return h.length?{mode:"stacktrace",name:a.name,message:a.message,url:document.location.href,stack:h,useragent:navigator.userAgent}:null}function o(b){var f=b.message.split("\n");if(f.length<4)return null;var g,k,l,m,n=/^\s*Line (\d+) of linked script ((?:file|https?)\S+)(?:: in function (\S+))?\s*$/i,o=/^\s*Line (\d+) of inline#(\d+) script in ((?:file|https?)\S+)(?:: in function (\S+))?\s*$/i,p=/^\s*Line (\d+) of function script\s*$/i,q=[],r=document.getElementsByTagName("script"),s=[];for(k in r)j(r,k)&&!r[k].src&&s.push(r[k]);for(k=2,l=f.length;l>k;k+=2){var t=null;if(g=n.exec(f[k]))t={url:g[2],func:g[3],line:+g[1]};else if(g=o.exec(f[k])){t={url:g[3],func:g[4]};var u=+g[1],v=s[g[2]-1];if(v&&(m=c(t.url))){m=m.join("\n");var w=m.indexOf(v.innerText);w>=0&&(t.line=u+m.substring(0,w).split("\n").length)}}else if(g=p.exec(f[k])){var x=a.location.href.replace(/#.*$/,""),y=g[1],z=new RegExp(h(f[k+1]));m=i(z,[x]),t={url:x,line:m?m.line:y,func:""}}if(t){t.func||(t.func=d(t.url,t.line));var A=e(t.url,t.line),B=A?A[Math.floor(A.length/2)]:null;t.context=A&&B.replace(/^\s*/,"")===f[k+1].replace(/^\s*/,"")?A:[f[k+1]],q.push(t)}}return q.length?{mode:"multiline",name:b.name,message:f[0],url:document.location.href,stack:q,useragent:navigator.userAgent}:null}function p(a,b,c,f){var g={url:b,line:c};if(g.url&&g.line){a.incomplete=!1,g.func||(g.func=d(g.url,g.line)),g.context||(g.context=e(g.url,g.line));var h=/ '([^']+)' /.exec(f);if(h&&(g.column=k(h[1],g.url,g.line)),a.stack.length>0&&a.stack[0].url===g.url){if(a.stack[0].line===g.line)return!1;if(!a.stack[0].line&&a.stack[0].func===g.func)return a.stack[0].line=g.line,a.stack[0].context=g.context,!1}return a.stack.unshift(g),a.partial=!0,!0}return a.incomplete=!0,!1}function q(a,b){for(var c,e,f,g=/function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,h=[],i={},j=!1,m=q.caller;m&&!j;m=m.caller)if(m!==r&&m!==x.report){if(e={url:null,func:z,line:null,column:null},m.name?e.func=m.name:(c=g.exec(m.toString()))&&(e.func=c[1]),f=l(m)){e.url=f.url,e.line=f.line,e.func===z&&(e.func=d(e.url,e.line));var n=/ '([^']+)' /.exec(a.message||a.description);n&&(e.column=k(n[1],f.url,f.line))}i[""+m]?j=!0:i[""+m]=!0,h.push(e)}b&&h.splice(0,b);var o={mode:"callers",name:a.name,message:a.message,url:document.location.href,stack:h,useragent:navigator.userAgent};return p(o,a.sourceURL||a.fileName,a.line||a.lineNumber,a.message||a.description),o}function r(a,b){var c=null;b=null==b?0:+b;try{if(c=n(a))return c}catch(d){if(t)throw d}try{if(c=m(a))return c}catch(d){if(t)throw d}try{if(c=o(a))return c}catch(d){if(t)throw d}try{if(c=q(a,b+1))return c}catch(d){if(t)throw d}return{mode:"failed"}}function s(a){a=(null==a?0:+a)+1;try{throw new Error}catch(b){return r(b,a+1)}}var t=!1,u={};return r.augmentStackTraceWithInitialElement=p,r.guessFunctionName=d,r.gatherContext=e,r.ofCaller=s,r}();var A,B,C,D,E,F,G=a.Raven,H=!(!a.JSON||!a.JSON.stringify),I={logger:"javascript",ignoreErrors:[],ignoreUrls:[],whitelistUrls:[],includePaths:[],collectWindowErrors:!0,tags:{},extra:{}},J={VERSION:"1.1.10",TraceKit:x,afterLoad:function(){var b=a.RavenConfig;b&&this.config(b.dsn,b.config).install()},noConflict:function(){return a.Raven=G,J},config:function(a,b){if(!a)return J;var c=e(a),d=c.path.lastIndexOf("/"),f=c.path.substr(1,d);return b&&k(b,function(a,b){I[a]=b}),I.ignoreErrors.push("Script error."),I.ignoreErrors.push("Script error"),I.ignoreErrors=v(I.ignoreErrors),I.ignoreUrls=I.ignoreUrls.length?v(I.ignoreUrls):!1,I.whitelistUrls=I.whitelistUrls.length?v(I.whitelistUrls):!1,I.includePaths=v(I.includePaths),E=c.user,F=c.path.substr(d+1),C="//"+c.host+(c.port?":"+c.port:"")+"/"+f+"api/"+F+"/store/",c.protocol&&(C=c.protocol+":"+C),I.fetchContext&&(x.remoteFetching=!0),I.linesOfContext&&(x.linesOfContext=I.linesOfContext),x.collectWindowErrors=!!I.collectWindowErrors,J},install:function(){return u()&&x.report.subscribe(m),J},context:function(a,c,d){return g(a)&&(d=c||[],c=a,a=b),J.wrap(a,c).apply(this,d)},wrap:function(a,c){function d(){for(var b=[],d=arguments.length,e=!a||a&&a.deep!==!1;d--;)b[d]=e?J.wrap(a,arguments[d]):arguments[d];try{return c.apply(this,b)}catch(f){throw J.captureException(f,a),f}}if(f(c)&&!g(a))return a;if(g(a)&&(c=a,a=b),!g(c))return c;if(c.__raven__)return c;for(var e in c)c.hasOwnProperty(e)&&(d[e]=c[e]);return d.__raven__=!0,d},uninstall:function(){return x.report.uninstall(),J},captureException:function(a,b){if(h(a))return J.captureMessage(a,b);A=a;try{x.report(a,b)}catch(c){if(a!==c)throw c}return J},captureMessage:function(a,b){return s(q({message:a},b)),J},setUser:function(a){return D=a,J},lastException:function(){return A},lastEventId:function(){return B}},K="source protocol user pass host port path".split(" "),L=/^(?:(\w+):)?\/\/(\w+)(:\w+)?@([\w\.-]+)(?::(\d+))?(\/.*)/;d.prototype=new Error,d.prototype.constructor=d;var M;J.afterLoad(),a.Raven=J,"function"==typeof define&&define.amd&&define("raven",[],function(){return J})}(window);
3+//# sourceMappingURL=raven.min.map