History

Raven.js 3.25.2 (30b6d4e)

https://github.com/getsentry/sentry-javascript/blob/d5e44e2cf87ccecefc9a07bc460f403b3a0f46fd/dist/raven.js Reformatted using Prettier.io

Simon Legner committed 2 years ago

Commit 91eb5251 parent 0dd0ad81 file · +1037 −125Browse files

Unified · Split

assets/javascripts/vendor/raven.js+1037−125
@@ -1,10 +1,10 @@
1−/*! Raven.js 3.20.1 (42adaf5) | github.com/getsentry/raven-js */
1+/*! Raven.js 3.25.2 (30b6d4e) | github.com/getsentry/raven-js */
22
33 /*
44 * Includes TraceKit
55 * https://github.com/getsentry/TraceKit
66 *
7− * Copyright 2017 Matt Robenolt and other contributors
7+ * Copyright 2018 Matt Robenolt and other contributors
88 * Released under the BSD license
99 * https://github.com/getsentry/raven-js/blob/master/LICENSE
1010 *
@@ -77,6 +77,8 @@ · 66 unmodified lines
7777 ],
7878 2: [
7979 function (_dereq_, module, exports) {
80+ var utils = _dereq_(5);
81+
8082 var wrapMethod = function (console, level, callback) {
8183 var originalConsoleLevel = console[level];
8284 var originalConsole = console;
@@ -90,7 +92,7 @@ · 7 unmodified lines
9092 console[level] = function () {
9193 var args = [].slice.call(arguments);
9294
93− var msg = "" + args.join(" ");
95+ var msg = utils.safeJoin(args, " ");
9496 var data = {
9597 level: sentryLevel,
9698 logger: "console",
@@ -102,7 +104,7 @@ · 5 unmodified lines
102104 // Default browsers message
103105 msg =
104106 "Assertion failed: " +
105− (args.slice(1).join(" ") || "console.assert");
107+ (utils.safeJoin(args.slice(1), " ") || "console.assert");
106108 data.extra.arguments = args.slice(1);
107109 callback && callback(msg, data);
108110 }
@@ -127,7 +129,7 @@ · 18 unmodified lines
127129 wrapMethod: wrapMethod,
128130 };
129131 },
130− {},
132+ { 5: 5 },
131133 ],
132134 3: [
133135 function (_dereq_, module, exports) {
@@ -136,12 +138,16 @@ · 2 unmodified lines
136138
137139 var TraceKit = _dereq_(6);
138140 var stringify = _dereq_(7);
141+ var md5 = _dereq_(8);
139142 var RavenConfigError = _dereq_(1);
140143
141144 var utils = _dereq_(5);
145+ var isErrorEvent = utils.isErrorEvent;
146+ var isDOMError = utils.isDOMError;
147+ var isDOMException = utils.isDOMException;
142148 var isError = utils.isError;
143149 var isObject = utils.isObject;
144− var isErrorEvent = utils.isErrorEvent;
150+ var isPlainObject = utils.isPlainObject;
145151 var isUndefined = utils.isUndefined;
146152 var isFunction = utils.isFunction;
147153 var isString = utils.isString;
@@ -160,6 +166,11 @@ · 12 unmodified lines
160166 var isSameStacktrace = utils.isSameStacktrace;
161167 var parseUrl = utils.parseUrl;
162168 var fill = utils.fill;
169+ var supportsFetch = utils.supportsFetch;
170+ var supportsReferrerPolicy = utils.supportsReferrerPolicy;
171+ var serializeKeysForMessage = utils.serializeKeysForMessage;
172+ var serializeException = utils.serializeException;
173+ var sanitize = utils.sanitize;
163174
164175 var wrapConsoleMethod = _dereq_(2).wrapMethod;
165176
@@ -207,20 +218,33 @@ · 41 unmodified lines
207218 this._globalProject = null;
208219 this._globalContext = {};
209220 this._globalOptions = {
221+ // SENTRY_RELEASE can be injected by https://github.com/getsentry/sentry-webpack-plugin
222+ release: _window.SENTRY_RELEASE && _window.SENTRY_RELEASE.id,
210223 logger: "javascript",
211224 ignoreErrors: [],
212225 ignoreUrls: [],
213226 whitelistUrls: [],
214227 includePaths: [],
228+ headers: null,
215229 collectWindowErrors: true,
230+ captureUnhandledRejections: true,
216231 maxMessageLength: 0,
217−
218232 // By default, truncates URL values to 250 chars
219233 maxUrlLength: 250,
220234 stackTraceLimit: 50,
221235 autoBreadcrumbs: true,
222236 instrument: true,
223237 sampleRate: 1,
238+ sanitizeKeys: [],
239+ };
240+ this._fetchDefaults = {
241+ method: "POST",
242+ keepalive: true,
243+ // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default
244+ // https://caniuse.com/#feat=referrer-policy
245+ // It doesn't. And it throw exception instead of ignoring this parameter...
246+ // REF: https://github.com/getsentry/raven-js/issues/1233
247+ referrerPolicy: supportsReferrerPolicy() ? "origin" : "",
224248 };
225249 this._ignoreOnError = 0;
226250 this._isRavenInstalled = false;
@@ -257,7 +281,7 @@ · 30 unmodified lines
257281 // webpack (using a build step causes webpack #1617). Grunt verifies that
258282 // this value matches package.json during build.
259283 // See: https://github.com/getsentry/raven-js/issues/465
260− VERSION: "3.20.1",
284+ VERSION: "3.25.2",
261285
262286 debug: false,
263287
@@ -376,6 +400,10 @@ · 112 unmodified lines
376400 self._handleOnErrorStackInfo.apply(self, arguments);
377401 });
378402
403+ if (self._globalOptions.captureUnhandledRejections) {
404+ self._attachPromiseRejectionHandler();
405+ }
406+
379407 self._patchFunctionToString();
380408
381409 if (
@@ -538,7 +566,7 @@ · 156 unmodified lines
538566 return wrapped;
539567 },
540568
541− /*
569+ /**
542570 * Uninstalls the global error handler.
543571 *
544572 * @return {Raven}
@@ -546,8 +574,10 @@ · 1 unmodified line
546574 uninstall: function () {
547575 TraceKit.report.uninstall();
548576
577+ this._detachPromiseRejectionHandler();
549578 this._unpatchFunctionToString();
550579 this._restoreBuiltIns();
580+ this._restoreConsole();
551581
552582 Error.stackTraceLimit = this._originalErrorStackTraceLimit;
553583 this._isRavenInstalled = false;
@@ -555,7 +585,58 @@ · 1 unmodified line
555585 return this;
556586 },
557587
558− /*
588+ /**
589+ * Callback used for `unhandledrejection` event
590+ *
591+ * @param {PromiseRejectionEvent} event An object containing
592+ * promise: the Promise that was rejected
593+ * reason: the value with which the Promise was rejected
594+ * @return void
595+ */
596+ _promiseRejectionHandler: function (event) {
597+ this._logDebug(
598+ "debug",
599+ "Raven caught unhandled promise rejection:",
600+ event,
601+ );
602+ this.captureException(event.reason, {
603+ extra: {
604+ unhandledPromiseRejection: true,
605+ },
606+ });
607+ },
608+
609+ /**
610+ * Installs the global promise rejection handler.
611+ *
612+ * @return {raven}
613+ */
614+ _attachPromiseRejectionHandler: function () {
615+ this._promiseRejectionHandler =
616+ this._promiseRejectionHandler.bind(this);
617+ _window.addEventListener &&
618+ _window.addEventListener(
619+ "unhandledrejection",
620+ this._promiseRejectionHandler,
621+ );
622+ return this;
623+ },
624+
625+ /**
626+ * Uninstalls the global promise rejection handler.
627+ *
628+ * @return {raven}
629+ */
630+ _detachPromiseRejectionHandler: function () {
631+ _window.removeEventListener &&
632+ _window.removeEventListener(
633+ "unhandledrejection",
634+ this._promiseRejectionHandler,
635+ );
636+ return this;
637+ },
638+
639+ /**
559640 * Manually capture an exception and send it over to Sentry
560641 *
561642 * @param {error} ex An exception to be logged
@@ -563,30 +644,60 @@ · 1 unmodified line
563644 * @return {Raven}
564645 */
565646 captureException: function (ex, options) {
566− // Cases for sending ex as a message, rather than an exception
567− var isNotError = !isError(ex);
568− var isNotErrorEvent = !isErrorEvent(ex);
569− var isErrorEventWithoutError = isErrorEvent(ex) && !ex.error;
647+ options = objectMerge(
648+ { trimHeadFrames: 0 },
649+ options ? options : {},
650+ );
570651
571− if (
572− (isNotError && isNotErrorEvent) ||
573− isErrorEventWithoutError
574− ) {
652+ if (isErrorEvent(ex) && ex.error) {
653+ // If it is an ErrorEvent with `error` property, extract it to get actual Error
654+ ex = ex.error;
655+ } else if (isDOMError(ex) || isDOMException(ex)) {
656+ // If it is a DOMError or DOMException (which are legacy APIs, but still supported in some browsers)
657+ // then we just extract the name and message, as they don't provide anything else
658+ // https://developer.mozilla.org/en-US/docs/Web/API/DOMError
659+ // https://developer.mozilla.org/en-US/docs/Web/API/DOMException
660+ var name =
661+ ex.name || (isDOMError(ex) ? "DOMError" : "DOMException");
662+ var message = ex.message ? name + ": " + ex.message : name;
663+
664+ return this.captureMessage(
665+ message,
666+ objectMerge(options, {
667+ // neither DOMError or DOMException provide stack trace and we most likely wont get it this way as well
668+ // but it's barely any overhead so we may at least try
669+ stacktrace: true,
670+ trimHeadFrames: options.trimHeadFrames + 1,
671+ }),
672+ );
673+ } else if (isError(ex)) {
674+ // we have a real Error object
675+ ex = ex;
676+ } else if (isPlainObject(ex)) {
677+ // If it is plain Object, serialize it manually and extract options
678+ // This will allow us to group events based on top-level keys
679+ // which is much better than creating new group when any key/value change
680+ options = this._getCaptureExceptionOptionsFromPlainObject(
681+ options,
682+ ex,
683+ );
684+ ex = new Error(options.message);
685+ } else {
686+ // If none of previous checks were valid, then it means that
687+ // it's not a DOMError/DOMException
688+ // it's not a plain Object
689+ // it's not a valid ErrorEvent (one with an error property)
690+ // it's not an Error
691+ // So bail out and capture it as a simple message:
575692 return this.captureMessage(
576693 ex,
577− objectMerge(
578− {
579− trimHeadFrames: 1,
580− stacktrace: true, // if we fall back to captureMessage, default to attempting a new trace
581− },
582− options,
583− ),
694+ objectMerge(options, {
695+ stacktrace: true, // if we fall back to captureMessage, default to attempting a new trace
696+ trimHeadFrames: options.trimHeadFrames + 1,
697+ }),
584698 );
585699 }
586700
587− // Get actual Error from ErrorEvent
588− if (isErrorEvent(ex)) ex = ex.error;
589−
590701 // Store the raw exception object for potential debugging and introspection
591702 this._lastCapturedException = ex;
592703
@@ -607,6 +718,23 @@ · 14 unmodified lines
607718 return this;
608719 },
609720
721+ _getCaptureExceptionOptionsFromPlainObject: function (
722+ currentOptions,
723+ ex,
724+ ) {
725+ var exKeys = Object.keys(ex).sort();
726+ var options = objectMerge(currentOptions, {
727+ message:
728+ "Non-Error exception captured with keys: " +
729+ serializeKeysForMessage(exKeys),
730+ fingerprint: [md5(exKeys)],
731+ extra: currentOptions.extra || {},
732+ });
733+ options.extra.__serialized__ = serializeException(ex);
734+
735+ return options;
736+ },
737+
610738 /*
611739 * Manually send a message to Sentry
612740 *
@@ -626,10 +754,11 @@ · 13 unmodified lines
626754 }
627755
628756 options = options || {};
757+ msg = msg + ""; // Make sure it's actually a string
629758
630759 var data = objectMerge(
631760 {
632− message: msg + "", // Make sure it's actually a string
761+ message: msg,
633762 },
634763 options,
635764 );
@@ -651,6 +780,17 @@ · 15 unmodified lines
651780
652781 // stack[0] is `throw new Error(msg)` call itself, we are interested in the frame that was just before that, stack[1]
653782 var initialCall = isArray(stack.stack) && stack.stack[1];
783+
784+ // if stack[1] is `Raven.captureException`, it means that someone passed a string to it and we redirected that call
785+ // to be handled by `captureMessage`, thus `initialCall` is the 3rd one, not 2nd
786+ // initialCall => captureException(string) => captureMessage(string)
787+ if (
788+ initialCall &&
789+ initialCall.func === "Raven.captureException"
790+ ) {
791+ initialCall = stack.stack[2];
792+ }
793+
654794 var fileurl = (initialCall && initialCall.url) || "";
655795
656796 if (
@@ -671,18 +811,21 @@ · 14 unmodified lines
671811 this._globalOptions.stacktrace ||
672812 (options && options.stacktrace)
673813 ) {
814+ // fingerprint on msg, not stack trace (legacy behavior, could be revisited)
815+ data.fingerprint =
816+ data.fingerprint == null ? msg : data.fingerprint;
817+
674818 options = objectMerge(
675819 {
676− // fingerprint on msg, not stack trace (legacy behavior, could be
677− // revisited)
678− fingerprint: msg,
679− // since we know this is a synthetic trace, the top N-most frames
680− // MUST be from Raven.js, so mark them as in_app later by setting
681− // trimHeadFrames
682− trimHeadFrames: (options.trimHeadFrames || 0) + 1,
820+ trimHeadFrames: 0,
683821 },
684822 options,
685823 );
824+ // Since we know this is a synthetic trace, the top frame (this function call)
825+ // MUST be from Raven.js, so mark it for trimming
826+ // We add to the trim counter so that callers can choose to trim extra frames, such
827+ // as utility functions.
828+ options.trimHeadFrames += 1;
686829
687830 var frames = this._prepareFrames(stack, options);
688831 data.stacktrace = {
@@ -691,6 +834,13 @@ · 2 unmodified lines
691834 };
692835 }
693836
837+ // Make sure that fingerprint is always wrapped in an array
838+ if (data.fingerprint) {
839+ data.fingerprint = isArray(data.fingerprint)
840+ ? data.fingerprint
841+ : [data.fingerprint];
842+ }
843+
694844 // Fire away!
695845 this._send(data);
696846
@@ -976,7 +1126,7 @@ · 279 unmodified lines
9761126 },
9771127
9781128 _triggerEvent: function (eventType, options) {
979− // NOTE: `event` is a native browser thing, so let's avoid conflicting with it
1129+ // NOTE: `event` is a native browser thing, so let's avoid conflicting wiht it
9801130 var evt, key;
9811131
9821132 if (!this._hasDocument) return;
@@ -1290,7 +1440,7 @@ · 307 unmodified lines
12901440
12911441 fill(_window, "setTimeout", wrapTimeFn, wrappedBuiltIns);
12921442 fill(_window, "setInterval", wrapTimeFn, wrappedBuiltIns);
1293− if (_requestAnimationFrame) {
1443+ if (_window.requestAnimationFrame) {
12941444 fill(
12951445 _window,
12961446 "requestAnimationFrame",
@@ -1365,7 +1515,8 @@ · 68 unmodified lines
13651515 }
13661516
13671517 if (autoBreadcrumbs.xhr && "XMLHttpRequest" in _window) {
1368− var xhrproto = XMLHttpRequest.prototype;
1518+ var xhrproto =
1519+ _window.XMLHttpRequest && _window.XMLHttpRequest.prototype;
13691520 fill(
13701521 xhrproto,
13711522 "open",
@@ -1395,7 +1546,7 @@ · 23 unmodified lines
13951546 xhrproto,
13961547 "send",
13971548 function (origSend) {
1398− return function (data) {
1549+ return function () {
13991550 // preserve arity
14001551 var xhr = this;
14011552
@@ -1450,12 +1601,12 @@ · 48 unmodified lines
14501601 );
14511602 }
14521603
1453− if (autoBreadcrumbs.xhr && "fetch" in _window) {
1604+ if (autoBreadcrumbs.xhr && supportsFetch()) {
14541605 fill(
14551606 _window,
14561607 "fetch",
14571608 function (origFetch) {
1458− return function (fn, t) {
1609+ return function () {
14591610 // preserve arity
14601611 // Make a copy of the arguments to prevent deoptimization
14611612 // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments
@@ -1482,6 +1633,11 @@ · 20 unmodified lines
14821633 url = "" + fetchInput;
14831634 }
14841635
1636+ // if Sentry key appears in URL, don't capture, as it's our own request
1637+ if (url.indexOf(self._globalKey) !== -1) {
1638+ return origFetch.apply(this, args);
1639+ }
1640+
14851641 if (args[1] && args[1].method) {
14861642 method = args[1].method;
14871643 }
@@ -1492,18 +1648,29 @@ · 4 unmodified lines
14921648 status_code: null,
14931649 };
14941650
1495− self.captureBreadcrumb({
1496− type: "http",
1497− category: "fetch",
1498− data: fetchData,
1499− });
1500−
15011651 return origFetch
15021652 .apply(this, args)
15031653 .then(function (response) {
15041654 fetchData.status_code = response.status;
15051655
1656+ self.captureBreadcrumb({
1657+ type: "http",
1658+ category: "fetch",
1659+ data: fetchData,
1660+ });
1661+
15061662 return response;
1663+ })
1664+ ["catch"](function (err) {
1665+ // if there is an error performing the request
1666+ self.captureBreadcrumb({
1667+ type: "http",
1668+ category: "fetch",
1669+ data: fetchData,
1670+ level: "error",
1671+ });
1672+
1673+ throw err;
15071674 });
15081675 };
15091676 },
@@ -1525,7 +1692,7 @@ · 15 unmodified lines
15251692 self._keypressEventHandler(),
15261693 false,
15271694 );
1528− } else {
1695+ } else if (_document.attachEvent) {
15291696 // IE8 Compatibility
15301697 _document.attachEvent(
15311698 "onclick",
@@ -1548,8 +1715,8 @@ · 16 unmodified lines
15481715 var hasPushAndReplaceState =
15491716 !isChromePackagedApp &&
15501717 _window.history &&
1551− history.pushState &&
1552− history.replaceState;
1718+ _window.history.pushState &&
1719+ _window.history.replaceState;
15531720 if (autoBreadcrumbs.location && hasPushAndReplaceState) {
15541721 // TODO: remove onpopstate handler on uninstall()
15551722 var oldOnPopState = _window.onpopstate;
@@ -1579,13 +1746,13 @@ · 23 unmodified lines
15791746 };
15801747
15811748 fill(
1582− history,
1749+ _window.history,
15831750 "pushState",
15841751 historyReplacementFunction,
15851752 wrappedBuiltIns,
15861753 );
15871754 fill(
1588− history,
1755+ _window.history,
15891756 "replaceState",
15901757 historyReplacementFunction,
15911758 wrappedBuiltIns,
@@ -1629,6 +1796,14 @@ · 37 unmodified lines
16291796 }
16301797 },
16311798
1799+ _restoreConsole: function () {
1800+ // eslint-disable-next-line guard-for-in
1801+ for (var method in this._originalConsoleMethods) {
1802+ this._originalConsole[method] =
1803+ this._originalConsoleMethods[method];
1804+ }
1805+ },
1806+
16321807 _drainPlugins: function () {
16331808 var self = this;
16341809
@@ -1822,7 +1997,7 @@ · 187 unmodified lines
18221997 },
18231998 ],
18241999 },
1825− culprit: fileurl,
2000+ transaction: fileurl,
18262001 },
18272002 options,
18282003 );
@@ -1905,18 +2080,18 @@ · 76 unmodified lines
19052080
19062081 if (this._hasNavigator && _navigator.userAgent) {
19072082 httpData.headers = {
1908− "User-Agent": navigator.userAgent,
2083+ "User-Agent": _navigator.userAgent,
19092084 };
19102085 }
19112086
1912− if (this._hasDocument) {
1913− if (_document.location && _document.location.href) {
1914− httpData.url = _document.location.href;
1915− }
1916− if (_document.referrer) {
1917− if (!httpData.headers) httpData.headers = {};
1918− httpData.headers.Referer = _document.referrer;
1919− }
2087+ // Check in `window` instead of `document`, as we may be in ServiceWorker environment
2088+ if (_window.location && _window.location.href) {
2089+ httpData.url = _window.location.href;
2090+ }
2091+
2092+ if (this._hasDocument && _document.referrer) {
2093+ if (!httpData.headers) httpData.headers = {};
2094+ httpData.headers.Referer = _document.referrer;
19202095 }
19212096
19222097 return httpData;
@@ -1949,7 +2124,7 @@ · 26 unmodified lines
19492124 if (
19502125 !last ||
19512126 current.message !== last.message || // defined for captureMessage
1952− current.culprit !== last.culprit // defined for captureException/onerror
2127+ current.transaction !== last.transaction // defined for captureException/onerror
19532128 )
19542129 return false;
19552130
@@ -1982,8 +2157,14 @@ · 26 unmodified lines
19822157 try {
19832158 // If Retry-After is not in Access-Control-Expose-Headers, most
19842159 // browsers will throw an exception trying to access it
1985− retry = request.getResponseHeader("Retry-After");
1986− retry = parseInt(retry, 10) * 1000; // Retry-After is returned in seconds
2160+ if (supportsFetch()) {
2161+ retry = request.headers.get("Retry-After");
2162+ } else {
2163+ retry = request.getResponseHeader("Retry-After");
2164+ }
2165+
2166+ // Retry-After is returned in seconds
2167+ retry = parseInt(retry, 10) * 1000;
19872168 } catch (e) {
19882169 /* eslint no-empty:0 */
19892170 }
@@ -2037,9 +2218,6 @@ · 47 unmodified lines
20372218 };
20382219 }
20392220
2040− // If there are no tags/extra, strip the key from the payload alltogther.
2041− if (isEmptyObject(data.tags)) delete data.tags;
2042−
20432221 if (this._globalContext.user) {
20442222 // sentry.interfaces.User
20452223 data.user = this._globalContext.user;
@@ -2056,6 +2234,19 @@ · 10 unmodified lines
20562234 if (globalOptions.serverName)
20572235 data.server_name = globalOptions.serverName;
20582236
2237+ data = this._sanitizeData(data);
2238+
2239+ // Cleanup empty properties before sending them to the server
2240+ Object.keys(data).forEach(function (key) {
2241+ if (
2242+ data[key] == null ||
2243+ data[key] === "" ||
2244+ isEmptyObject(data[key])
2245+ ) {
2246+ delete data[key];
2247+ }
2248+ });
2249+
20592250 if (isFunction(globalOptions.dataCallback)) {
20602251 data = globalOptions.dataCallback(data) || data;
20612252 }
@@ -2093,6 +2284,10 @@ · 31 unmodified lines
20932284 }
20942285 },
20952286
2287+ _sanitizeData: function (data) {
2288+ return sanitize(data, this._globalOptions.sanitizeKeys);
2289+ },
2290+
20962291 _getUuid: function () {
20972292 return uuid4();
20982293 },
@@ -2197,6 +2392,61 @@ · 98 unmodified lines
21972392 },
21982393
21992394 _makeRequest: function (opts) {
2395+ // Auth is intentionally sent as part of query string (NOT as custom HTTP header) to avoid preflight CORS requests
2396+ var url = opts.url + "?" + urlencode(opts.auth);
2397+
2398+ var evaluatedHeaders = null;
2399+ var evaluatedFetchParameters = {};
2400+
2401+ if (opts.options.headers) {
2402+ evaluatedHeaders = this._evaluateHash(opts.options.headers);
2403+ }
2404+
2405+ if (opts.options.fetchParameters) {
2406+ evaluatedFetchParameters = this._evaluateHash(
2407+ opts.options.fetchParameters,
2408+ );
2409+ }
2410+
2411+ if (supportsFetch()) {
2412+ evaluatedFetchParameters.body = stringify(opts.data);
2413+
2414+ var defaultFetchOptions = objectMerge(
2415+ {},
2416+ this._fetchDefaults,
2417+ );
2418+ var fetchOptions = objectMerge(
2419+ defaultFetchOptions,
2420+ evaluatedFetchParameters,
2421+ );
2422+
2423+ if (evaluatedHeaders) {
2424+ fetchOptions.headers = evaluatedHeaders;
2425+ }
2426+
2427+ return _window
2428+ .fetch(url, fetchOptions)
2429+ .then(function (response) {
2430+ if (response.ok) {
2431+ opts.onSuccess && opts.onSuccess();
2432+ } else {
2433+ var error = new Error(
2434+ "Sentry error code: " + response.status,
2435+ );
2436+ // It's called request only to keep compatibility with XHR interface
2437+ // and not add more redundant checks in setBackoffState method
2438+ error.request = response;
2439+ opts.onError && opts.onError(error);
2440+ }
2441+ })
2442+ ["catch"](function () {
2443+ opts.onError &&
2444+ opts.onError(
2445+ new Error("Sentry error code: network unavailable"),
2446+ );
2447+ });
2448+ }
2449+
22002450 var request =
22012451 _window.XMLHttpRequest && new _window.XMLHttpRequest();
22022452 if (!request) return;
@@ -2208,8 +2458,6 @@ · 5 unmodified lines
22082458
22092459 if (!hasCORS) return;
22102460
2211− var url = opts.url;
2212−
22132461 if ("withCredentials" in request) {
22142462 request.onreadystatechange = function () {
22152463 if (request.readyState !== 4) {
@@ -2243,14 +2491,37 @@ · 27 unmodified lines
22432491 }
22442492 }
22452493
2246− // NOTE: auth is intentionally sent as part of query string (NOT as custom
2247− // HTTP header) so as to avoid preflight CORS requests
2248− request.open("POST", url + "?" + urlencode(opts.auth));
2494+ request.open("POST", url);
2495+
2496+ if (evaluatedHeaders) {
2497+ each(evaluatedHeaders, function (key, value) {
2498+ request.setRequestHeader(key, value);
2499+ });
2500+ }
2501+
22492502 request.send(stringify(opts.data));
22502503 },
22512504
2505+ _evaluateHash: function (hash) {
2506+ var evaluated = {};
2507+
2508+ for (var key in hash) {
2509+ if (hash.hasOwnProperty(key)) {
2510+ var value = hash[key];
2511+ evaluated[key] =
2512+ typeof value === "function" ? value() : value;
2513+ }
2514+ }
2515+
2516+ return evaluated;
2517+ },
2518+
22522519 _logDebug: function (level) {
2253− if (this._originalConsoleMethods[level] && this.debug) {
2520+ // We allow `Raven.debug` and `Raven.config(DSN, { debug: true })` to not make backward incompatible API change
2521+ if (
2522+ this._originalConsoleMethods[level] &&
2523+ (this.debug || this._globalOptions.debug)
2524+ ) {
22542525 // In IE<10 console methods do not have their own 'apply' method
22552526 Function.prototype.apply.call(
22562527 this._originalConsoleMethods[level],
@@ -2288,7 +2559,7 @@ · 31 unmodified lines
22882559 : {},
22892560 );
22902561 },
2291− { 1: 1, 2: 2, 5: 5, 6: 6, 7: 7 },
2562+ { 1: 1, 2: 2, 5: 5, 6: 6, 7: 7, 8: 8 },
22922563 ],
22932564 4: [
22942565 function (_dereq_, module, exports) {
@@ -2328,6 +2599,42 @@ · 33 unmodified lines
23282599 Raven.afterLoad();
23292600
23302601 module.exports = Raven;
2602+
2603+ /**
2604+ * DISCLAIMER:
2605+ *
2606+ * Expose `Client` constructor for cases where user want to track multiple "sub-applications" in one larger app.
2607+ * It's not meant to be used by a wide audience, so pleaaase make sure that you know what you're doing before using it.
2608+ * Accidentally calling `install` multiple times, may result in an unexpected behavior that's very hard to debug.
2609+ *
2610+ * It's called `Client' to be in-line with Raven Node implementation.
2611+ *
2612+ * HOWTO:
2613+ *
2614+ * import Raven from 'raven-js';
2615+ *
2616+ * const someAppReporter = new Raven.Client();
2617+ * const someOtherAppReporter = new Raven.Client();
2618+ *
2619+ * someAppReporter.config('__DSN__', {
2620+ * ...config goes here
2621+ * });
2622+ *
2623+ * someOtherAppReporter.config('__OTHER_DSN__', {
2624+ * ...config goes here
2625+ * });
2626+ *
2627+ * someAppReporter.captureMessage(...);
2628+ * someAppReporter.captureException(...);
2629+ * someAppReporter.captureBreadcrumb(...);
2630+ *
2631+ * someOtherAppReporter.captureMessage(...);
2632+ * someOtherAppReporter.captureException(...);
2633+ * someOtherAppReporter.captureBreadcrumb(...);
2634+ *
2635+ * It should "just work".
2636+ */
2637+ module.exports.Client = RavenConstructor;
23312638 }).call(
23322639 this,
23332640 typeof global !== "undefined"
@@ -2344,6 +2651,8 @@ · 10 unmodified lines
23442651 5: [
23452652 function (_dereq_, module, exports) {
23462653 (function (global) {
2654+ var stringify = _dereq_(7);
2655+
23472656 var _window =
23482657 typeof window !== "undefined"
23492658 ? window
@@ -2360,7 +2669,7 @@ · 10 unmodified lines
23602669 // Yanked from https://git.io/vS8DV re-used under CC0
23612670 // with some tiny modifications
23622671 function isError(value) {
2363− switch ({}.toString.call(value)) {
2672+ switch (Object.prototype.toString.call(value)) {
23642673 case "[object Error]":
23652674 return true;
23662675 case "[object Exception]":
@@ -2374,8 +2683,20 @@ · 7 unmodified lines
23742683
23752684 function isErrorEvent(value) {
23762685 return (
2377− supportsErrorEvent() &&
2378− {}.toString.call(value) === "[object ErrorEvent]"
2686+ Object.prototype.toString.call(value) === "[object ErrorEvent]"
2687+ );
2688+ }
2689+
2690+ function isDOMError(value) {
2691+ return (
2692+ Object.prototype.toString.call(value) === "[object DOMError]"
2693+ );
2694+ }
2695+
2696+ function isDOMException(value) {
2697+ return (
2698+ Object.prototype.toString.call(value) ===
2699+ "[object DOMException]"
23792700 );
23802701 }
23812702
@@ -2387,6 +2708,10 @@ · 5 unmodified lines
23872708 return typeof what === "function";
23882709 }
23892710
2711+ function isPlainObject(what) {
2712+ return Object.prototype.toString.call(what) === "[object Object]";
2713+ }
2714+
23902715 function isString(what) {
23912716 return Object.prototype.toString.call(what) === "[object String]";
23922717 }
@@ -2396,6 +2721,8 @@ · 3 unmodified lines
23962721 }
23972722
23982723 function isEmptyObject(what) {
2724+ if (!isPlainObject(what)) return false;
2725+
23992726 for (var _ in what) {
24002727 if (what.hasOwnProperty(_)) {
24012728 return false;
@@ -2413,6 +2740,59 @@ · 11 unmodified lines
24132740 }
24142741 }
24152742
2743+ function supportsDOMError() {
2744+ try {
2745+ new DOMError(""); // eslint-disable-line no-new
2746+ return true;
2747+ } catch (e) {
2748+ return false;
2749+ }
2750+ }
2751+
2752+ function supportsDOMException() {
2753+ try {
2754+ new DOMException(""); // eslint-disable-line no-new
2755+ return true;
2756+ } catch (e) {
2757+ return false;
2758+ }
2759+ }
2760+
2761+ function supportsFetch() {
2762+ if (!("fetch" in _window)) return false;
2763+
2764+ try {
2765+ new Headers(); // eslint-disable-line no-new
2766+ new Request(""); // eslint-disable-line no-new
2767+ new Response(); // eslint-disable-line no-new
2768+ return true;
2769+ } catch (e) {
2770+ return false;
2771+ }
2772+ }
2773+
2774+ // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default
2775+ // https://caniuse.com/#feat=referrer-policy
2776+ // It doesn't. And it throw exception instead of ignoring this parameter...
2777+ // REF: https://github.com/getsentry/raven-js/issues/1233
2778+ function supportsReferrerPolicy() {
2779+ if (!supportsFetch()) return false;
2780+
2781+ try {
2782+ // eslint-disable-next-line no-new
2783+ new Request("pickleRick", {
2784+ referrerPolicy: "origin",
2785+ });
2786+ return true;
2787+ } catch (e) {
2788+ return false;
2789+ }
2790+ }
2791+
2792+ function supportsPromiseRejectionEvent() {
2793+ return typeof PromiseRejectionEvent === "function";
2794+ }
2795+
24162796 function wrappedCallback(callback) {
24172797 function dataCallback(data, original) {
24182798 var normalizedData = callback(data) || data;
@@ -2470,9 +2850,15 @@ · 51 unmodified lines
24702850 }
24712851
24722852 function truncate(str, max) {
2473− return !max || str.length <= max
2474− ? str
2475− : str.substr(0, max) + "\u2026";
2853+ if (typeof max !== "number") {
2854+ throw new Error(
2855+ "2nd argument to `truncate` function should be a number",
2856+ );
2857+ }
2858+ if (typeof str !== "string" || max === 0) {
2859+ return str;
2860+ }
2861+ return str.length <= max ? str : str.substr(0, max) + "\u2026";
24762862 }
24772863
24782864 /**
@@ -2521,14 +2907,14 @@ · 42 unmodified lines
25212907 return pairs.join("&");
25222908 }
25232909
2524− // borrowed from https://datatracker.ietf.org/doc/html/rfc3986#appendix-B
2910+ // borrowed from https://tools.ietf.org/html/rfc3986#appendix-B
25252911 // intentionally using regex and not <a/> href parsing trick because React Native and other
25262912 // environments where DOM might not be available
25272913 function parseUrl(url) {
2914+ if (typeof url !== "string") return {};
25282915 var match = url.match(
25292916 /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/,
25302917 );
2531− if (!match) return {};
25322918
25332919 // coerce to undefined values to empty string so we don't get 'undefined'
25342920 var query = match[6] || "";
@@ -2675,6 +3061,13 @@ · 140 unmodified lines
26753061 return !!(!!a ^ !!b);
26763062 }
26773063
3064+ /**
3065+ * Returns true if both parameters are undefined
3066+ */
3067+ function isBothUndefined(a, b) {
3068+ return isUndefined(a) && isUndefined(b);
3069+ }
3070+
26783071 /**
26793072 * Returns true if the two input exception interfaces have the same content
26803073 */
@@ -2687,6 +3080,9 @@ · 6 unmodified lines
26873080 if (ex1.type !== ex2.type || ex1.value !== ex2.value)
26883081 return false;
26893082
3083+ // in case both stacktraces are undefined, we can't decide so default to false
3084+ if (isBothUndefined(ex1.stacktrace, ex2.stacktrace)) return false;
3085+
26903086 return isSameStacktrace(ex1.stacktrace, ex2.stacktrace);
26913087 }
26923088
@@ -2726,6 +3122,7 @@ · 33 unmodified lines
27263122 * @param track {optional} record instrumentation to an array
27273123 */
27283124 function fill(obj, name, replacement, track) {
3125+ if (obj == null) return;
27293126 var orig = obj[name];
27303127 obj[name] = replacement(orig);
27313128 obj[name].__raven__ = true;
@@ -2735,16 +3132,190 @@ · 3 unmodified lines
27353132 }
27363133 }
27373134
3135+ /**
3136+ * Join values in array
3137+ * @param input array of values to be joined together
3138+ * @param delimiter string to be placed in-between values
3139+ * @returns {string}
3140+ */
3141+ function safeJoin(input, delimiter) {
3142+ if (!isArray(input)) return "";
3143+
3144+ var output = [];
3145+
3146+ for (var i = 0; i < input.length; i++) {
3147+ try {
3148+ output.push(String(input[i]));
3149+ } catch (e) {
3150+ output.push("[value cannot be serialized]");
3151+ }
3152+ }
3153+
3154+ return output.join(delimiter);
3155+ }
3156+
3157+ // Default Node.js REPL depth
3158+ var MAX_SERIALIZE_EXCEPTION_DEPTH = 3;
3159+ // 50kB, as 100kB is max payload size, so half sounds reasonable
3160+ var MAX_SERIALIZE_EXCEPTION_SIZE = 50 * 1024;
3161+ var MAX_SERIALIZE_KEYS_LENGTH = 40;
3162+
3163+ function utf8Length(value) {
3164+ return ~-encodeURI(value).split(/%..|./).length;
3165+ }
3166+
3167+ function jsonSize(value) {
3168+ return utf8Length(JSON.stringify(value));
3169+ }
3170+
3171+ function serializeValue(value) {
3172+ if (typeof value === "string") {
3173+ var maxLength = 40;
3174+ return truncate(value, maxLength);
3175+ } else if (
3176+ typeof value === "number" ||
3177+ typeof value === "boolean" ||
3178+ typeof value === "undefined"
3179+ ) {
3180+ return value;
3181+ }
3182+
3183+ var type = Object.prototype.toString.call(value);
3184+
3185+ // Node.js REPL notation
3186+ if (type === "[object Object]") return "[Object]";
3187+ if (type === "[object Array]") return "[Array]";
3188+ if (type === "[object Function]")
3189+ return value.name
3190+ ? "[Function: " + value.name + "]"
3191+ : "[Function]";
3192+
3193+ return value;
3194+ }
3195+
3196+ function serializeObject(value, depth) {
3197+ if (depth === 0) return serializeValue(value);
3198+
3199+ if (isPlainObject(value)) {
3200+ return Object.keys(value).reduce(function (acc, key) {
3201+ acc[key] = serializeObject(value[key], depth - 1);
3202+ return acc;
3203+ }, {});
3204+ } else if (Array.isArray(value)) {
3205+ return value.map(function (val) {
3206+ return serializeObject(val, depth - 1);
3207+ });
3208+ }
3209+
3210+ return serializeValue(value);
3211+ }
3212+
3213+ function serializeException(ex, depth, maxSize) {
3214+ if (!isPlainObject(ex)) return ex;
3215+
3216+ depth =
3217+ typeof depth !== "number"
3218+ ? MAX_SERIALIZE_EXCEPTION_DEPTH
3219+ : depth;
3220+ maxSize =
3221+ typeof depth !== "number"
3222+ ? MAX_SERIALIZE_EXCEPTION_SIZE
3223+ : maxSize;
3224+
3225+ var serialized = serializeObject(ex, depth);
3226+
3227+ if (jsonSize(stringify(serialized)) > maxSize) {
3228+ return serializeException(ex, depth - 1);
3229+ }
3230+
3231+ return serialized;
3232+ }
3233+
3234+ function serializeKeysForMessage(keys, maxLength) {
3235+ if (typeof keys === "number" || typeof keys === "string")
3236+ return keys.toString();
3237+ if (!Array.isArray(keys)) return "";
3238+
3239+ keys = keys.filter(function (key) {
3240+ return typeof key === "string";
3241+ });
3242+ if (keys.length === 0) return "[object has no keys]";
3243+
3244+ maxLength =
3245+ typeof maxLength !== "number"
3246+ ? MAX_SERIALIZE_KEYS_LENGTH
3247+ : maxLength;
3248+ if (keys[0].length >= maxLength) return keys[0];
3249+
3250+ for (var usedKeys = keys.length; usedKeys > 0; usedKeys--) {
3251+ var serialized = keys.slice(0, usedKeys).join(", ");
3252+ if (serialized.length > maxLength) continue;
3253+ if (usedKeys === keys.length) return serialized;
3254+ return serialized + "\u2026";
3255+ }
3256+
3257+ return "";
3258+ }
3259+
3260+ function sanitize(input, sanitizeKeys) {
3261+ if (
3262+ !isArray(sanitizeKeys) ||
3263+ (isArray(sanitizeKeys) && sanitizeKeys.length === 0)
3264+ )
3265+ return input;
3266+
3267+ var sanitizeRegExp = joinRegExp(sanitizeKeys);
3268+ var sanitizeMask = "********";
3269+ var safeInput;
3270+
3271+ try {
3272+ safeInput = JSON.parse(stringify(input));
3273+ } catch (o_O) {
3274+ return input;
3275+ }
3276+
3277+ function sanitizeWorker(workerInput) {
3278+ if (isArray(workerInput)) {
3279+ return workerInput.map(function (val) {
3280+ return sanitizeWorker(val);
3281+ });
3282+ }
3283+
3284+ if (isPlainObject(workerInput)) {
3285+ return Object.keys(workerInput).reduce(function (acc, k) {
3286+ if (sanitizeRegExp.test(k)) {
3287+ acc[k] = sanitizeMask;
3288+ } else {
3289+ acc[k] = sanitizeWorker(workerInput[k]);
3290+ }
3291+ return acc;
3292+ }, {});
3293+ }
3294+
3295+ return workerInput;
3296+ }
3297+
3298+ return sanitizeWorker(safeInput);
3299+ }
3300+
27383301 module.exports = {
27393302 isObject: isObject,
27403303 isError: isError,
27413304 isErrorEvent: isErrorEvent,
3305+ isDOMError: isDOMError,
3306+ isDOMException: isDOMException,
27423307 isUndefined: isUndefined,
27433308 isFunction: isFunction,
3309+ isPlainObject: isPlainObject,
27443310 isString: isString,
27453311 isArray: isArray,
27463312 isEmptyObject: isEmptyObject,
27473313 supportsErrorEvent: supportsErrorEvent,
3314+ supportsDOMError: supportsDOMError,
3315+ supportsDOMException: supportsDOMException,
3316+ supportsFetch: supportsFetch,
3317+ supportsReferrerPolicy: supportsReferrerPolicy,
3318+ supportsPromiseRejectionEvent: supportsPromiseRejectionEvent,
27483319 wrappedCallback: wrappedCallback,
27493320 each: each,
27503321 objectMerge: objectMerge,
@@ -2760,6 +3331,10 @@ · 9 unmodified lines
27603331 isSameStacktrace: isSameStacktrace,
27613332 parseUrl: parseUrl,
27623333 fill: fill,
3334+ safeJoin: safeJoin,
3335+ serializeException: serializeException,
3336+ serializeKeysForMessage: serializeKeysForMessage,
3337+ sanitize: sanitize,
27633338 };
27643339 }).call(
27653340 this,
@@ -2772,7 +3347,7 @@ · 6 unmodified lines
27723347 : {},
27733348 );
27743349 },
2775− {},
3350+ { 7: 7 },
27763351 ],
27773352 6: [
27783353 function (_dereq_, module, exports) {
@@ -2780,14 +3355,14 @@ · 1 unmodified line
27803355 var utils = _dereq_(5);
27813356
27823357 /*
2783− TraceKit - Cross brower stack traces
2784−
2785− This was originally forked from github.com/occ/TraceKit, but has since been
2786− largely re-written and is now maintained as part of raven-js. Tests for
2787− this are in test/vendor.
2788−
2789− MIT license
2790−*/
3358+ TraceKit - Cross brower stack traces
3359+
3360+ This was originally forked from github.com/occ/TraceKit, but has since been
3361+ largely re-written and is now maintained as part of raven-js. Tests for
3362+ this are in test/vendor.
3363+
3364+ MIT license
3365+ */
27913366
27923367 var TraceKit = {
27933368 collectWindowErrors: true,
@@ -2815,10 +3390,25 @@ · 21 unmodified lines
28153390 function getLocationHref() {
28163391 if (typeof document === "undefined" || document.location == null)
28173392 return "";
2818−
28193393 return document.location.href;
28203394 }
28213395
3396+ function getLocationOrigin() {
3397+ if (typeof document === "undefined" || document.location == null)
3398+ return "";
3399+
3400+ // Oh dear IE10...
3401+ if (!document.location.origin) {
3402+ document.location.origin =
3403+ document.location.protocol +
3404+ "//" +
3405+ document.location.hostname +
3406+ (document.location.port ? ":" + document.location.port : "");
3407+ }
3408+
3409+ return document.location.origin;
3410+ }
3411+
28223412 /**
28233413 * TraceKit.report: cross-browser processing of unhandled exceptions
28243414 *
@@ -2925,7 +3515,7 @@ · 100 unmodified lines
29253515 /**
29263516 * Ensures all global unhandled exceptions are recorded.
29273517 * Supported by Gecko and IE.
2928− * @param {string} message Error message.
3518+ * @param {string} msg Error message.
29293519 * @param {string} url URL of script that generated the exception.
29303520 * @param {(number|string)} lineNo The line number at which the error
29313521 * occurred.
@@ -2933,8 +3523,12 @@ · 1 unmodified line
29333523 * occurred.
29343524 * @param {?Error} ex The actual Error object.
29353525 */
2936− function traceKitWindowOnError(message, url, lineNo, colNo, ex) {
3526+ function traceKitWindowOnError(msg, url, lineNo, colNo, ex) {
29373527 var stack = null;
3528+ // If 'ex' is ErrorEvent, get real Error from inside
3529+ var exception = utils.isErrorEvent(ex) ? ex.error : ex;
3530+ // If 'msg' is ErrorEvent, get real message from inside
3531+ var message = utils.isErrorEvent(msg) ? msg.message : msg;
29383532
29393533 if (lastExceptionStack) {
29403534 TraceKit.computeStackTrace.augmentStackTraceWithInitialElement(
@@ -2944,13 +3538,13 @@ · 3 unmodified lines
29443538 message,
29453539 );
29463540 processLastException();
2947− } else if (ex && utils.isError(ex)) {
2948− // non-string `ex` arg; attempt to extract stack trace
3541+ } else if (exception && utils.isError(exception)) {
3542+ // non-string `exception` arg; attempt to extract stack trace
29493543
29503544 // New chrome and blink send along a real error object
29513545 // Let's just report that like a normal error.
29523546 // See: https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror
2953− stack = TraceKit.computeStackTrace(ex);
3547+ stack = TraceKit.computeStackTrace(exception);
29543548 notifyHandlers(stack, true);
29553549 } else {
29563550 var location = {
@@ -2960,13 +3554,13 @@ · 3 unmodified lines
29603554 };
29613555
29623556 var name = undefined;
2963− var msg = message; // must be new var or will modify original `arguments`
29643557 var groups;
3558+
29653559 if ({}.toString.call(message) === "[object String]") {
29663560 var groups = message.match(ERROR_TYPES_RE);
29673561 if (groups) {
29683562 name = groups[1];
2969− msg = groups[2];
3563+ message = groups[2];
29703564 }
29713565 }
29723566
@@ -2974,7 +3568,7 @@ · 1 unmodified line
29743568
29753569 stack = {
29763570 name: name,
2977− message: msg,
3571+ message: message,
29783572 url: getLocationHref(),
29793573 stack: [location],
29803574 };
@@ -3163,20 +3757,22 @@ · 182 unmodified lines
31633757 if (typeof ex.stack === "undefined" || !ex.stack) return;
31643758
31653759 var chrome =
3166− /^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,
3167− gecko =
3168− /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i,
3169− winjs =
3170− /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,
3171− // Used to additionally parse URL/line/column from eval frames
3172− geckoEval = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i,
3173− chromeEval = /\((\S*)(?::(\d+))(?::(\d+))\)/,
3174− lines = ex.stack.split("\n"),
3175− stack = [],
3176− submatch,
3177− parts,
3178− element,
3179− reference = /^(.*) is undefined$/.exec(ex.message);
3760+ /^\s*at (?:(.*?) ?\()?((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
3761+ var winjs =
3762+ /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
3763+ // NOTE: blob urls are now supposed to always have an origin, therefore it's format
3764+ // which is `blob:http://url/path/with-some-uuid`, is matched by `blob.*?:\/` as well
3765+ var gecko =
3766+ /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|moz-extension).*?:\/.*?|\[native code\]|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i;
3767+ // Used to additionally parse URL/line/column from eval frames
3768+ var geckoEval = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
3769+ var chromeEval = /\((\S*)(?::(\d+))(?::(\d+))\)/;
3770+ var lines = ex.stack.split("\n");
3771+ var stack = [];
3772+ var submatch;
3773+ var parts;
3774+ var element;
3775+ var reference = /^(.*) is undefined$/.exec(ex.message);
31803776
31813777 for (var i = 0, j = lines.length; i < j; ++i) {
31823778 if ((parts = chrome.exec(lines[i]))) {
@@ -3236,6 +3832,47 @@ · 53 unmodified lines
32363832 element.func = UNKNOWN_FUNCTION;
32373833 }
32383834
3835+ if (element.url && element.url.substr(0, 5) === "blob:") {
3836+ // Special case for handling JavaScript loaded into a blob.
3837+ // We use a synchronous AJAX request here as a blob is already in
3838+ // memory - it's not making a network request. This will generate a warning
3839+ // in the browser console, but there has already been an error so that's not
3840+ // that much of an issue.
3841+ var xhr = new XMLHttpRequest();
3842+ xhr.open("GET", element.url, false);
3843+ xhr.send(null);
3844+
3845+ // If we failed to download the source, skip this patch
3846+ if (xhr.status === 200) {
3847+ var source = xhr.responseText || "";
3848+
3849+ // We trim the source down to the last 300 characters as sourceMappingURL is always at the end of the file.
3850+ // Why 300? To be in line with: https://github.com/getsentry/sentry/blob/4af29e8f2350e20c28a6933354e4f42437b4ba42/src/sentry/lang/javascript/processor.py#L164-L175
3851+ source = source.slice(-300);
3852+
3853+ // Now we dig out the source map URL
3854+ var sourceMaps = source.match(
3855+ /\/\/# sourceMappingURL=(.*)$/,
3856+ );
3857+
3858+ // If we don't find a source map comment or we find more than one, continue on to the next element.
3859+ if (sourceMaps) {
3860+ var sourceMapAddress = sourceMaps[1];
3861+
3862+ // Now we check to see if it's a relative URL.
3863+ // If it is, convert it to an absolute one.
3864+ if (sourceMapAddress.charAt(0) === "~") {
3865+ sourceMapAddress =
3866+ getLocationOrigin() + sourceMapAddress.slice(1);
3867+ }
3868+
3869+ // Now we strip the '.map' off of the end of the URL and update the
3870+ // element so that Sentry can match the map to the blob.
3871+ element.url = sourceMapAddress.slice(0, -4);
3872+ }
3873+ }
3874+ }
3875+
32393876 stack.push(element);
32403877 }
32413878
@@ -3449,15 +4086,15 @@ · 207 unmodified lines
34494086 7: [
34504087 function (_dereq_, module, exports) {
34514088 /*
3452− json-stringify-safe
3453− Like JSON.stringify, but doesn't throw on circular references.
3454−
3455− Originally forked from https://github.com/isaacs/json-stringify-safe
3456− version 5.0.1 on 3/8/2017 and modified to handle Errors serialization
3457− and IE8 compatibility. Tests for this are in test/vendor.
3458−
3459− ISC license: https://github.com/isaacs/json-stringify-safe/blob/master/LICENSE
3460−*/
4089+ json-stringify-safe
4090+ Like JSON.stringify, but doesn't throw on circular references.
4091+
4092+ Originally forked from https://github.com/isaacs/json-stringify-safe
4093+ version 5.0.1 on 3/8/2017 and modified to handle Errors serialization
4094+ and IE8 compatibility. Tests for this are in test/vendor.
4095+
4096+ ISC license: https://github.com/isaacs/json-stringify-safe/blob/master/LICENSE
4097+ */
34614098
34624099 exports = module.exports = stringify;
34634100 exports.getSerialize = serializer;
@@ -3535,6 +4172,281 @@ · 71 unmodified lines
35354172 },
35364173 {},
35374174 ],
4175+ 8: [
4176+ function (_dereq_, module, exports) {
4177+ /*
4178+ * JavaScript MD5
4179+ * https://github.com/blueimp/JavaScript-MD5
4180+ *
4181+ * Copyright 2011, Sebastian Tschan
4182+ * https://blueimp.net
4183+ *
4184+ * Licensed under the MIT license:
4185+ * https://opensource.org/licenses/MIT
4186+ *
4187+ * Based on
4188+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
4189+ * Digest Algorithm, as defined in RFC 1321.
4190+ * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
4191+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
4192+ * Distributed under the BSD License
4193+ * See http://pajhome.org.uk/crypt/md5 for more info.
4194+ */
4195+
4196+ /*
4197+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
4198+ * to work around bugs in some JS interpreters.
4199+ */
4200+ function safeAdd(x, y) {
4201+ var lsw = (x & 0xffff) + (y & 0xffff);
4202+ var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
4203+ return (msw << 16) | (lsw & 0xffff);
4204+ }
4205+
4206+ /*
4207+ * Bitwise rotate a 32-bit number to the left.
4208+ */
4209+ function bitRotateLeft(num, cnt) {
4210+ return (num << cnt) | (num >>> (32 - cnt));
4211+ }
4212+
4213+ /*
4214+ * These functions implement the four basic operations the algorithm uses.
4215+ */
4216+ function md5cmn(q, a, b, x, s, t) {
4217+ return safeAdd(
4218+ bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s),
4219+ b,
4220+ );
4221+ }
4222+ function md5ff(a, b, c, d, x, s, t) {
4223+ return md5cmn((b & c) | (~b & d), a, b, x, s, t);
4224+ }
4225+ function md5gg(a, b, c, d, x, s, t) {
4226+ return md5cmn((b & d) | (c & ~d), a, b, x, s, t);
4227+ }
4228+ function md5hh(a, b, c, d, x, s, t) {
4229+ return md5cmn(b ^ c ^ d, a, b, x, s, t);
4230+ }
4231+ function md5ii(a, b, c, d, x, s, t) {
4232+ return md5cmn(c ^ (b | ~d), a, b, x, s, t);
4233+ }
4234+
4235+ /*
4236+ * Calculate the MD5 of an array of little-endian words, and a bit length.
4237+ */
4238+ function binlMD5(x, len) {
4239+ /* append padding */
4240+ x[len >> 5] |= 0x80 << len % 32;
4241+ x[(((len + 64) >>> 9) << 4) + 14] = len;
4242+
4243+ var i;
4244+ var olda;
4245+ var oldb;
4246+ var oldc;
4247+ var oldd;
4248+ var a = 1732584193;
4249+ var b = -271733879;
4250+ var c = -1732584194;
4251+ var d = 271733878;
4252+
4253+ for (i = 0; i < x.length; i += 16) {
4254+ olda = a;
4255+ oldb = b;
4256+ oldc = c;
4257+ oldd = d;
4258+
4259+ a = md5ff(a, b, c, d, x[i], 7, -680876936);
4260+ d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);
4261+ c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);
4262+ b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);
4263+ a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);
4264+ d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);
4265+ c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);
4266+ b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);
4267+ a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);
4268+ d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);
4269+ c = md5ff(c, d, a, b, x[i + 10], 17, -42063);
4270+ b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);
4271+ a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);
4272+ d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);
4273+ c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);
4274+ b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);
4275+
4276+ a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);
4277+ d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);
4278+ c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);
4279+ b = md5gg(b, c, d, a, x[i], 20, -373897302);
4280+ a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);
4281+ d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);
4282+ c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);
4283+ b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);
4284+ a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);
4285+ d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);
4286+ c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);
4287+ b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);
4288+ a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);
4289+ d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);
4290+ c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);
4291+ b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);
4292+
4293+ a = md5hh(a, b, c, d, x[i + 5], 4, -378558);
4294+ d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);
4295+ c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);
4296+ b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);
4297+ a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);
4298+ d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);
4299+ c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);
4300+ b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);
4301+ a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);
4302+ d = md5hh(d, a, b, c, x[i], 11, -358537222);
4303+ c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);
4304+ b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);
4305+ a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);
4306+ d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);
4307+ c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);
4308+ b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);
4309+
4310+ a = md5ii(a, b, c, d, x[i], 6, -198630844);
4311+ d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);
4312+ c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);
4313+ b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);
4314+ a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);
4315+ d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);
4316+ c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);
4317+ b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);
4318+ a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);
4319+ d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);
4320+ c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);
4321+ b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);
4322+ a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);
4323+ d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);
4324+ c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);
4325+ b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);
4326+
4327+ a = safeAdd(a, olda);
4328+ b = safeAdd(b, oldb);
4329+ c = safeAdd(c, oldc);
4330+ d = safeAdd(d, oldd);
4331+ }
4332+ return [a, b, c, d];
4333+ }
4334+
4335+ /*
4336+ * Convert an array of little-endian words to a string
4337+ */
4338+ function binl2rstr(input) {
4339+ var i;
4340+ var output = "";
4341+ var length32 = input.length * 32;
4342+ for (i = 0; i < length32; i += 8) {
4343+ output += String.fromCharCode((input[i >> 5] >>> i % 32) & 0xff);
4344+ }
4345+ return output;
4346+ }
4347+
4348+ /*
4349+ * Convert a raw string to an array of little-endian words
4350+ * Characters >255 have their high-byte silently ignored.
4351+ */
4352+ function rstr2binl(input) {
4353+ var i;
4354+ var output = [];
4355+ output[(input.length >> 2) - 1] = undefined;
4356+ for (i = 0; i < output.length; i += 1) {
4357+ output[i] = 0;
4358+ }
4359+ var length8 = input.length * 8;
4360+ for (i = 0; i < length8; i += 8) {
4361+ output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << i % 32;
4362+ }
4363+ return output;
4364+ }
4365+
4366+ /*
4367+ * Calculate the MD5 of a raw string
4368+ */
4369+ function rstrMD5(s) {
4370+ return binl2rstr(binlMD5(rstr2binl(s), s.length * 8));
4371+ }
4372+
4373+ /*
4374+ * Calculate the HMAC-MD5, of a key and some data (raw strings)
4375+ */
4376+ function rstrHMACMD5(key, data) {
4377+ var i;
4378+ var bkey = rstr2binl(key);
4379+ var ipad = [];
4380+ var opad = [];
4381+ var hash;
4382+ ipad[15] = opad[15] = undefined;
4383+ if (bkey.length > 16) {
4384+ bkey = binlMD5(bkey, key.length * 8);
4385+ }
4386+ for (i = 0; i < 16; i += 1) {
4387+ ipad[i] = bkey[i] ^ 0x36363636;
4388+ opad[i] = bkey[i] ^ 0x5c5c5c5c;
4389+ }
4390+ hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
4391+ return binl2rstr(binlMD5(opad.concat(hash), 512 + 128));
4392+ }
4393+
4394+ /*
4395+ * Convert a raw string to a hex string
4396+ */
4397+ function rstr2hex(input) {
4398+ var hexTab = "0123456789abcdef";
4399+ var output = "";
4400+ var x;
4401+ var i;
4402+ for (i = 0; i < input.length; i += 1) {
4403+ x = input.charCodeAt(i);
4404+ output +=
4405+ hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f);
4406+ }
4407+ return output;
4408+ }
4409+
4410+ /*
4411+ * Encode a string as utf-8
4412+ */
4413+ function str2rstrUTF8(input) {
4414+ return unescape(encodeURIComponent(input));
4415+ }
4416+
4417+ /*
4418+ * Take string arguments and return either raw or hex encoded strings
4419+ */
4420+ function rawMD5(s) {
4421+ return rstrMD5(str2rstrUTF8(s));
4422+ }
4423+ function hexMD5(s) {
4424+ return rstr2hex(rawMD5(s));
4425+ }
4426+ function rawHMACMD5(k, d) {
4427+ return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d));
4428+ }
4429+ function hexHMACMD5(k, d) {
4430+ return rstr2hex(rawHMACMD5(k, d));
4431+ }
4432+
4433+ function md5(string, key, raw) {
4434+ if (!key) {
4435+ if (!raw) {
4436+ return hexMD5(string);
4437+ }
4438+ return rawMD5(string);
4439+ }
4440+ if (!raw) {
4441+ return hexHMACMD5(key, string);
4442+ }
4443+ return rawHMACMD5(key, string);
4444+ }
4445+
4446+ module.exports = md5;
4447+ },
4448+ {},
4449+ ],
35384450 },
35394451 {},
35404452 [4],