Unified · Split
| @@ -1,4 +1,4 @@ | |||
| 1 | /*! Raven.js 1.1.18 (8ad15bc) | github.com/getsentry/raven-js */ | 1 | /*! Raven.js 1.3.0 (768fdca) | github.com/getsentry/raven-js */ |
| 2 | 2 | ||
| 3 | /* | 3 | /* |
| 4 | * Includes TraceKit | 4 | * Includes TraceKit |
| @@ -21,7 +21,8 @@ var TraceKit = { · 16 unmodified lines | |||
| 21 | remoteFetching: false, | 21 | remoteFetching: false, |
| 22 | collectWindowErrors: true, | 22 | collectWindowErrors: true, |
| 23 | // 3 lines before, the offending line, 3 lines after | 23 | // 3 lines before, the offending line, 3 lines after |
| 24 | linesOfContext: 7 | 24 | linesOfContext: 7, |
| 25 | debug: false | ||
| 25 | }; | 26 | }; |
| 26 | 27 | ||
| 27 | // global reference to slice | 28 | // global reference to slice |
| @@ -29,23 +30,11 @@ var _slice = [].slice; · 1 unmodified line | |||
| 29 | var UNKNOWN_FUNCTION = '?'; | 30 | var UNKNOWN_FUNCTION = '?'; |
| 30 | 31 | ||
| 31 | 32 | ||
| 32 | /** | 33 | function getLocationHref() { |
| 33 | * TraceKit.wrap: Wrap any function in a TraceKit reporter | 34 | if (typeof document === 'undefined') |
| 34 | * Example: func = TraceKit.wrap(func); | 35 | return ''; |
| 35 | * | 36 | |
| 36 | * @param {Function} func Function to be wrapped | 37 | return document.location.href; |
| 37 | * @return {Function} The wrapped func | ||
| 38 | */ | ||
| 39 | TraceKit.wrap = function traceKitWrapper(func) { | ||
| 40 | function wrapped() { | ||
| 41 | try { | ||
| 42 | return func.apply(this, arguments); | ||
| 43 | } catch (e) { | ||
| 44 | TraceKit.report(e); | ||
| 45 | throw e; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | return wrapped; | ||
| 49 | }; | 38 | }; |
| 50 | 39 | ||
| 51 | /** | 40 | /** |
| @@ -181,7 +170,7 @@ TraceKit.report = (function reportModuleWrapper() { · 129 unmodified lines | |||
| 181 | location.context = TraceKit.computeStackTrace.gatherContext(location.url, location.line); | 170 | location.context = TraceKit.computeStackTrace.gatherContext(location.url, location.line); |
| 182 | stack = { | 171 | stack = { |
| 183 | 'message': message, | 172 | 'message': message, |
| 184 | 'url': document.location.href, | 173 | 'url': getLocationHref(), |
| 185 | 'stack': [location] | 174 | 'stack': [location] |
| 186 | }; | 175 | }; |
| 187 | notifyHandlers(stack, true); | 176 | notifyHandlers(stack, true); |
| @@ -319,8 +308,7 @@ TraceKit.report = (function reportModuleWrapper() { · 131 unmodified lines | |||
| 319 | * | 308 | * |
| 320 | */ | 309 | */ |
| 321 | TraceKit.computeStackTrace = (function computeStackTraceWrapper() { | 310 | TraceKit.computeStackTrace = (function computeStackTraceWrapper() { |
| 322 | var debug = false, | 311 | var sourceCache = {}; |
| 323 | sourceCache = {}; | ||
| 324 | 312 | ||
| 325 | /** | 313 | /** |
| 326 | * Attempts to retrieve source code via XMLHttpRequest, which is used | 314 | * Attempts to retrieve source code via XMLHttpRequest, which is used |
| @@ -362,7 +350,9 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 35 unmodified lines | |||
| 362 | // URL needs to be able to fetched within the acceptable domain. Otherwise, | 350 | // URL needs to be able to fetched within the acceptable domain. Otherwise, |
| 363 | // cross-domain errors will be triggered. | 351 | // cross-domain errors will be triggered. |
| 364 | var source = ''; | 352 | var source = ''; |
| 365 | if (url.indexOf(document.domain) !== -1) { | 353 | var domain = ''; |
| 354 | try { domain = document.domain; } catch (e) {} | ||
| 355 | if (url.indexOf(domain) !== -1) { | ||
| 366 | source = loadSource(url); | 356 | source = loadSource(url); |
| 367 | } | 357 | } |
| 368 | sourceCache[url] = source ? source.split('\n') : []; | 358 | sourceCache[url] = source ? source.split('\n') : []; |
| @@ -524,6 +514,9 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 155 unmodified lines | |||
| 524 | * the url, line, and column number of the defined function. | 514 | * the url, line, and column number of the defined function. |
| 525 | */ | 515 | */ |
| 526 | function findSourceByFunctionBody(func) { | 516 | function findSourceByFunctionBody(func) { |
| 517 | if (typeof document === 'undefined') | ||
| 518 | return; | ||
| 519 | |||
| 527 | var urls = [window.location.href], | 520 | var urls = [window.location.href], |
| 528 | scripts = document.getElementsByTagName('script'), | 521 | scripts = document.getElementsByTagName('script'), |
| 529 | body, | 522 | body, |
| @@ -627,12 +620,11 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 97 unmodified lines | |||
| 627 | * @return {?Object.<string, *>} Stack trace information. | 620 | * @return {?Object.<string, *>} Stack trace information. |
| 628 | */ | 621 | */ |
| 629 | function computeStackTraceFromStackProp(ex) { | 622 | function computeStackTraceFromStackProp(ex) { |
| 630 | if (!ex.stack) { | 623 | if (isUndefined(ex.stack) || !ex.stack) return; |
| 631 | return null; | ||
| 632 | } | ||
| 633 | 624 | ||
| 634 | var chrome = /^\s*at (.*?) ?\(?((?:file|https?|chrome-extension):.*?):(\d+)(?::(\d+))?\)?\s*$/i, | 625 | var chrome = /^\s*at (.*?) ?\(?((?:(?:file|https?|chrome-extension):.*?)|<anonymous>):(\d+)(?::(\d+))?\)?\s*$/i, |
| 635 | gecko = /^\s*(.*?)(?:\((.*?)\))?@((?:file|https?|chrome).*?):(\d+)(?::(\d+))?\s*$/i, | 626 | gecko = /^\s*(.*?)(?:\((.*?)\))?@((?:file|https?|chrome).*?):(\d+)(?::(\d+))?\s*$/i, |
| 627 | winjs = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:ms-appx|http|https):.*?):(\d+)(?::(\d+))?\)?\s*$/i, | ||
| 636 | lines = ex.stack.split('\n'), | 628 | lines = ex.stack.split('\n'), |
| 637 | stack = [], | 629 | stack = [], |
| 638 | parts, | 630 | parts, |
| @@ -655,6 +647,13 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 16 unmodified lines | |||
| 655 | 'line': +parts[3], | 647 | 'line': +parts[3], |
| 656 | 'column': parts[4] ? +parts[4] : null | 648 | 'column': parts[4] ? +parts[4] : null |
| 657 | }; | 649 | }; |
| 650 | } else if ((parts = winjs.exec(lines[i]))) { | ||
| 651 | element = { | ||
| 652 | 'url': parts[2], | ||
| 653 | 'func': parts[1] || UNKNOWN_FUNCTION, | ||
| 654 | 'line': +parts[3], | ||
| 655 | 'column': parts[4] ? +parts[4] : null | ||
| 656 | }; | ||
| 658 | } else { | 657 | } else { |
| 659 | continue; | 658 | continue; |
| 660 | } | 659 | } |
| @@ -686,7 +685,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 25 unmodified lines | |||
| 686 | return { | 685 | return { |
| 687 | 'name': ex.name, | 686 | 'name': ex.name, |
| 688 | 'message': ex.message, | 687 | 'message': ex.message, |
| 689 | 'url': document.location.href, | 688 | 'url': getLocationHref(), |
| 690 | 'stack': stack | 689 | 'stack': stack |
| 691 | }; | 690 | }; |
| 692 | } | 691 | } |
| @@ -702,6 +701,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 9 unmodified lines | |||
| 702 | // else to it because Opera is not very good at providing it | 701 | // else to it because Opera is not very good at providing it |
| 703 | // reliably in other circumstances. | 702 | // reliably in other circumstances. |
| 704 | var stacktrace = ex.stacktrace; | 703 | var stacktrace = ex.stacktrace; |
| 704 | if (isUndefined(ex.stacktrace) || !ex.stacktrace) return; | ||
| 705 | 705 | ||
| 706 | var testRE = / line (\d+), column (\d+) in (?:<anonymous function: ([^>]+)>|([^\)]+))\((.*)\) in (.*):\s*$/i, | 706 | var testRE = / line (\d+), column (\d+) in (?:<anonymous function: ([^>]+)>|([^\)]+))\((.*)\) in (.*):\s*$/i, |
| 707 | lines = stacktrace.split('\n'), | 707 | lines = stacktrace.split('\n'), |
| @@ -742,7 +742,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 34 unmodified lines | |||
| 742 | return { | 742 | return { |
| 743 | 'name': ex.name, | 743 | 'name': ex.name, |
| 744 | 'message': ex.message, | 744 | 'message': ex.message, |
| 745 | 'url': document.location.href, | 745 | 'url': getLocationHref(), |
| 746 | 'stack': stack | 746 | 'stack': stack |
| 747 | }; | 747 | }; |
| 748 | } | 748 | } |
| @@ -852,7 +852,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 103 unmodified lines | |||
| 852 | return { | 852 | return { |
| 853 | 'name': ex.name, | 853 | 'name': ex.name, |
| 854 | 'message': lines[0], | 854 | 'message': lines[0], |
| 855 | 'url': document.location.href, | 855 | 'url': getLocationHref(), |
| 856 | 'stack': stack | 856 | 'stack': stack |
| 857 | }; | 857 | }; |
| 858 | } | 858 | } |
| @@ -951,6 +951,12 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 92 unmodified lines | |||
| 951 | item.func = parts[1]; | 951 | item.func = parts[1]; |
| 952 | } | 952 | } |
| 953 | 953 | ||
| 954 | if (typeof item.func === 'undefined') { | ||
| 955 | try { | ||
| 956 | item.func = parts.input.substring(0, parts.input.indexOf('{')); | ||
| 957 | } catch (e) { } | ||
| 958 | } | ||
| 959 | |||
| 954 | if ((source = findSourceByFunctionBody(curr))) { | 960 | if ((source = findSourceByFunctionBody(curr))) { |
| 955 | item.url = source.url; | 961 | item.url = source.url; |
| 956 | item.line = source.line; | 962 | item.line = source.line; |
| @@ -983,7 +989,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 26 unmodified lines | |||
| 983 | var result = { | 989 | var result = { |
| 984 | 'name': ex.name, | 990 | 'name': ex.name, |
| 985 | 'message': ex.message, | 991 | 'message': ex.message, |
| 986 | 'url': document.location.href, | 992 | 'url': getLocationHref(), |
| 987 | 'stack': stack | 993 | 'stack': stack |
| 988 | }; | 994 | }; |
| 989 | augmentStackTraceWithInitialElement(result, ex.sourceURL || ex.fileName, ex.line || ex.lineNumber, ex.message || ex.description); | 995 | augmentStackTraceWithInitialElement(result, ex.sourceURL || ex.fileName, ex.line || ex.lineNumber, ex.message || ex.description); |
| @@ -1008,7 +1014,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 18 unmodified lines | |||
| 1008 | return stack; | 1014 | return stack; |
| 1009 | } | 1015 | } |
| 1010 | } catch (e) { | 1016 | } catch (e) { |
| 1011 | if (debug) { | 1017 | if (TraceKit.debug) { |
| 1012 | throw e; | 1018 | throw e; |
| 1013 | } | 1019 | } |
| 1014 | } | 1020 | } |
| @@ -1019,7 +1025,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 4 unmodified lines | |||
| 1019 | return stack; | 1025 | return stack; |
| 1020 | } | 1026 | } |
| 1021 | } catch (e) { | 1027 | } catch (e) { |
| 1022 | if (debug) { | 1028 | if (TraceKit.debug) { |
| 1023 | throw e; | 1029 | throw e; |
| 1024 | } | 1030 | } |
| 1025 | } | 1031 | } |
| @@ -1030,7 +1036,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 4 unmodified lines | |||
| 1030 | return stack; | 1036 | return stack; |
| 1031 | } | 1037 | } |
| 1032 | } catch (e) { | 1038 | } catch (e) { |
| 1033 | if (debug) { | 1039 | if (TraceKit.debug) { |
| 1034 | throw e; | 1040 | throw e; |
| 1035 | } | 1041 | } |
| 1036 | } | 1042 | } |
| @@ -1041,12 +1047,16 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 4 unmodified lines | |||
| 1041 | return stack; | 1047 | return stack; |
| 1042 | } | 1048 | } |
| 1043 | } catch (e) { | 1049 | } catch (e) { |
| 1044 | if (debug) { | 1050 | if (TraceKit.debug) { |
| 1045 | throw e; | 1051 | throw e; |
| 1046 | } | 1052 | } |
| 1047 | } | 1053 | } |
| 1048 | 1054 | ||
| 1049 | return {}; | 1055 | return { |
| 1056 | 'name': ex.name, | ||
| 1057 | 'message': ex.message, | ||
| 1058 | 'url': getLocationHref() | ||
| 1059 | }; | ||
| 1050 | } | 1060 | } |
| 1051 | 1061 | ||
| 1052 | computeStackTrace.augmentStackTraceWithInitialElement = augmentStackTraceWithInitialElement; | 1062 | computeStackTrace.augmentStackTraceWithInitialElement = augmentStackTraceWithInitialElement; |
| @@ -1064,38 +1074,45 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() { · 11 unmodified lines | |||
| 1064 | // since JSON is required to encode the payload | 1074 | // since JSON is required to encode the payload |
| 1065 | var _Raven = window.Raven, | 1075 | var _Raven = window.Raven, |
| 1066 | hasJSON = !!(typeof JSON === 'object' && JSON.stringify), | 1076 | hasJSON = !!(typeof JSON === 'object' && JSON.stringify), |
| 1077 | // Raven can run in contexts where there's no document (react-native) | ||
| 1078 | hasDocument = typeof document !== 'undefined', | ||
| 1067 | lastCapturedException, | 1079 | lastCapturedException, |
| 1068 | lastEventId, | 1080 | lastEventId, |
| 1069 | globalServer, | 1081 | globalServer, |
| 1070 | globalUser, | ||
| 1071 | globalKey, | 1082 | globalKey, |
| 1072 | globalProject, | 1083 | globalProject, |
| 1084 | globalContext = {}, | ||
| 1073 | globalOptions = { | 1085 | globalOptions = { |
| 1074 | logger: 'javascript', | 1086 | logger: 'javascript', |
| 1075 | ignoreErrors: [], | 1087 | ignoreErrors: [], |
| 1076 | ignoreUrls: [], | 1088 | ignoreUrls: [], |
| 1077 | whitelistUrls: [], | 1089 | whitelistUrls: [], |
| 1078 | includePaths: [], | 1090 | includePaths: [], |
| 1091 | crossOrigin: 'anonymous', | ||
| 1079 | collectWindowErrors: true, | 1092 | collectWindowErrors: true, |
| 1080 | tags: {}, | 1093 | maxMessageLength: 100 |
| 1081 | maxMessageLength: 100, | ||
| 1082 | extra: {} | ||
| 1083 | }, | 1094 | }, |
| 1084 | authQueryString, | ||
| 1085 | isRavenInstalled = false, | 1095 | isRavenInstalled = false, |
| 1086 | |||
| 1087 | objectPrototype = Object.prototype, | 1096 | objectPrototype = Object.prototype, |
| 1097 | // capture references to window.console *and* all its methods first | ||
| 1098 | // before the console plugin has a chance to monkey patch | ||
| 1099 | originalConsole = window.console || {}, | ||
| 1100 | originalConsoleMethods = {}, | ||
| 1101 | plugins = [], | ||
| 1088 | startTime = now(); | 1102 | startTime = now(); |
| 1089 | 1103 | ||
| 1104 | for (var method in originalConsole) { | ||
| 1105 | originalConsoleMethods[method] = originalConsole[method]; | ||
| 1106 | } | ||
| 1090 | /* | 1107 | /* |
| 1091 | * The core Raven singleton | 1108 | * The core Raven singleton |
| 1092 | * | 1109 | * |
| 1093 | * @this {Raven} | 1110 | * @this {Raven} |
| 1094 | */ | 1111 | */ |
| 1095 | var Raven = { | 1112 | var Raven = { |
| 1096 | VERSION: '1.1.18', | 1113 | VERSION: '1.3.0', |
| 1097 | 1114 | ||
| 1098 | debug: true, | 1115 | debug: false, |
| 1099 | 1116 | ||
| 1100 | /* | 1117 | /* |
| 1101 | * Allow multiple versions of Raven to be installed. | 1118 | * Allow multiple versions of Raven to be installed. |
| @@ -1129,7 +1146,12 @@ var Raven = { · 27 unmodified lines | |||
| 1129 | // merge in options | 1146 | // merge in options |
| 1130 | if (options) { | 1147 | if (options) { |
| 1131 | each(options, function(key, value){ | 1148 | each(options, function(key, value){ |
| 1132 | globalOptions[key] = value; | 1149 | // tags and extra are special and need to be put into context |
| 1150 | if (key == 'tags' || key == 'extra') { | ||
| 1151 | globalContext[key] = value; | ||
| 1152 | } else { | ||
| 1153 | globalOptions[key] = value; | ||
| 1154 | } | ||
| 1133 | }); | 1155 | }); |
| 1134 | } | 1156 | } |
| 1135 | 1157 | ||
| @@ -1166,8 +1188,6 @@ var Raven = { · 30 unmodified lines | |||
| 1166 | 1188 | ||
| 1167 | TraceKit.collectWindowErrors = !!globalOptions.collectWindowErrors; | 1189 | TraceKit.collectWindowErrors = !!globalOptions.collectWindowErrors; |
| 1168 | 1190 | ||
| 1169 | setAuthQueryString(); | ||
| 1170 | |||
| 1171 | // return for chaining | 1191 | // return for chaining |
| 1172 | return Raven; | 1192 | return Raven; |
| 1173 | }, | 1193 | }, |
| @@ -1183,6 +1203,12 @@ var Raven = { · 9 unmodified lines | |||
| 1183 | install: function() { | 1203 | install: function() { |
| 1184 | if (isSetup() && !isRavenInstalled) { | 1204 | if (isSetup() && !isRavenInstalled) { |
| 1185 | TraceKit.report.subscribe(handleStackInfo); | 1205 | TraceKit.report.subscribe(handleStackInfo); |
| 1206 | |||
| 1207 | // Install all of the plugins | ||
| 1208 | each(plugins, function(_, plugin) { | ||
| 1209 | plugin(); | ||
| 1210 | }); | ||
| 1211 | |||
| 1186 | isRavenInstalled = true; | 1212 | isRavenInstalled = true; |
| 1187 | } | 1213 | } |
| 1188 | 1214 | ||
| @@ -1261,6 +1287,7 @@ var Raven = { · 72 unmodified lines | |||
| 1261 | wrapped[property] = func[property]; | 1287 | wrapped[property] = func[property]; |
| 1262 | } | 1288 | } |
| 1263 | } | 1289 | } |
| 1290 | wrapped.prototype = func.prototype; | ||
| 1264 | 1291 | ||
| 1265 | // Signal that this function has been wrapped already | 1292 | // Signal that this function has been wrapped already |
| 1266 | // for both debugging and to prevent it to being wrapped twice | 1293 | // for both debugging and to prevent it to being wrapped twice |
| @@ -1302,7 +1329,8 @@ var Raven = { · 35 unmodified lines | |||
| 1302 | // raises an exception different from the one we asked to | 1329 | // raises an exception different from the one we asked to |
| 1303 | // report on. | 1330 | // report on. |
| 1304 | try { | 1331 | try { |
| 1305 | TraceKit.report(ex, options); | 1332 | var stack = TraceKit.computeStackTrace(ex); |
| 1333 | handleStackInfo(stack, options); | ||
| 1306 | } catch(ex1) { | 1334 | } catch(ex1) { |
| 1307 | if(ex !== ex1) { | 1335 | if(ex !== ex1) { |
| 1308 | throw ex1; | 1336 | throw ex1; |
| @@ -1337,6 +1365,12 @@ var Raven = { · 28 unmodified lines | |||
| 1337 | return Raven; | 1365 | return Raven; |
| 1338 | }, | 1366 | }, |
| 1339 | 1367 | ||
| 1368 | addPlugin: function(plugin) { | ||
| 1369 | plugins.push(plugin); | ||
| 1370 | if (isRavenInstalled) plugin(); | ||
| 1371 | return Raven; | ||
| 1372 | }, | ||
| 1373 | |||
| 1340 | /* | 1374 | /* |
| 1341 | * Set/clear a user to be sent along with the payload. | 1375 | * Set/clear a user to be sent along with the payload. |
| 1342 | * | 1376 | * |
| @@ -1344,47 +1378,110 @@ var Raven = { · 1 unmodified line | |||
| 1344 | * @return {Raven} | 1378 | * @return {Raven} |
| 1345 | */ | 1379 | */ |
| 1346 | setUserContext: function(user) { | 1380 | setUserContext: function(user) { |
| 1347 | globalUser = user; | 1381 | // Intentionally do not merge here since that's an unexpected behavior. |
| 1382 | globalContext.user = user; | ||
| 1348 | 1383 | ||
| 1349 | return Raven; | 1384 | return Raven; |
| 1350 | }, | 1385 | }, |
| 1351 | 1386 | ||
| 1352 | /* | 1387 | /* |
| 1353 | * Set extra attributes to be sent along with the payload. | 1388 | * Merge extra attributes to be sent along with the payload. |
| 1354 | * | 1389 | * |
| 1355 | * @param {object} extra An object representing extra data [optional] | 1390 | * @param {object} extra An object representing extra data [optional] |
| 1356 | * @return {Raven} | 1391 | * @return {Raven} |
| 1357 | */ | 1392 | */ |
| 1358 | setExtraContext: function(extra) { | 1393 | setExtraContext: function(extra) { |
| 1359 | globalOptions.extra = extra || {}; | 1394 | mergeContext('extra', extra); |
| 1360 | 1395 | ||
| 1361 | return Raven; | 1396 | return Raven; |
| 1362 | }, | 1397 | }, |
| 1363 | 1398 | ||
| 1364 | /* | 1399 | /* |
| 1365 | * Set tags to be sent along with the payload. | 1400 | * Merge tags to be sent along with the payload. |
| 1366 | * | 1401 | * |
| 1367 | * @param {object} tags An object representing tags [optional] | 1402 | * @param {object} tags An object representing tags [optional] |
| 1368 | * @return {Raven} | 1403 | * @return {Raven} |
| 1369 | */ | 1404 | */ |
| 1370 | setTagsContext: function(tags) { | 1405 | setTagsContext: function(tags) { |
| 1371 | globalOptions.tags = tags || {}; | 1406 | mergeContext('tags', tags); |
| 1372 | 1407 | ||
| 1373 | return Raven; | 1408 | return Raven; |
| 1374 | }, | 1409 | }, |
| 1375 | 1410 | ||
| 1411 | /* | ||
| 1412 | * Clear all of the context. | ||
| 1413 | * | ||
| 1414 | * @return {Raven} | ||
| 1415 | */ | ||
| 1416 | clearContext: function() { | ||
| 1417 | globalContext = {}; | ||
| 1418 | |||
| 1419 | return Raven; | ||
| 1420 | }, | ||
| 1421 | |||
| 1422 | /* | ||
| 1423 | * Get a copy of the current context. This cannot be mutated. | ||
| 1424 | * | ||
| 1425 | * @return {object} copy of context | ||
| 1426 | */ | ||
| 1427 | getContext: function() { | ||
| 1428 | // lol javascript | ||
| 1429 | return JSON.parse(JSON.stringify(globalContext)); | ||
| 1430 | }, | ||
| 1431 | |||
| 1376 | /* | 1432 | /* |
| 1377 | * Set release version of application | 1433 | * Set release version of application |
| 1378 | * | 1434 | * |
| 1379 | * @param {string} release Typically something like a git SHA to identify version | 1435 | * @param {string} release Typically something like a git SHA to identify version |
| 1380 | * @return {Raven} | 1436 | * @return {Raven} |
| 1381 | */ | 1437 | */ |
| 1382 | setReleaseContext: function(release) { | 1438 | setRelease: function(release) { |
| 1383 | globalOptions.release = release; | 1439 | globalOptions.release = release; |
| 1384 | 1440 | ||
| 1385 | return Raven; | 1441 | return Raven; |
| 1386 | }, | 1442 | }, |
| 1387 | 1443 | ||
| 1444 | /* | ||
| 1445 | * Set the dataCallback option | ||
| 1446 | * | ||
| 1447 | * @param {function} callback The callback to run which allows the | ||
| 1448 | * data blob to be mutated before sending | ||
| 1449 | * @return {Raven} | ||
| 1450 | */ | ||
| 1451 | setDataCallback: function(callback) { | ||
| 1452 | globalOptions.dataCallback = callback; | ||
| 1453 | |||
| 1454 | return Raven; | ||
| 1455 | }, | ||
| 1456 | |||
| 1457 | /* | ||
| 1458 | * Set the shouldSendCallback option | ||
| 1459 | * | ||
| 1460 | * @param {function} callback The callback to run which allows | ||
| 1461 | * introspecting the blob before sending | ||
| 1462 | * @return {Raven} | ||
| 1463 | */ | ||
| 1464 | setShouldSendCallback: function(callback) { | ||
| 1465 | globalOptions.shouldSendCallback = callback; | ||
| 1466 | |||
| 1467 | return Raven; | ||
| 1468 | }, | ||
| 1469 | |||
| 1470 | /** | ||
| 1471 | * Override the default HTTP transport mechanism that transmits data | ||
| 1472 | * to the Sentry server. | ||
| 1473 | * | ||
| 1474 | * @param {function} transport Function invoked instead of the default | ||
| 1475 | * `makeRequest` handler. | ||
| 1476 | * | ||
| 1477 | * @return {Raven} | ||
| 1478 | */ | ||
| 1479 | setTransport: function(transport) { | ||
| 1480 | globalOptions.transport = transport; | ||
| 1481 | |||
| 1482 | return Raven; | ||
| 1483 | }, | ||
| 1484 | |||
| 1388 | /* | 1485 | /* |
| 1389 | * Get the latest raw exception that was captured by Raven. | 1486 | * Get the latest raw exception that was captured by Raven. |
| 1390 | * | 1487 | * |
| @@ -1413,41 +1510,47 @@ var Raven = { · 22 unmodified lines | |||
| 1413 | } | 1510 | } |
| 1414 | }; | 1511 | }; |
| 1415 | 1512 | ||
| 1416 | Raven.setUser = Raven.setUserContext; // To be deprecated | 1513 | // Deprecations |
| 1514 | Raven.setUser = Raven.setUserContext; | ||
| 1515 | Raven.setReleaseContext = Raven.setRelease; | ||
| 1417 | 1516 | ||
| 1418 | function triggerEvent(eventType, options) { | 1517 | function triggerEvent(eventType, options) { |
| 1419 | var event, key; | 1518 | // NOTE: `event` is a native browser thing, so let's avoid conflicting wiht it |
| 1519 | var evt, key; | ||
| 1520 | |||
| 1521 | if (!hasDocument) | ||
| 1522 | return; | ||
| 1420 | 1523 | ||
| 1421 | options = options || {}; | 1524 | options = options || {}; |
| 1422 | 1525 | ||
| 1423 | eventType = 'raven' + eventType.substr(0,1).toUpperCase() + eventType.substr(1); | 1526 | eventType = 'raven' + eventType.substr(0,1).toUpperCase() + eventType.substr(1); |
| 1424 | 1527 | ||
| 1425 | if (document.createEvent) { | 1528 | if (document.createEvent) { |
| 1426 | event = document.createEvent('HTMLEvents'); | 1529 | evt = document.createEvent('HTMLEvents'); |
| 1427 | event.initEvent(eventType, true, true); | 1530 | evt.initEvent(eventType, true, true); |
| 1428 | } else { | 1531 | } else { |
| 1429 | event = document.createEventObject(); | 1532 | evt = document.createEventObject(); |
| 1430 | event.eventType = eventType; | 1533 | evt.eventType = eventType; |
| 1431 | } | 1534 | } |
| 1432 | 1535 | ||
| 1433 | for (key in options) if (hasKey(options, key)) { | 1536 | for (key in options) if (hasKey(options, key)) { |
| 1434 | event[key] = options[key]; | 1537 | evt[key] = options[key]; |
| 1435 | } | 1538 | } |
| 1436 | 1539 | ||
| 1437 | if (document.createEvent) { | 1540 | if (document.createEvent) { |
| 1438 | // IE9 if standards | 1541 | // IE9 if standards |
| 1439 | document.dispatchEvent(event); | 1542 | document.dispatchEvent(evt); |
| 1440 | } else { | 1543 | } else { |
| 1441 | // IE8 regardless of Quirks or Standards | 1544 | // IE8 regardless of Quirks or Standards |
| 1442 | // IE9 if quirks | 1545 | // IE9 if quirks |
| 1443 | try { | 1546 | try { |
| 1444 | document.fireEvent('on' + event.eventType.toLowerCase(), event); | 1547 | document.fireEvent('on' + evt.eventType.toLowerCase(), evt); |
| 1445 | } catch(e) {} | 1548 | } catch(e) {} |
| 1446 | } | 1549 | } |
| 1447 | } | 1550 | } |
| 1448 | 1551 | ||
| 1449 | var dsnKeys = 'source protocol user pass host port path'.split(' '), | 1552 | var dsnKeys = 'source protocol user pass host port path'.split(' '), |
| 1450 | dsnPattern = /^(?:(\w+):)?\/\/(\w+)(:\w+)?@([\w\.-]+)(?::(\d+))?(\/.*)/; | 1553 | dsnPattern = /^(?:(\w+):)?\/\/(?:(\w+)(:\w+)?@)?([\w\.-]+)(?::(\d+))?(\/.*)/; |
| 1451 | 1554 | ||
| 1452 | function RavenConfigError(message) { | 1555 | function RavenConfigError(message) { |
| 1453 | this.name = 'RavenConfigError'; | 1556 | this.name = 'RavenConfigError'; |
| @@ -1475,7 +1578,7 @@ function parseDSN(str) { · 21 unmodified lines | |||
| 1475 | } | 1578 | } |
| 1476 | 1579 | ||
| 1477 | function isUndefined(what) { | 1580 | function isUndefined(what) { |
| 1478 | return typeof what === 'undefined'; | 1581 | return what === void 0; |
| 1479 | } | 1582 | } |
| 1480 | 1583 | ||
| 1481 | function isFunction(what) { | 1584 | function isFunction(what) { |
| @@ -1483,7 +1586,7 @@ function isFunction(what) { · 1 unmodified line | |||
| 1483 | } | 1586 | } |
| 1484 | 1587 | ||
| 1485 | function isString(what) { | 1588 | function isString(what) { |
| 1486 | return typeof what === 'string'; | 1589 | return objectPrototype.toString.call(what) === '[object String]'; |
| 1487 | } | 1590 | } |
| 1488 | 1591 | ||
| 1489 | function isObject(what) { | 1592 | function isObject(what) { |
| @@ -1533,15 +1636,6 @@ function each(obj, callback) { · 43 unmodified lines | |||
| 1533 | } | 1636 | } |
| 1534 | } | 1637 | } |
| 1535 | 1638 | ||
| 1536 | |||
| 1537 | function setAuthQueryString() { | ||
| 1538 | authQueryString = | ||
| 1539 | '?sentry_version=4' + | ||
| 1540 | '&sentry_client=raven-js/' + Raven.VERSION + | ||
| 1541 | '&sentry_key=' + globalKey; | ||
| 1542 | } | ||
| 1543 | |||
| 1544 | |||
| 1545 | function handleStackInfo(stackInfo, options) { | 1639 | function handleStackInfo(stackInfo, options) { |
| 1546 | var frames = []; | 1640 | var frames = []; |
| 1547 | 1641 | ||
| @@ -1588,7 +1682,7 @@ function normalizeFrame(frame) { · 40 unmodified lines | |||
| 1588 | 1682 | ||
| 1589 | normalized.in_app = !( // determine if an exception came from outside of our app | 1683 | normalized.in_app = !( // determine if an exception came from outside of our app |
| 1590 | // first we check the global includePaths list. | 1684 | // first we check the global includePaths list. |
| 1591 | !globalOptions.includePaths.test(normalized.filename) || | 1685 | (!!globalOptions.includePaths.test && !globalOptions.includePaths.test(normalized.filename)) || |
| 1592 | // Now we check for fun, if the function name is Raven or TraceKit | 1686 | // Now we check for fun, if the function name is Raven or TraceKit |
| 1593 | /(Raven|TraceKit)\./.test(normalized['function']) || | 1687 | /(Raven|TraceKit)\./.test(normalized['function']) || |
| 1594 | // finally, we do a last ditch effort and check for raven.min.js | 1688 | // finally, we do a last ditch effort and check for raven.min.js |
| @@ -1638,20 +1732,12 @@ function extractContextFromFrame(frame) { · 43 unmodified lines | |||
| 1638 | } | 1732 | } |
| 1639 | 1733 | ||
| 1640 | function processException(type, message, fileurl, lineno, frames, options) { | 1734 | function processException(type, message, fileurl, lineno, frames, options) { |
| 1641 | var stacktrace, label, i; | 1735 | var stacktrace, i, fullMessage; |
| 1642 | 1736 | ||
| 1643 | // In some instances message is not actually a string, no idea why, | 1737 | if (!!globalOptions.ignoreErrors.test && globalOptions.ignoreErrors.test(message)) return; |
| 1644 | // so we want to always coerce it to one. | ||
| 1645 | message += ''; | ||
| 1646 | |||
| 1647 | // Sometimes an exception is getting logged in Sentry as | ||
| 1648 | // <no message value> | ||
| 1649 | // This can only mean that the message was falsey since this value | ||
| 1650 | // is hardcoded into Sentry itself. | ||
| 1651 | // At this point, if the message is falsey, we bail since it's useless | ||
| 1652 | if (type === 'Error' && !message) return; | ||
| 1653 | 1738 | ||
| 1654 | if (globalOptions.ignoreErrors.test(message)) return; | 1739 | message += ''; |
| 1740 | fullMessage = type + ': ' + message; | ||
| 1655 | 1741 | ||
| 1656 | if (frames && frames.length) { | 1742 | if (frames && frames.length) { |
| 1657 | fileurl = frames[0].filename || fileurl; | 1743 | fileurl = frames[0].filename || fileurl; |
| @@ -1669,26 +1755,22 @@ function processException(type, message, fileurl, lineno, frames, options) { · 11 unmodified lines | |||
| 1669 | }; | 1755 | }; |
| 1670 | } | 1756 | } |
| 1671 | 1757 | ||
| 1672 | // Truncate the message to a max of characters | 1758 | if (!!globalOptions.ignoreUrls.test && globalOptions.ignoreUrls.test(fileurl)) return; |
| 1673 | message = truncate(message, globalOptions.maxMessageLength); | 1759 | if (!!globalOptions.whitelistUrls.test && !globalOptions.whitelistUrls.test(fileurl)) return; |
| 1674 | |||
| 1675 | if (globalOptions.ignoreUrls && globalOptions.ignoreUrls.test(fileurl)) return; | ||
| 1676 | if (globalOptions.whitelistUrls && !globalOptions.whitelistUrls.test(fileurl)) return; | ||
| 1677 | |||
| 1678 | label = lineno ? message + ' at ' + lineno : message; | ||
| 1679 | 1760 | ||
| 1680 | // Fire away! | 1761 | // Fire away! |
| 1681 | send( | 1762 | send( |
| 1682 | objectMerge({ | 1763 | objectMerge({ |
| 1683 | // sentry.interfaces.Exception | 1764 | // sentry.interfaces.Exception |
| 1684 | exception: { | 1765 | exception: { |
| 1685 | type: type, | 1766 | values: [{ |
| 1686 | value: message | 1767 | type: type, |
| 1768 | value: message, | ||
| 1769 | stacktrace: stacktrace | ||
| 1770 | }] | ||
| 1687 | }, | 1771 | }, |
| 1688 | // sentry.interfaces.Stacktrace | ||
| 1689 | stacktrace: stacktrace, | ||
| 1690 | culprit: fileurl, | 1772 | culprit: fileurl, |
| 1691 | message: label | 1773 | message: fullMessage |
| 1692 | }, options) | 1774 | }, options) |
| 1693 | ); | 1775 | ); |
| 1694 | } | 1776 | } |
| @@ -1707,58 +1789,83 @@ function truncate(str, max) { · 12 unmodified lines | |||
| 1707 | return str.length <= max ? str : str.substr(0, max) + '\u2026'; | 1789 | return str.length <= max ? str : str.substr(0, max) + '\u2026'; |
| 1708 | } | 1790 | } |
| 1709 | 1791 | ||
| 1792 | function trimPacket(data) { | ||
| 1793 | // For now, we only want to truncate the two different messages | ||
| 1794 | // but this could/should be expanded to just trim everything | ||
| 1795 | var max = globalOptions.maxMessageLength; | ||
| 1796 | data.message = truncate(data.message, max); | ||
| 1797 | if (data.exception) { | ||
| 1798 | var exception = data.exception.values[0]; | ||
| 1799 | exception.value = truncate(exception.value, max); | ||
| 1800 | } | ||
| 1801 | |||
| 1802 | return data; | ||
| 1803 | } | ||
| 1804 | |||
| 1710 | function now() { | 1805 | function now() { |
| 1711 | return +new Date(); | 1806 | return +new Date(); |
| 1712 | } | 1807 | } |
| 1713 | 1808 | ||
| 1714 | function getHttpData() { | 1809 | function getHttpData() { |
| 1715 | var http = { | 1810 | if (!hasDocument || !document.location || !document.location.href) { |
| 1716 | url: document.location.href, | 1811 | return; |
| 1812 | } | ||
| 1813 | |||
| 1814 | var httpData = { | ||
| 1717 | headers: { | 1815 | headers: { |
| 1718 | 'User-Agent': navigator.userAgent | 1816 | 'User-Agent': navigator.userAgent |
| 1719 | } | 1817 | } |
| 1720 | }; | 1818 | }; |
| 1721 | 1819 | ||
| 1820 | httpData.url = document.location.href; | ||
| 1821 | |||
| 1722 | if (document.referrer) { | 1822 | if (document.referrer) { |
| 1723 | http.headers.Referer = document.referrer; | 1823 | httpData.headers.Referer = document.referrer; |
| 1724 | } | 1824 | } |
| 1725 | 1825 | ||
| 1726 | return http; | 1826 | return httpData; |
| 1727 | } | 1827 | } |
| 1728 | 1828 | ||
| 1729 | function send(data) { | 1829 | function send(data) { |
| 1730 | if (!isSetup()) return; | 1830 | var baseData = { |
| 1731 | |||
| 1732 | data = objectMerge({ | ||
| 1733 | project: globalProject, | 1831 | project: globalProject, |
| 1734 | logger: globalOptions.logger, | 1832 | logger: globalOptions.logger, |
| 1735 | platform: 'javascript', | 1833 | platform: 'javascript' |
| 1736 | // sentry.interfaces.Http | 1834 | }, httpData = getHttpData(); |
| 1737 | request: getHttpData() | 1835 | |
| 1738 | }, data); | 1836 | if (httpData) { |
| 1837 | baseData.request = httpData; | ||
| 1838 | } | ||
| 1839 | |||
| 1840 | data = objectMerge(baseData, data); | ||
| 1739 | 1841 | ||
| 1740 | // Merge in the tags and extra separately since objectMerge doesn't handle a deep merge | 1842 | // Merge in the tags and extra separately since objectMerge doesn't handle a deep merge |
| 1741 | data.tags = objectMerge(objectMerge({}, globalOptions.tags), data.tags); | 1843 | data.tags = objectMerge(objectMerge({}, globalContext.tags), data.tags); |
| 1742 | data.extra = objectMerge(objectMerge({}, globalOptions.extra), data.extra); | 1844 | data.extra = objectMerge(objectMerge({}, globalContext.extra), data.extra); |
| 1743 | 1845 | ||
| 1744 | // Send along our own collected metadata with extra | 1846 | // Send along our own collected metadata with extra |
| 1745 | data.extra = objectMerge({ | 1847 | data.extra['session:duration'] = now() - startTime; |
| 1746 | 'session:duration': now() - startTime | ||
| 1747 | }, data.extra); | ||
| 1748 | 1848 | ||
| 1749 | // If there are no tags/extra, strip the key from the payload alltogther. | 1849 | // If there are no tags/extra, strip the key from the payload alltogther. |
| 1750 | if (isEmptyObject(data.tags)) delete data.tags; | 1850 | if (isEmptyObject(data.tags)) delete data.tags; |
| 1751 | 1851 | ||
| 1752 | if (globalUser) { | 1852 | if (globalContext.user) { |
| 1753 | // sentry.interfaces.User | 1853 | // sentry.interfaces.User |
| 1754 | data.user = globalUser; | 1854 | data.user = globalContext.user; |
| 1755 | } | 1855 | } |
| 1756 | 1856 | ||
| 1757 | // Include the release iff it's defined in globalOptions | 1857 | // Include the release if it's defined in globalOptions |
| 1758 | if (globalOptions.release) data.release = globalOptions.release; | 1858 | if (globalOptions.release) data.release = globalOptions.release; |
| 1859 | // Include server_name if it's defined in globalOptions | ||
| 1860 | if (globalOptions.serverName) data.server_name = globalOptions.serverName; | ||
| 1759 | 1861 | ||
| 1760 | if (isFunction(globalOptions.dataCallback)) { | 1862 | if (isFunction(globalOptions.dataCallback)) { |
| 1761 | data = globalOptions.dataCallback(data); | 1863 | data = globalOptions.dataCallback(data) || data; |
| 1864 | } | ||
| 1865 | |||
| 1866 | // Why?????????? | ||
| 1867 | if (!data || isEmptyObject(data)) { | ||
| 1868 | return; | ||
| 1762 | } | 1869 | } |
| 1763 | 1870 | ||
| 1764 | // Check if the request should be filtered or not | 1871 | // Check if the request should be filtered or not |
| @@ -1771,34 +1878,68 @@ function send(data) { · 6 unmodified lines | |||
| 1771 | // Set lastEventId after we know the error should actually be sent | 1878 | // Set lastEventId after we know the error should actually be sent |
| 1772 | lastEventId = data.event_id || (data.event_id = uuid4()); | 1879 | lastEventId = data.event_id || (data.event_id = uuid4()); |
| 1773 | 1880 | ||
| 1774 | makeRequest(data); | 1881 | // Try and clean up the packet before sending by truncating long values |
| 1882 | data = trimPacket(data); | ||
| 1883 | |||
| 1884 | logDebug('debug', 'Raven about to send:', data); | ||
| 1885 | |||
| 1886 | if (!isSetup()) return; | ||
| 1887 | |||
| 1888 | (globalOptions.transport || makeRequest)({ | ||
| 1889 | url: globalServer, | ||
| 1890 | auth: { | ||
| 1891 | sentry_version: '7', | ||
| 1892 | sentry_client: 'raven-js/' + Raven.VERSION, | ||
| 1893 | sentry_key: globalKey | ||
| 1894 | }, | ||
| 1895 | data: data, | ||
| 1896 | options: globalOptions, | ||
| 1897 | onSuccess: function success() { | ||
| 1898 | triggerEvent('success', { | ||
| 1899 | data: data, | ||
| 1900 | src: globalServer | ||
| 1901 | }); | ||
| 1902 | }, | ||
| 1903 | onError: function failure() { | ||
| 1904 | triggerEvent('failure', { | ||
| 1905 | data: data, | ||
| 1906 | src: globalServer | ||
| 1907 | }); | ||
| 1908 | } | ||
| 1909 | }); | ||
| 1775 | } | 1910 | } |
| 1776 | 1911 | ||
| 1912 | function makeRequest(opts) { | ||
| 1913 | // Tack on sentry_data to auth options, which get urlencoded | ||
| 1914 | opts.auth.sentry_data = JSON.stringify(opts.data); | ||
| 1777 | 1915 | ||
| 1778 | function makeRequest(data) { | 1916 | var img = newImage(), |
| 1779 | var img = new Image(), | 1917 | src = opts.url + '?' + urlencode(opts.auth), |
| 1780 | src = globalServer + authQueryString + '&sentry_data=' + encodeURIComponent(JSON.stringify(data)); | 1918 | crossOrigin = opts.options.crossOrigin; |
| 1781 | 1919 | ||
| 1782 | img.crossOrigin = 'anonymous'; | 1920 | if (crossOrigin || crossOrigin === '') { |
| 1783 | img.onload = function success() { | 1921 | img.crossOrigin = crossOrigin; |
| 1784 | triggerEvent('success', { | 1922 | } |
| 1785 | data: data, | 1923 | img.onload = opts.onSuccess; |
| 1786 | src: src | 1924 | img.onerror = img.onabort = opts.onError; |
| 1787 | }); | ||
| 1788 | }; | ||
| 1789 | img.onerror = img.onabort = function failure() { | ||
| 1790 | triggerEvent('failure', { | ||
| 1791 | data: data, | ||
| 1792 | src: src | ||
| 1793 | }); | ||
| 1794 | }; | ||
| 1795 | img.src = src; | 1925 | img.src = src; |
| 1796 | } | 1926 | } |
| 1797 | 1927 | ||
| 1928 | // Note: this is shitty, but I can't figure out how to get | ||
| 1929 | // sinon to stub document.createElement without breaking everything | ||
| 1930 | // so this wrapper is just so I can stub it for tests. | ||
| 1931 | function newImage() { | ||
| 1932 | return document.createElement('img'); | ||
| 1933 | } | ||
| 1934 | |||
| 1935 | var ravenNotConfiguredError; | ||
| 1936 | |||
| 1798 | function isSetup() { | 1937 | function isSetup() { |
| 1799 | if (!hasJSON) return false; // needs JSON support | 1938 | if (!hasJSON) return false; // needs JSON support |
| 1800 | if (!globalServer) { | 1939 | if (!globalServer) { |
| 1801 | logDebug('error', 'Error: Raven has not been configured.'); | 1940 | if (!ravenNotConfiguredError) |
| 1941 | logDebug('error', 'Error: Raven has not been configured.'); | ||
| 1942 | ravenNotConfiguredError = true; | ||
| 1802 | return false; | 1943 | return false; |
| 1803 | } | 1944 | } |
| 1804 | return true; | 1945 | return true; |
| @@ -1826,18 +1967,44 @@ function joinRegExp(patterns) { · 21 unmodified lines | |||
| 1826 | return new RegExp(sources.join('|'), 'i'); | 1967 | return new RegExp(sources.join('|'), 'i'); |
| 1827 | } | 1968 | } |
| 1828 | 1969 | ||
| 1829 | // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523 | ||
| 1830 | function uuid4() { | 1970 | function uuid4() { |
| 1831 | return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) { | 1971 | var crypto = window.crypto || window.msCrypto; |
| 1832 | var r = Math.random()*16|0, | 1972 | |
| 1833 | v = c == 'x' ? r : (r&0x3|0x8); | 1973 | if (!isUndefined(crypto) && crypto.getRandomValues) { |
| 1834 | return v.toString(16); | 1974 | // Use window.crypto API if available |
| 1835 | }); | 1975 | var arr = new Uint16Array(8); |
| 1976 | crypto.getRandomValues(arr); | ||
| 1977 | |||
| 1978 | // set 4 in byte 7 | ||
| 1979 | arr[3] = arr[3] & 0xFFF | 0x4000; | ||
| 1980 | // set 2 most significant bits of byte 9 to '10' | ||
| 1981 | arr[4] = arr[4] & 0x3FFF | 0x8000; | ||
| 1982 | |||
| 1983 | var pad = function(num) { | ||
| 1984 | var v = num.toString(16); | ||
| 1985 | while (v.length < 4) { | ||
| 1986 | v = '0' + v; | ||
| 1987 | } | ||
| 1988 | return v; | ||
| 1989 | }; | ||
| 1990 | |||
| 1991 | return (pad(arr[0]) + pad(arr[1]) + pad(arr[2]) + pad(arr[3]) + pad(arr[4]) + | ||
| 1992 | pad(arr[5]) + pad(arr[6]) + pad(arr[7])); | ||
| 1993 | } else { | ||
| 1994 | // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523 | ||
| 1995 | return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) { | ||
| 1996 | var r = Math.random()*16|0, | ||
| 1997 | v = c == 'x' ? r : (r&0x3|0x8); | ||
| 1998 | return v.toString(16); | ||
| 1999 | }); | ||
| 2000 | } | ||
| 1836 | } | 2001 | } |
| 1837 | 2002 | ||
| 1838 | function logDebug(level, message) { | 2003 | function logDebug(level) { |
| 1839 | if (window.console && console[level] && Raven.debug) { | 2004 | if (originalConsoleMethods[level] && Raven.debug) { |
| 1840 | console[level](message); | 2005 | // _slice is coming from vendor/TraceKit/tracekit.js |
| 2006 | // so it's accessible globally | ||
| 2007 | originalConsoleMethods[level].apply(originalConsole, _slice.call(arguments, 1)); | ||
| 1841 | } | 2008 | } |
| 1842 | } | 2009 | } |
| 1843 | 2010 | ||
| @@ -1848,12 +2015,32 @@ function afterLoad() { · 4 unmodified lines | |||
| 1848 | Raven.config(RavenConfig.dsn, RavenConfig.config).install(); | 2015 | Raven.config(RavenConfig.dsn, RavenConfig.config).install(); |
| 1849 | } | 2016 | } |
| 1850 | } | 2017 | } |
| 2018 | |||
| 2019 | function urlencode(o) { | ||
| 2020 | var pairs = []; | ||
| 2021 | each(o, function(key, value) { | ||
| 2022 | pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); | ||
| 2023 | }); | ||
| 2024 | return pairs.join('&'); | ||
| 2025 | } | ||
| 2026 | |||
| 2027 | function mergeContext(key, context) { | ||
| 2028 | if (isUndefined(context)) { | ||
| 2029 | delete globalContext[key]; | ||
| 2030 | } else { | ||
| 2031 | globalContext[key] = objectMerge(globalContext[key] || {}, context); | ||
| 2032 | } | ||
| 2033 | } | ||
| 2034 | |||
| 1851 | afterLoad(); | 2035 | afterLoad(); |
| 1852 | 2036 | ||
| 2037 | // This is being exposed no matter what because there are too many weird | ||
| 2038 | // usecases for how people use Raven. If this is really a problem, I'm sorry. | ||
| 2039 | window.Raven = Raven; | ||
| 2040 | |||
| 1853 | // Expose Raven to the world | 2041 | // Expose Raven to the world |
| 1854 | if (typeof define === 'function' && define.amd) { | 2042 | if (typeof define === 'function' && define.amd) { |
| 1855 | // AMD | 2043 | // AMD |
| 1856 | window.Raven = Raven; | ||
| 1857 | define('raven', [], function() { | 2044 | define('raven', [], function() { |
| 1858 | return Raven; | 2045 | return Raven; |
| 1859 | }); | 2046 | }); |
| @@ -1863,9 +2050,6 @@ if (typeof define === 'function' && define.amd) { · 3 unmodified lines | |||
| 1863 | } else if (typeof exports === 'object') { | 2050 | } else if (typeof exports === 'object') { |
| 1864 | // CommonJS | 2051 | // CommonJS |
| 1865 | exports = Raven; | 2052 | exports = Raven; |
| 1866 | } else { | ||
| 1867 | // Everything else | ||
| 1868 | window.Raven = Raven; | ||
| 1869 | } | 2053 | } |
| 1870 | 2054 | ||
| 1871 | })(window); | 2055 | })(typeof window !== 'undefined' ? window : this); |