History

Update Raven.js

Thibaut Courouble committed 10 years ago

Commit 5db1ca71 parent c2dcd3d1 file · +218 −166Browse files

Unified · Split

assets/javascripts/vendor/raven.js+218−166
@@ -1,4 +1,4 @@
1−/*! Raven.js 3.0.4 (0784c3c) | github.com/getsentry/raven-js */
1+/*! Raven.js 3.5.1 (bef9fa7) | github.com/getsentry/raven-js */
22
33 /*
44 * Includes TraceKit
@@ -11,6 +11,35 @@ · 6 unmodified lines
1111 */
1212
1313 (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Raven = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
14+exports = module.exports = stringify
15+exports.getSerialize = serializer
16+
17+function stringify(obj, replacer, spaces, cycleReplacer) {
18+ return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces)
19+}
20+
21+function serializer(replacer, cycleReplacer) {
22+ var stack = [], keys = []
23+
24+ if (cycleReplacer == null) cycleReplacer = function(key, value) {
25+ if (stack[0] === value) return "[Circular ~]"
26+ return "[Circular ~." + keys.slice(0, stack.indexOf(value)).join(".") + "]"
27+ }
28+
29+ return function(key, value) {
30+ if (stack.length > 0) {
31+ var thisPos = stack.indexOf(this)
32+ ~thisPos ? stack.splice(thisPos + 1) : stack.push(this)
33+ ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key)
34+ if (~stack.indexOf(value)) value = cycleReplacer.call(this, key, value)
35+ }
36+ else stack.push(value)
37+
38+ return replacer == null ? value : replacer.call(this, key, value)
39+ }
40+}
41+
42+},{}],2:[function(_dereq_,module,exports){
1443 'use strict';
1544
1645 function RavenConfigError(message) {
@@ -22,7 +51,7 @@ RavenConfigError.prototype.constructor = RavenConfigError; · 5 unmodified lines
2251
2352 module.exports = RavenConfigError;
2453
25−},{}],2:[function(_dereq_,module,exports){
54+},{}],3:[function(_dereq_,module,exports){
2655 'use strict';
2756
2857 var wrapMethod = function(console, level, callback) {
@@ -61,13 +90,14 @@ module.exports = { · 32 unmodified lines
6190 wrapMethod: wrapMethod
6291 };
6392
64−},{}],3:[function(_dereq_,module,exports){
93+},{}],4:[function(_dereq_,module,exports){
6594 /*global XDomainRequest:false*/
6695 'use strict';
6796
68−var TraceKit = _dereq_(6);
69−var RavenConfigError = _dereq_(1);
70−var utils = _dereq_(5);
97+var TraceKit = _dereq_(7);
98+var RavenConfigError = _dereq_(2);
99+var utils = _dereq_(6);
100+var stringify = _dereq_(1);
71101
72102 var isFunction = utils.isFunction;
73103 var isUndefined = utils.isUndefined;
@@ -83,8 +113,9 @@ var uuid4 = utils.uuid4; · 9 unmodified lines
83113 var htmlTreeAsString = utils.htmlTreeAsString;
84114 var parseUrl = utils.parseUrl;
85115 var isString = utils.isString;
116+var fill = utils.fill;
86117
87−var wrapConsoleMethod = _dereq_(2).wrapMethod;
118+var wrapConsoleMethod = _dereq_(3).wrapMethod;
88119
89120 var dsnKeys = 'source protocol user pass host port path'.split(' '),
90121 dsnPattern = /^(?:(\w+):)?\/\/(?:(\w+)(:\w+)?@)?([\w\.-]+)(?::(\d+))?(\/.*)/;
@@ -93,6 +124,7 @@ function now() { · 2 unmodified lines
93124 return +new Date();
94125 }
95126
127+
96128 // First, check for JSON support
97129 // If there is no JSON, we no-op the core features of Raven
98130 // since JSON is required to encode the payload
@@ -115,7 +147,8 @@ function Raven() { · 16 unmodified lines
115147 crossOrigin: 'anonymous',
116148 collectWindowErrors: true,
117149 maxMessageLength: 0,
118− stackTraceLimit: 50
150+ stackTraceLimit: 50,
151+ autoBreadcrumbs: true
119152 };
120153 this._ignoreOnError = 0;
121154 this._isRavenInstalled = false;
@@ -128,7 +161,6 @@ function Raven() { · 6 unmodified lines
128161 this._startTime = now();
129162 this._wrappedBuiltIns = [];
130163 this._breadcrumbs = [];
131− this._breadcrumbLimit = 20;
132164 this._lastCapturedEvent = null;
133165 this._keypressTimeout;
134166 this._location = window.location;
@@ -150,7 +182,7 @@ Raven.prototype = { · 15 unmodified lines
150182 // webpack (using a build step causes webpack #1617). Grunt verifies that
151183 // this value matches package.json during build.
152184 // See: https://github.com/getsentry/raven-js/issues/465
153− VERSION: '3.0.4',
185+ VERSION: '3.5.1',
154186
155187 debug: false,
156188
@@ -200,6 +232,22 @@ Raven.prototype = { · 43 unmodified lines
200232 this._globalOptions.ignoreUrls = this._globalOptions.ignoreUrls.length ? joinRegExp(this._globalOptions.ignoreUrls) : false;
201233 this._globalOptions.whitelistUrls = this._globalOptions.whitelistUrls.length ? joinRegExp(this._globalOptions.whitelistUrls) : false;
202234 this._globalOptions.includePaths = joinRegExp(this._globalOptions.includePaths);
235+ this._globalOptions.maxBreadcrumbs = Math.max(0, Math.min(this._globalOptions.maxBreadcrumbs || 100, 100)); // default and hard limit is 100
236+
237+ var autoBreadcrumbDefaults = {
238+ xhr: true,
239+ console: true,
240+ dom: true,
241+ location: true
242+ };
243+
244+ var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs;
245+ if ({}.toString.call(autoBreadcrumbs) === '[object Object]') {
246+ autoBreadcrumbs = objectMerge(autoBreadcrumbDefaults, autoBreadcrumbs);
247+ } else if (autoBreadcrumbs !== false) {
248+ autoBreadcrumbs = autoBreadcrumbDefaults;
249+ }
250+ this._globalOptions.autoBreadcrumbs = autoBreadcrumbs;
203251
204252 this._globalKey = uri.user;
205253 this._globalSecret = uri.pass && uri.pass.substr(1);
@@ -210,14 +258,6 @@ Raven.prototype = { · 4 unmodified lines
210258 this._globalEndpoint = this._globalServer +
211259 '/' + path + 'api/' + this._globalProject + '/store/';
212260
213− if (this._globalOptions.fetchContext) {
214− TraceKit.remoteFetching = true;
215− }
216−
217− if (this._globalOptions.linesOfContext) {
218− TraceKit.linesOfContext = this._globalOptions.linesOfContext;
219− }
220−
221261 TraceKit.collectWindowErrors = !!this._globalOptions.collectWindowErrors;
222262
223263 // return for chaining
@@ -238,7 +278,9 @@ Raven.prototype = { · 14 unmodified lines
238278 TraceKit.report.subscribe(function () {
239279 self._handleOnErrorStackInfo.apply(self, arguments);
240280 });
241− this._wrapBuiltIns();
281+ this._instrumentTryCatch();
282+ if (self._globalOptions.autoBreadcrumbs)
283+ this._instrumentBreadcrumbs();
242284
243285 // Install all of the plugins
244286 this._drainPlugins();
@@ -429,7 +471,7 @@ Raven.prototype = { · 184 unmodified lines
429471 }, obj);
430472
431473 this._breadcrumbs.push(crumb);
432− if (this._breadcrumbs.length > this._breadcrumbLimit) {
474+ if (this._breadcrumbs.length > this._globalOptions.maxBreadcrumbs) {
433475 this._breadcrumbs.shift();
434476 }
435477 },
@@ -500,7 +542,20 @@ Raven.prototype = { · 64 unmodified lines
500542 */
501543 getContext: function() {
502544 // lol javascript
503− return JSON.parse(JSON.stringify(this._globalContext));
545+ return JSON.parse(stringify(this._globalContext));
546+ },
547+
548+
549+ /*
550+ * Set environment of application
551+ *
552+ * @param {string} environment Typically something like 'production'.
553+ * @return {Raven}
554+ */
555+ setEnvironment: function(environment) {
556+ this._globalOptions.environment = environment;
557+
558+ return this;
504559 },
505560
506561 /*
@@ -523,7 +578,10 @@ Raven.prototype = { · 16 unmodified lines
523578 * @return {Raven}
524579 */
525580 setDataCallback: function(callback) {
526− this._globalOptions.dataCallback = callback;
581+ var original = this._globalOptions.dataCallback;
582+ this._globalOptions.dataCallback = isFunction(callback)
583+ ? function (data) { return callback(data, original); }
584+ : callback;
527585
528586 return this;
529587 },
@@ -536,7 +594,10 @@ Raven.prototype = { · 6 unmodified lines
536594 * @return {Raven}
537595 */
538596 setShouldSendCallback: function(callback) {
539− this._globalOptions.shouldSendCallback = callback;
597+ var original = this._globalOptions.shouldSendCallback;
598+ this._globalOptions.shouldSendCallback = isFunction(callback)
599+ ? function (data) { return callback(data, original); }
600+ : callback;
540601
541602 return this;
542603 },
@@ -794,16 +855,10 @@ Raven.prototype = { · 251 unmodified lines
794855 /**
795856 * Install any queued plugins
796857 */
797− _wrapBuiltIns: function() {
858+ _instrumentTryCatch: function() {
798859 var self = this;
799860
800− function fill(obj, name, replacement, noUndo) {
801− var orig = obj[name];
802− obj[name] = replacement(orig);
803− if (!noUndo) {
804− self._wrappedBuiltIns.push([obj, name, orig]);
805− }
806− }
861+ var wrappedBuiltIns = self._wrappedBuiltIns;
807862
808863 function wrapTimeFn(orig) {
809864 return function (fn, t) { // preserve arity
@@ -829,6 +884,8 @@ Raven.prototype = { · 19 unmodified lines
829884 };
830885 }
831886
887+ var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs;
888+
832889 function wrapEventTarget(global) {
833890 var proto = window[global] && window[global].prototype;
834891 if (proto && proto.hasOwnProperty && proto.hasOwnProperty('addEventListener')) {
@@ -842,10 +899,10 @@ Raven.prototype = { · 7 unmodified lines
842899 // can sometimes get 'Permission denied to access property "handle Event'
843900 }
844901
845−
846− // TODO: more than just click
902+ // More breadcrumb DOM capture ... done here and not in `_instrumentBreadcrumbs`
903+ // so that we don't have more than one wrapper function
847904 var before;
848− if (global === 'EventTarget' || global === 'Node') {
905+ if (autoBreadcrumbs && autoBreadcrumbs.dom && (global === 'EventTarget' || global === 'Node')) {
849906 if (evtName === 'click'){
850907 before = self._breadcrumbEventHandler(evtName);
851908 } else if (evtName === 'keypress') {
@@ -854,39 +911,24 @@ Raven.prototype = { · 2 unmodified lines
854911 }
855912 return orig.call(this, evtName, self.wrap(fn, undefined, before), capture, secure);
856913 };
857− });
914+ }, wrappedBuiltIns);
858915 fill(proto, 'removeEventListener', function (orig) {
859916 return function (evt, fn, capture, secure) {
860917 fn = fn && (fn.__raven_wrapper__ ? fn.__raven_wrapper__ : fn);
861918 return orig.call(this, evt, fn, capture, secure);
862919 };
863− });
920+ }, wrappedBuiltIns);
864921 }
865922 }
866923
867− function wrapProp(prop, xhr) {
868− if (prop in xhr && isFunction(xhr[prop])) {
869− fill(xhr, prop, function (orig) {
870− return self.wrap(orig);
871− }, true /* noUndo */); // don't track filled methods on XHR instances
872− }
873− }
874−
875− fill(window, 'setTimeout', wrapTimeFn);
876− fill(window, 'setInterval', wrapTimeFn);
924+ fill(window, 'setTimeout', wrapTimeFn, wrappedBuiltIns);
925+ fill(window, 'setInterval', wrapTimeFn, wrappedBuiltIns);
877926 if (window.requestAnimationFrame) {
878927 fill(window, 'requestAnimationFrame', function (orig) {
879928 return function (cb) {
880929 return orig(self.wrap(cb));
881930 };
882− });
883− }
884−
885− // Capture breadcrubms from any click that is unhandled / bubbled up all the way
886− // to the document. Do this before we instrument addEventListener.
887− if (this._hasDocument) {
888− document.addEventListener('click', self._breadcrumbEventHandler('click'));
889− document.addEventListener('keypress', self._keypressEventHandler());
931+ }, wrappedBuiltIns);
890932 }
891933
892934 // event targets borrowed from bugsnag-js:
@@ -896,7 +938,41 @@ Raven.prototype = { · 3 unmodified lines
896938 wrapEventTarget(eventTargets[i]);
897939 }
898940
899− if ('XMLHttpRequest' in window) {
941+ var $ = window.jQuery || window.$;
942+ if ($ && $.fn && $.fn.ready) {
943+ fill($.fn, 'ready', function (orig) {
944+ return function (fn) {
945+ return orig.call(this, self.wrap(fn));
946+ };
947+ }, wrappedBuiltIns);
948+ }
949+ },
950+
951+
952+ /**
953+ * Instrument browser built-ins w/ breadcrumb capturing
954+ * - XMLHttpRequests
955+ * - DOM interactions (click/typing)
956+ * - window.location changes
957+ * - console
958+ *
959+ * Can be disabled or individually configured via the `autoBreadcrumbs` config option
960+ */
961+ _instrumentBreadcrumbs: function () {
962+ var self = this;
963+ var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs;
964+
965+ var wrappedBuiltIns = self._wrappedBuiltIns;
966+
967+ function wrapProp(prop, xhr) {
968+ if (prop in xhr && isFunction(xhr[prop])) {
969+ fill(xhr, prop, function (orig) {
970+ return self.wrap(orig);
971+ }); // intentionally don't track filled methods on XHR instances
972+ }
973+ }
974+
975+ if (autoBreadcrumbs.xhr && 'XMLHttpRequest' in window) {
900976 var xhrproto = XMLHttpRequest.prototype;
901977 fill(xhrproto, 'open', function(origOpen) {
902978 return function (method, url) { // preserve arity
@@ -912,7 +988,7 @@ Raven.prototype = { · 9 unmodified lines
912988
913989 return origOpen.apply(this, arguments);
914990 };
915− });
991+ }, wrappedBuiltIns);
916992
917993 fill(xhrproto, 'send', function(origSend) {
918994 return function (data) { // preserve arity
@@ -941,7 +1017,7 @@ Raven.prototype = { · 22 unmodified lines
9411017 if ('onreadystatechange' in xhr && isFunction(xhr.onreadystatechange)) {
9421018 fill(xhr, 'onreadystatechange', function (orig) {
9431019 return self.wrap(orig, undefined, onreadystatechangeHandler);
944− }, true /* noUndo */);
1020+ } /* intentionally don't track this instrumentation */);
9451021 } else {
9461022 // if onreadystatechange wasn't actually set by the page on this xhr, we
9471023 // are free to set our own and capture the breadcrumb
@@ -950,11 +1026,31 @@ Raven.prototype = { · 2 unmodified lines
9501026
9511027 return origSend.apply(this, arguments);
9521028 };
953− });
1029+ }, wrappedBuiltIns);
1030+ }
1031+
1032+ // Capture breadcrumbs from any click that is unhandled / bubbled up all the way
1033+ // to the document. Do this before we instrument addEventListener.
1034+ if (autoBreadcrumbs.dom && this._hasDocument) {
1035+ if (document.addEventListener) {
1036+ document.addEventListener('click', self._breadcrumbEventHandler('click'), false);
1037+ document.addEventListener('keypress', self._keypressEventHandler(), false);
1038+ }
1039+ else {
1040+ // IE8 Compatibility
1041+ document.attachEvent('onclick', self._breadcrumbEventHandler('click'));
1042+ document.attachEvent('onkeypress', self._keypressEventHandler());
1043+ }
9541044 }
9551045
9561046 // record navigation (URL) changes
957− if ('history' in window && history.pushState) {
1047+ // NOTE: in Chrome App environment, touching history.pushState, *even inside
1048+ // a try/catch block*, will cause Chrome to output an error to console.error
1049+ // borrowed from: https://github.com/angular/angular.js/pull/13945/files
1050+ var chrome = window.chrome;
1051+ var isChromePackagedApp = chrome && chrome.app && chrome.app.runtime;
1052+ var hasPushState = !isChromePackagedApp && window.history && history.pushState;
1053+ if (autoBreadcrumbs.location && hasPushState) {
9581054 // TODO: remove onpopstate handler on uninstall()
9591055 var oldOnPopState = window.onpopstate;
9601056 window.onpopstate = function () {
@@ -969,7 +1065,7 @@ Raven.prototype = { · 8 unmodified lines
9691065 fill(history, 'pushState', function (origPushState) {
9701066 // note history.pushState.length is 0; intentionally not declaring
9711067 // params to preserve 0 arity
972− return function(/* state, title, url */) {
1068+ return function (/* state, title, url */) {
9731069 var url = arguments.length > 2 ? arguments[2] : undefined;
9741070
9751071 // url argument is optional
@@ -980,32 +1076,24 @@ Raven.prototype = { · 4 unmodified lines
9801076
9811077 return origPushState.apply(this, arguments);
9821078 };
983− });
1079+ }, wrappedBuiltIns);
9841080 }
9851081
986− // console
987− var consoleMethodCallback = function (msg, data) {
988− self.captureBreadcrumb({
989− message: msg,
990− level: data.level,
991− category: 'console'
992− });
993− };
1082+ if (autoBreadcrumbs.console && 'console' in window && console.log) {
1083+ // console
1084+ var consoleMethodCallback = function (msg, data) {
1085+ self.captureBreadcrumb({
1086+ message: msg,
1087+ level: data.level,
1088+ category: 'console'
1089+ });
1090+ };
9941091
995− if ('console' in window && console.log) {
9961092 each(['debug', 'info', 'warn', 'error', 'log'], function (_, level) {
9971093 wrapConsoleMethod(console, level, consoleMethodCallback);
9981094 });
9991095 }
10001096
1001− var $ = window.jQuery || window.$;
1002− if ($ && $.fn && $.fn.ready) {
1003− fill($.fn, 'ready', function (orig) {
1004− return function (fn) {
1005− return orig.call(this, self.wrap(fn));
1006− };
1007− });
1008− }
10091097 },
10101098
10111099 _restoreBuiltIns: function () {
@@ -1106,13 +1194,7 @@ Raven.prototype = { · 94 unmodified lines
11061194 lineno: frame.line,
11071195 colno: frame.column,
11081196 'function': frame.func || '?'
1109− }, context = this._extractContextFromFrame(frame), i;
1110−
1111− if (context) {
1112− var keys = ['pre_context', 'context_line', 'post_context'];
1113− i = 3;
1114− while (i--) normalized[keys[i]] = context[i];
1115− }
1197+ };
11161198
11171199 normalized.in_app = !( // determine if an exception came from outside of our app
11181200 // first we check the global includePaths list.
@@ -1126,55 +1208,12 @@ Raven.prototype = { · 7 unmodified lines
11261208 return normalized;
11271209 },
11281210
1129− _extractContextFromFrame: function(frame) {
1130− // immediately check if we should even attempt to parse a context
1131− if (!frame.context || !this._globalOptions.fetchContext) return;
1132−
1133− var context = frame.context,
1134− pivot = ~~(context.length / 2),
1135− i = context.length, isMinified = false;
1136−
1137− while (i--) {
1138− // We're making a guess to see if the source is minified or not.
1139− // To do that, we make the assumption if *any* of the lines passed
1140− // in are greater than 300 characters long, we bail.
1141− // Sentry will see that there isn't a context
1142− if (context[i].length > 300) {
1143− isMinified = true;
1144− break;
1145− }
1146− }
1147−
1148− if (isMinified) {
1149− // The source is minified and we don't know which column. Fuck it.
1150− if (isUndefined(frame.column)) return;
1151−
1152− // If the source is minified and has a frame column
1153− // we take a chunk of the offending line to hopefully shed some light
1154− return [
1155− [], // no pre_context
1156− context[pivot].substr(frame.column, 50), // grab 50 characters, starting at the offending column
1157− [] // no post_context
1158− ];
1159− }
1160−
1161− return [
1162− context.slice(0, pivot), // pre_context
1163− context[pivot], // context_line
1164− context.slice(pivot + 1) // post_context
1165− ];
1166− },
1167−
11681211 _processException: function(type, message, fileurl, lineno, frames, options) {
1169− var stacktrace, fullMessage;
1212+ var stacktrace;
11701213
11711214 if (!!this._globalOptions.ignoreErrors.test && this._globalOptions.ignoreErrors.test(message)) return;
11721215
11731216 message += '';
1174− message = truncate(message, this._globalOptions.maxMessageLength);
1175−
1176− fullMessage = (type ? type + ': ' : '') + message;
1177− fullMessage = truncate(fullMessage, this._globalOptions.maxMessageLength);
11781217
11791218 if (frames && frames.length) {
11801219 fileurl = frames[0].filename || fileurl;
@@ -1204,8 +1243,7 @@ Raven.prototype = { · 23 unmodified lines
12041243 stacktrace: stacktrace
12051244 }]
12061245 },
1207− culprit: fileurl,
1208− message: fullMessage
1246+ culprit: fileurl
12091247 }, options);
12101248
12111249 // Fire away!
@@ -1216,7 +1254,9 @@ Raven.prototype = { · 4 unmodified lines
12161254 // For now, we only want to truncate the two different messages
12171255 // but this could/should be expanded to just trim everything
12181256 var max = this._globalOptions.maxMessageLength;
1219− data.message = truncate(data.message, max);
1257+ if (data.message) {
1258+ data.message = truncate(data.message, max);
1259+ }
12201260 if (data.exception) {
12211261 var exception = data.exception.values[0];
12221262 exception.value = truncate(exception.value, max);
@@ -1247,8 +1287,6 @@ Raven.prototype = { · 24 unmodified lines
12471287
12481288
12491289 _send: function(data) {
1250− var self = this;
1251−
12521290 var globalOptions = this._globalOptions;
12531291
12541292 var baseData = {
@@ -1286,6 +1324,9 @@ Raven.prototype = { · 31 unmodified lines
12861324 data.user = this._globalContext.user;
12871325 }
12881326
1327+ // Include the environment if it's defined in globalOptions
1328+ if (globalOptions.environment) data.environment = globalOptions.environment;
1329+
12891330 // Include the release if it's defined in globalOptions
12901331 if (globalOptions.release) data.release = globalOptions.release;
12911332
@@ -1306,6 +1347,13 @@ Raven.prototype = { · 14 unmodified lines
13061347 return;
13071348 }
13081349
1350+ this._sendProcessedPayload(data);
1351+ },
1352+
1353+ _sendProcessedPayload: function(data, callback) {
1354+ var self = this;
1355+ var globalOptions = this._globalOptions;
1356+
13091357 // Send along an event_id if not explicitly passed.
13101358 // This event_id can be used to reference the error within Sentry itself.
13111359 // Set lastEventId after we know the error should actually be sent
@@ -1327,10 +1375,14 @@ Raven.prototype = { · 15 unmodified lines
13271375 auth.sentry_secret = this._globalSecret;
13281376 }
13291377
1378+ var exception = data.exception && data.exception.values[0];
13301379 this.captureBreadcrumb({
13311380 category: 'sentry',
1332− message: data.message,
1333− event_id: data.event_id
1381+ message: exception
1382+ ? (exception.type ? exception.type + ': ' : '') + exception.value
1383+ : data.message,
1384+ event_id: data.event_id,
1385+ level: data.level || 'error' // presume error unless specified
13341386 });
13351387
13361388 var url = this._globalEndpoint;
@@ -1344,12 +1396,15 @@ Raven.prototype = { · 7 unmodified lines
13441396 data: data,
13451397 src: url
13461398 });
1399+ callback && callback();
13471400 },
1348− onError: function failure() {
1401+ onError: function failure(error) {
13491402 self._triggerEvent('failure', {
13501403 data: data,
13511404 src: url
13521405 });
1406+ error = error || new Error('Raven send failed (no additional details provided)');
1407+ callback && callback(error);
13531408 }
13541409 });
13551410 },
@@ -1371,7 +1426,7 @@ Raven.prototype = { · 15 unmodified lines
13711426 opts.onSuccess();
13721427 }
13731428 } else if (opts.onError) {
1374− opts.onError();
1429+ opts.onError(new Error('Sentry error code: ' + request.status));
13751430 }
13761431 }
13771432
@@ -1395,14 +1450,7 @@ Raven.prototype = { · 17 unmodified lines
13951450 // NOTE: auth is intentionally sent as part of query string (NOT as custom
13961451 // HTTP header) so as to avoid preflight CORS requests
13971452 request.open('POST', url + '?' + urlencode(opts.auth));
1398− request.send(JSON.stringify(opts.data));
1399− },
1400−
1401− // Note: this is shitty, but I can't figure out how to get
1402− // sinon to stub document.createElement without breaking everything
1403− // so this wrapper is just so I can stub it for tests.
1404− _newImage: function() {
1405− return document.createElement('img');
1453+ request.send(stringify(opts.data));
14061454 },
14071455
14081456 _logDebug: function(level) {
@@ -1431,7 +1479,7 @@ Raven.prototype.setReleaseContext = Raven.prototype.setRelease; · 22 unmodified lines
14311479
14321480 module.exports = Raven;
14331481
1434−},{"1":1,"2":2,"5":5,"6":6}],4:[function(_dereq_,module,exports){
1482+},{"1":1,"2":2,"3":3,"6":6,"7":7}],5:[function(_dereq_,module,exports){
14351483 /**
14361484 * Enforces a single instance of the Raven client, and the
14371485 * main entry point for Raven. If you are a consumer of the
@@ -1440,7 +1488,7 @@ module.exports = Raven; · 2 unmodified lines
14401488
14411489 'use strict';
14421490
1443−var RavenConstructor = _dereq_(3);
1491+var RavenConstructor = _dereq_(4);
14441492
14451493 var _Raven = window.Raven;
14461494
@@ -1461,7 +1509,7 @@ Raven.afterLoad(); · 14 unmodified lines
14611509
14621510 module.exports = Raven;
14631511
1464−},{"3":3}],5:[function(_dereq_,module,exports){
1512+},{"4":4}],6:[function(_dereq_,module,exports){
14651513 /*eslint no-extra-parens:0*/
14661514 'use strict';
14671515
@@ -1700,6 +1748,21 @@ function htmlElementAsString(elem) { · 232 unmodified lines
17001748 return out.join('');
17011749 }
17021750
1751+/**
1752+ * Polyfill a method
1753+ * @param obj object e.g. `document`
1754+ * @param name method name present on object e.g. `addEventListener`
1755+ * @param replacement replacement function
1756+ * @param track {optional} record instrumentation to an array
1757+ */
1758+function fill(obj, name, replacement, track) {
1759+ var orig = obj[name];
1760+ obj[name] = replacement(orig);
1761+ if (track) {
1762+ track.push([obj, name, orig]);
1763+ }
1764+}
1765+
17031766 module.exports = {
17041767 isUndefined: isUndefined,
17051768 isFunction: isFunction,
@@ -1716,13 +1779,14 @@ module.exports = { · 10 unmodified lines
17161779 uuid4: uuid4,
17171780 htmlTreeAsString: htmlTreeAsString,
17181781 htmlElementAsString: htmlElementAsString,
1719− parseUrl: parseUrl
1782+ parseUrl: parseUrl,
1783+ fill: fill
17201784 };
17211785
1722−},{}],6:[function(_dereq_,module,exports){
1786+},{}],7:[function(_dereq_,module,exports){
17231787 'use strict';
17241788
1725−var utils = _dereq_(5);
1789+var utils = _dereq_(6);
17261790
17271791 var hasKey = utils.hasKey;
17281792 var isString = utils.isString;
@@ -1734,10 +1798,7 @@ var isUndefined = utils.isUndefined; · 5 unmodified lines
17341798 */
17351799
17361800 var TraceKit = {
1737− remoteFetching: false,
17381801 collectWindowErrors: true,
1739− // 3 lines before, the offending line, 3 lines after
1740− linesOfContext: 7,
17411802 debug: false
17421803 };
17431804
@@ -1897,7 +1958,6 @@ TraceKit.report = (function reportModuleWrapper() { · 153 unmodified lines
18971958 }
18981959
18991960 location.func = UNKNOWN_FUNCTION;
1900− location.context = null;
19011961
19021962 stack = {
19031963 'name': name,
@@ -2000,7 +2060,6 @@ TraceKit.report = (function reportModuleWrapper() { · 96 unmodified lines
20002060 * s.stack[i].args - arguments passed to the function, if known
20012061 * s.stack[i].line - line number, if known
20022062 * s.stack[i].column - column number, if known
2003− * s.stack[i].context - an array of source code lines; the middle element corresponds to the correct line#
20042063 *
20052064 * Supports:
20062065 * - Firefox: full stack trace with line numbers and unreliable column
@@ -2109,7 +2168,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 102 unmodified lines
21092168
21102169 var chrome = /^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|<anonymous>).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,
21112170 gecko = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|\[native).*?)(?::(\d+))?(?::(\d+))?\s*$/i,
2112− winjs = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:ms-appx|https?|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,
2171+ winjs = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,
21132172 lines = ex.stack.split('\n'),
21142173 stack = [],
21152174 parts,
@@ -2150,10 +2209,6 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 34 unmodified lines
21502209 element.func = UNKNOWN_FUNCTION;
21512210 }
21522211
2153− if (element.line) {
2154− element.context = null;
2155− }
2156−
21572212 stack.push(element);
21582213 }
21592214
@@ -2219,7 +2274,6 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 59 unmodified lines
22192274 if (!element.func && element.line) {
22202275 element.func = UNKNOWN_FUNCTION;
22212276 }
2222− element.context = [lines[line + 1]];
22232277
22242278 stack.push(element);
22252279 }
@@ -2307,7 +2361,6 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 81 unmodified lines
23072361 if (!item.func) {
23082362 item.func = UNKNOWN_FUNCTION;
23092363 }
2310− item.context = [lines[line + 1]];
23112364
23122365 stack.push(item);
23132366 }
@@ -2357,7 +2410,6 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 43 unmodified lines
23572410 return false; // already in stack trace
23582411 } else if (!stackInfo.stack[0].line && stackInfo.stack[0].func === initial.func) {
23592412 stackInfo.stack[0].line = initial.line;
2360− stackInfo.stack[0].context = initial.context;
23612413 return false;
23622414 }
23632415 }
@@ -2512,5 +2564,5 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 148 unmodified lines
25122564
25132565 module.exports = TraceKit;
25142566
2515−},{"5":5}]},{},[4])(4)
2567+},{"6":6}]},{},[5])(5)
25162568 });