https://github.com/getsentry/sentry-javascript/blob/d5e44e2cf87ccecefc9a07bc460f403b3a0f46fd/dist/raven.js Reformatted using Prettier.io
Unified · Split
| @@ -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 */ |
| 2 | 2 | ||
| 3 | /* | 3 | /* |
| 4 | * Includes TraceKit | 4 | * Includes TraceKit |
| 5 | * https://github.com/getsentry/TraceKit | 5 | * https://github.com/getsentry/TraceKit |
| 6 | * | 6 | * |
| 7 | * Copyright 2017 Matt Robenolt and other contributors | 7 | * Copyright 2018 Matt Robenolt and other contributors |
| 8 | * Released under the BSD license | 8 | * Released under the BSD license |
| 9 | * https://github.com/getsentry/raven-js/blob/master/LICENSE | 9 | * https://github.com/getsentry/raven-js/blob/master/LICENSE |
| 10 | * | 10 | * |
| @@ -77,6 +77,8 @@ · 66 unmodified lines | |||
| 77 | ], | 77 | ], |
| 78 | 2: [ | 78 | 2: [ |
| 79 | function (_dereq_, module, exports) { | 79 | function (_dereq_, module, exports) { |
| 80 | var utils = _dereq_(5); | ||
| 81 | |||
| 80 | var wrapMethod = function (console, level, callback) { | 82 | var wrapMethod = function (console, level, callback) { |
| 81 | var originalConsoleLevel = console[level]; | 83 | var originalConsoleLevel = console[level]; |
| 82 | var originalConsole = console; | 84 | var originalConsole = console; |
| @@ -90,7 +92,7 @@ · 7 unmodified lines | |||
| 90 | console[level] = function () { | 92 | console[level] = function () { |
| 91 | var args = [].slice.call(arguments); | 93 | var args = [].slice.call(arguments); |
| 92 | 94 | ||
| 93 | var msg = "" + args.join(" "); | 95 | var msg = utils.safeJoin(args, " "); |
| 94 | var data = { | 96 | var data = { |
| 95 | level: sentryLevel, | 97 | level: sentryLevel, |
| 96 | logger: "console", | 98 | logger: "console", |
| @@ -102,7 +104,7 @@ · 5 unmodified lines | |||
| 102 | // Default browsers message | 104 | // Default browsers message |
| 103 | msg = | 105 | msg = |
| 104 | "Assertion failed: " + | 106 | "Assertion failed: " + |
| 105 | (args.slice(1).join(" ") || "console.assert"); | 107 | (utils.safeJoin(args.slice(1), " ") || "console.assert"); |
| 106 | data.extra.arguments = args.slice(1); | 108 | data.extra.arguments = args.slice(1); |
| 107 | callback && callback(msg, data); | 109 | callback && callback(msg, data); |
| 108 | } | 110 | } |
| @@ -127,7 +129,7 @@ · 18 unmodified lines | |||
| 127 | wrapMethod: wrapMethod, | 129 | wrapMethod: wrapMethod, |
| 128 | }; | 130 | }; |
| 129 | }, | 131 | }, |
| 130 | {}, | 132 | { 5: 5 }, |
| 131 | ], | 133 | ], |
| 132 | 3: [ | 134 | 3: [ |
| 133 | function (_dereq_, module, exports) { | 135 | function (_dereq_, module, exports) { |
| @@ -136,12 +138,16 @@ · 2 unmodified lines | |||
| 136 | 138 | ||
| 137 | var TraceKit = _dereq_(6); | 139 | var TraceKit = _dereq_(6); |
| 138 | var stringify = _dereq_(7); | 140 | var stringify = _dereq_(7); |
| 141 | var md5 = _dereq_(8); | ||
| 139 | var RavenConfigError = _dereq_(1); | 142 | var RavenConfigError = _dereq_(1); |
| 140 | 143 | ||
| 141 | var utils = _dereq_(5); | 144 | var utils = _dereq_(5); |
| 145 | var isErrorEvent = utils.isErrorEvent; | ||
| 146 | var isDOMError = utils.isDOMError; | ||
| 147 | var isDOMException = utils.isDOMException; | ||
| 142 | var isError = utils.isError; | 148 | var isError = utils.isError; |
| 143 | var isObject = utils.isObject; | 149 | var isObject = utils.isObject; |
| 144 | var isErrorEvent = utils.isErrorEvent; | 150 | var isPlainObject = utils.isPlainObject; |
| 145 | var isUndefined = utils.isUndefined; | 151 | var isUndefined = utils.isUndefined; |
| 146 | var isFunction = utils.isFunction; | 152 | var isFunction = utils.isFunction; |
| 147 | var isString = utils.isString; | 153 | var isString = utils.isString; |
| @@ -160,6 +166,11 @@ · 12 unmodified lines | |||
| 160 | var isSameStacktrace = utils.isSameStacktrace; | 166 | var isSameStacktrace = utils.isSameStacktrace; |
| 161 | var parseUrl = utils.parseUrl; | 167 | var parseUrl = utils.parseUrl; |
| 162 | var fill = utils.fill; | 168 | 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; | ||
| 163 | 174 | ||
| 164 | var wrapConsoleMethod = _dereq_(2).wrapMethod; | 175 | var wrapConsoleMethod = _dereq_(2).wrapMethod; |
| 165 | 176 | ||
| @@ -207,20 +218,33 @@ · 41 unmodified lines | |||
| 207 | this._globalProject = null; | 218 | this._globalProject = null; |
| 208 | this._globalContext = {}; | 219 | this._globalContext = {}; |
| 209 | this._globalOptions = { | 220 | 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, | ||
| 210 | logger: "javascript", | 223 | logger: "javascript", |
| 211 | ignoreErrors: [], | 224 | ignoreErrors: [], |
| 212 | ignoreUrls: [], | 225 | ignoreUrls: [], |
| 213 | whitelistUrls: [], | 226 | whitelistUrls: [], |
| 214 | includePaths: [], | 227 | includePaths: [], |
| 228 | headers: null, | ||
| 215 | collectWindowErrors: true, | 229 | collectWindowErrors: true, |
| 230 | captureUnhandledRejections: true, | ||
| 216 | maxMessageLength: 0, | 231 | maxMessageLength: 0, |
| 217 | |||
| 218 | // By default, truncates URL values to 250 chars | 232 | // By default, truncates URL values to 250 chars |
| 219 | maxUrlLength: 250, | 233 | maxUrlLength: 250, |
| 220 | stackTraceLimit: 50, | 234 | stackTraceLimit: 50, |
| 221 | autoBreadcrumbs: true, | 235 | autoBreadcrumbs: true, |
| 222 | instrument: true, | 236 | instrument: true, |
| 223 | sampleRate: 1, | 237 | 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" : "", | ||
| 224 | }; | 248 | }; |
| 225 | this._ignoreOnError = 0; | 249 | this._ignoreOnError = 0; |
| 226 | this._isRavenInstalled = false; | 250 | this._isRavenInstalled = false; |
| @@ -257,7 +281,7 @@ · 30 unmodified lines | |||
| 257 | // webpack (using a build step causes webpack #1617). Grunt verifies that | 281 | // webpack (using a build step causes webpack #1617). Grunt verifies that |
| 258 | // this value matches package.json during build. | 282 | // this value matches package.json during build. |
| 259 | // See: https://github.com/getsentry/raven-js/issues/465 | 283 | // See: https://github.com/getsentry/raven-js/issues/465 |
| 260 | VERSION: "3.20.1", | 284 | VERSION: "3.25.2", |
| 261 | 285 | ||
| 262 | debug: false, | 286 | debug: false, |
| 263 | 287 | ||
| @@ -376,6 +400,10 @@ · 112 unmodified lines | |||
| 376 | self._handleOnErrorStackInfo.apply(self, arguments); | 400 | self._handleOnErrorStackInfo.apply(self, arguments); |
| 377 | }); | 401 | }); |
| 378 | 402 | ||
| 403 | if (self._globalOptions.captureUnhandledRejections) { | ||
| 404 | self._attachPromiseRejectionHandler(); | ||
| 405 | } | ||
| 406 | |||
| 379 | self._patchFunctionToString(); | 407 | self._patchFunctionToString(); |
| 380 | 408 | ||
| 381 | if ( | 409 | if ( |
| @@ -538,7 +566,7 @@ · 156 unmodified lines | |||
| 538 | return wrapped; | 566 | return wrapped; |
| 539 | }, | 567 | }, |
| 540 | 568 | ||
| 541 | /* | 569 | /** |
| 542 | * Uninstalls the global error handler. | 570 | * Uninstalls the global error handler. |
| 543 | * | 571 | * |
| 544 | * @return {Raven} | 572 | * @return {Raven} |
| @@ -546,8 +574,10 @@ · 1 unmodified line | |||
| 546 | uninstall: function () { | 574 | uninstall: function () { |
| 547 | TraceKit.report.uninstall(); | 575 | TraceKit.report.uninstall(); |
| 548 | 576 | ||
| 577 | this._detachPromiseRejectionHandler(); | ||
| 549 | this._unpatchFunctionToString(); | 578 | this._unpatchFunctionToString(); |
| 550 | this._restoreBuiltIns(); | 579 | this._restoreBuiltIns(); |
| 580 | this._restoreConsole(); | ||
| 551 | 581 | ||
| 552 | Error.stackTraceLimit = this._originalErrorStackTraceLimit; | 582 | Error.stackTraceLimit = this._originalErrorStackTraceLimit; |
| 553 | this._isRavenInstalled = false; | 583 | this._isRavenInstalled = false; |
| @@ -555,7 +585,58 @@ · 1 unmodified line | |||
| 555 | return this; | 585 | return this; |
| 556 | }, | 586 | }, |
| 557 | 587 | ||
| 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 | /** | ||
| 559 | * Manually capture an exception and send it over to Sentry | 640 | * Manually capture an exception and send it over to Sentry |
| 560 | * | 641 | * |
| 561 | * @param {error} ex An exception to be logged | 642 | * @param {error} ex An exception to be logged |
| @@ -563,30 +644,60 @@ · 1 unmodified line | |||
| 563 | * @return {Raven} | 644 | * @return {Raven} |
| 564 | */ | 645 | */ |
| 565 | captureException: function (ex, options) { | 646 | captureException: function (ex, options) { |
| 566 | // Cases for sending ex as a message, rather than an exception | 647 | options = objectMerge( |
| 567 | var isNotError = !isError(ex); | 648 | { trimHeadFrames: 0 }, |
| 568 | var isNotErrorEvent = !isErrorEvent(ex); | 649 | options ? options : {}, |
| 569 | var isErrorEventWithoutError = isErrorEvent(ex) && !ex.error; | 650 | ); |
| 570 | 651 | ||
| 571 | if ( | 652 | if (isErrorEvent(ex) && ex.error) { |
| 572 | (isNotError && isNotErrorEvent) || | 653 | // If it is an ErrorEvent with `error` property, extract it to get actual Error |
| 573 | isErrorEventWithoutError | 654 | ex = ex.error; |
| 574 | ) { | 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: | ||
| 575 | return this.captureMessage( | 692 | return this.captureMessage( |
| 576 | ex, | 693 | ex, |
| 577 | objectMerge( | 694 | objectMerge(options, { |
| 578 | { | 695 | stacktrace: true, // if we fall back to captureMessage, default to attempting a new trace |
| 579 | trimHeadFrames: 1, | 696 | trimHeadFrames: options.trimHeadFrames + 1, |
| 580 | stacktrace: true, // if we fall back to captureMessage, default to attempting a new trace | 697 | }), |
| 581 | }, | ||
| 582 | options, | ||
| 583 | ), | ||
| 584 | ); | 698 | ); |
| 585 | } | 699 | } |
| 586 | 700 | ||
| 587 | // Get actual Error from ErrorEvent | ||
| 588 | if (isErrorEvent(ex)) ex = ex.error; | ||
| 589 | |||
| 590 | // Store the raw exception object for potential debugging and introspection | 701 | // Store the raw exception object for potential debugging and introspection |
| 591 | this._lastCapturedException = ex; | 702 | this._lastCapturedException = ex; |
| 592 | 703 | ||
| @@ -607,6 +718,23 @@ · 14 unmodified lines | |||
| 607 | return this; | 718 | return this; |
| 608 | }, | 719 | }, |
| 609 | 720 | ||
| 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 | |||
| 610 | /* | 738 | /* |
| 611 | * Manually send a message to Sentry | 739 | * Manually send a message to Sentry |
| 612 | * | 740 | * |
| @@ -626,10 +754,11 @@ · 13 unmodified lines | |||
| 626 | } | 754 | } |
| 627 | 755 | ||
| 628 | options = options || {}; | 756 | options = options || {}; |
| 757 | msg = msg + ""; // Make sure it's actually a string | ||
| 629 | 758 | ||
| 630 | var data = objectMerge( | 759 | var data = objectMerge( |
| 631 | { | 760 | { |
| 632 | message: msg + "", // Make sure it's actually a string | 761 | message: msg, |
| 633 | }, | 762 | }, |
| 634 | options, | 763 | options, |
| 635 | ); | 764 | ); |
| @@ -651,6 +780,17 @@ · 15 unmodified lines | |||
| 651 | 780 | ||
| 652 | // stack[0] is `throw new Error(msg)` call itself, we are interested in the frame that was just before that, stack[1] | 781 | // stack[0] is `throw new Error(msg)` call itself, we are interested in the frame that was just before that, stack[1] |
| 653 | var initialCall = isArray(stack.stack) && stack.stack[1]; | 782 | 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 | |||
| 654 | var fileurl = (initialCall && initialCall.url) || ""; | 794 | var fileurl = (initialCall && initialCall.url) || ""; |
| 655 | 795 | ||
| 656 | if ( | 796 | if ( |
| @@ -671,18 +811,21 @@ · 14 unmodified lines | |||
| 671 | this._globalOptions.stacktrace || | 811 | this._globalOptions.stacktrace || |
| 672 | (options && options.stacktrace) | 812 | (options && options.stacktrace) |
| 673 | ) { | 813 | ) { |
| 814 | // fingerprint on msg, not stack trace (legacy behavior, could be revisited) | ||
| 815 | data.fingerprint = | ||
| 816 | data.fingerprint == null ? msg : data.fingerprint; | ||
| 817 | |||
| 674 | options = objectMerge( | 818 | options = objectMerge( |
| 675 | { | 819 | { |
| 676 | // fingerprint on msg, not stack trace (legacy behavior, could be | 820 | trimHeadFrames: 0, |
| 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, | ||
| 683 | }, | 821 | }, |
| 684 | options, | 822 | options, |
| 685 | ); | 823 | ); |
| 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; | ||
| 686 | 829 | ||
| 687 | var frames = this._prepareFrames(stack, options); | 830 | var frames = this._prepareFrames(stack, options); |
| 688 | data.stacktrace = { | 831 | data.stacktrace = { |
| @@ -691,6 +834,13 @@ · 2 unmodified lines | |||
| 691 | }; | 834 | }; |
| 692 | } | 835 | } |
| 693 | 836 | ||
| 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 | |||
| 694 | // Fire away! | 844 | // Fire away! |
| 695 | this._send(data); | 845 | this._send(data); |
| 696 | 846 | ||
| @@ -976,7 +1126,7 @@ · 279 unmodified lines | |||
| 976 | }, | 1126 | }, |
| 977 | 1127 | ||
| 978 | _triggerEvent: function (eventType, options) { | 1128 | _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 |
| 980 | var evt, key; | 1130 | var evt, key; |
| 981 | 1131 | ||
| 982 | if (!this._hasDocument) return; | 1132 | if (!this._hasDocument) return; |
| @@ -1290,7 +1440,7 @@ · 307 unmodified lines | |||
| 1290 | 1440 | ||
| 1291 | fill(_window, "setTimeout", wrapTimeFn, wrappedBuiltIns); | 1441 | fill(_window, "setTimeout", wrapTimeFn, wrappedBuiltIns); |
| 1292 | fill(_window, "setInterval", wrapTimeFn, wrappedBuiltIns); | 1442 | fill(_window, "setInterval", wrapTimeFn, wrappedBuiltIns); |
| 1293 | if (_requestAnimationFrame) { | 1443 | if (_window.requestAnimationFrame) { |
| 1294 | fill( | 1444 | fill( |
| 1295 | _window, | 1445 | _window, |
| 1296 | "requestAnimationFrame", | 1446 | "requestAnimationFrame", |
| @@ -1365,7 +1515,8 @@ · 68 unmodified lines | |||
| 1365 | } | 1515 | } |
| 1366 | 1516 | ||
| 1367 | if (autoBreadcrumbs.xhr && "XMLHttpRequest" in _window) { | 1517 | if (autoBreadcrumbs.xhr && "XMLHttpRequest" in _window) { |
| 1368 | var xhrproto = XMLHttpRequest.prototype; | 1518 | var xhrproto = |
| 1519 | _window.XMLHttpRequest && _window.XMLHttpRequest.prototype; | ||
| 1369 | fill( | 1520 | fill( |
| 1370 | xhrproto, | 1521 | xhrproto, |
| 1371 | "open", | 1522 | "open", |
| @@ -1395,7 +1546,7 @@ · 23 unmodified lines | |||
| 1395 | xhrproto, | 1546 | xhrproto, |
| 1396 | "send", | 1547 | "send", |
| 1397 | function (origSend) { | 1548 | function (origSend) { |
| 1398 | return function (data) { | 1549 | return function () { |
| 1399 | // preserve arity | 1550 | // preserve arity |
| 1400 | var xhr = this; | 1551 | var xhr = this; |
| 1401 | 1552 | ||
| @@ -1450,12 +1601,12 @@ · 48 unmodified lines | |||
| 1450 | ); | 1601 | ); |
| 1451 | } | 1602 | } |
| 1452 | 1603 | ||
| 1453 | if (autoBreadcrumbs.xhr && "fetch" in _window) { | 1604 | if (autoBreadcrumbs.xhr && supportsFetch()) { |
| 1454 | fill( | 1605 | fill( |
| 1455 | _window, | 1606 | _window, |
| 1456 | "fetch", | 1607 | "fetch", |
| 1457 | function (origFetch) { | 1608 | function (origFetch) { |
| 1458 | return function (fn, t) { | 1609 | return function () { |
| 1459 | // preserve arity | 1610 | // preserve arity |
| 1460 | // Make a copy of the arguments to prevent deoptimization | 1611 | // Make a copy of the arguments to prevent deoptimization |
| 1461 | // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments | 1612 | // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments |
| @@ -1482,6 +1633,11 @@ · 20 unmodified lines | |||
| 1482 | url = "" + fetchInput; | 1633 | url = "" + fetchInput; |
| 1483 | } | 1634 | } |
| 1484 | 1635 | ||
| 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 | |||
| 1485 | if (args[1] && args[1].method) { | 1641 | if (args[1] && args[1].method) { |
| 1486 | method = args[1].method; | 1642 | method = args[1].method; |
| 1487 | } | 1643 | } |
| @@ -1492,18 +1648,29 @@ · 4 unmodified lines | |||
| 1492 | status_code: null, | 1648 | status_code: null, |
| 1493 | }; | 1649 | }; |
| 1494 | 1650 | ||
| 1495 | self.captureBreadcrumb({ | ||
| 1496 | type: "http", | ||
| 1497 | category: "fetch", | ||
| 1498 | data: fetchData, | ||
| 1499 | }); | ||
| 1500 | |||
| 1501 | return origFetch | 1651 | return origFetch |
| 1502 | .apply(this, args) | 1652 | .apply(this, args) |
| 1503 | .then(function (response) { | 1653 | .then(function (response) { |
| 1504 | fetchData.status_code = response.status; | 1654 | fetchData.status_code = response.status; |
| 1505 | 1655 | ||
| 1656 | self.captureBreadcrumb({ | ||
| 1657 | type: "http", | ||
| 1658 | category: "fetch", | ||
| 1659 | data: fetchData, | ||
| 1660 | }); | ||
| 1661 | |||
| 1506 | return response; | 1662 | 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; | ||
| 1507 | }); | 1674 | }); |
| 1508 | }; | 1675 | }; |
| 1509 | }, | 1676 | }, |
| @@ -1525,7 +1692,7 @@ · 15 unmodified lines | |||
| 1525 | self._keypressEventHandler(), | 1692 | self._keypressEventHandler(), |
| 1526 | false, | 1693 | false, |
| 1527 | ); | 1694 | ); |
| 1528 | } else { | 1695 | } else if (_document.attachEvent) { |
| 1529 | // IE8 Compatibility | 1696 | // IE8 Compatibility |
| 1530 | _document.attachEvent( | 1697 | _document.attachEvent( |
| 1531 | "onclick", | 1698 | "onclick", |
| @@ -1548,8 +1715,8 @@ · 16 unmodified lines | |||
| 1548 | var hasPushAndReplaceState = | 1715 | var hasPushAndReplaceState = |
| 1549 | !isChromePackagedApp && | 1716 | !isChromePackagedApp && |
| 1550 | _window.history && | 1717 | _window.history && |
| 1551 | history.pushState && | 1718 | _window.history.pushState && |
| 1552 | history.replaceState; | 1719 | _window.history.replaceState; |
| 1553 | if (autoBreadcrumbs.location && hasPushAndReplaceState) { | 1720 | if (autoBreadcrumbs.location && hasPushAndReplaceState) { |
| 1554 | // TODO: remove onpopstate handler on uninstall() | 1721 | // TODO: remove onpopstate handler on uninstall() |
| 1555 | var oldOnPopState = _window.onpopstate; | 1722 | var oldOnPopState = _window.onpopstate; |
| @@ -1579,13 +1746,13 @@ · 23 unmodified lines | |||
| 1579 | }; | 1746 | }; |
| 1580 | 1747 | ||
| 1581 | fill( | 1748 | fill( |
| 1582 | history, | 1749 | _window.history, |
| 1583 | "pushState", | 1750 | "pushState", |
| 1584 | historyReplacementFunction, | 1751 | historyReplacementFunction, |
| 1585 | wrappedBuiltIns, | 1752 | wrappedBuiltIns, |
| 1586 | ); | 1753 | ); |
| 1587 | fill( | 1754 | fill( |
| 1588 | history, | 1755 | _window.history, |
| 1589 | "replaceState", | 1756 | "replaceState", |
| 1590 | historyReplacementFunction, | 1757 | historyReplacementFunction, |
| 1591 | wrappedBuiltIns, | 1758 | wrappedBuiltIns, |
| @@ -1629,6 +1796,14 @@ · 37 unmodified lines | |||
| 1629 | } | 1796 | } |
| 1630 | }, | 1797 | }, |
| 1631 | 1798 | ||
| 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 | |||
| 1632 | _drainPlugins: function () { | 1807 | _drainPlugins: function () { |
| 1633 | var self = this; | 1808 | var self = this; |
| 1634 | 1809 | ||
| @@ -1822,7 +1997,7 @@ · 187 unmodified lines | |||
| 1822 | }, | 1997 | }, |
| 1823 | ], | 1998 | ], |
| 1824 | }, | 1999 | }, |
| 1825 | culprit: fileurl, | 2000 | transaction: fileurl, |
| 1826 | }, | 2001 | }, |
| 1827 | options, | 2002 | options, |
| 1828 | ); | 2003 | ); |
| @@ -1905,18 +2080,18 @@ · 76 unmodified lines | |||
| 1905 | 2080 | ||
| 1906 | if (this._hasNavigator && _navigator.userAgent) { | 2081 | if (this._hasNavigator && _navigator.userAgent) { |
| 1907 | httpData.headers = { | 2082 | httpData.headers = { |
| 1908 | "User-Agent": navigator.userAgent, | 2083 | "User-Agent": _navigator.userAgent, |
| 1909 | }; | 2084 | }; |
| 1910 | } | 2085 | } |
| 1911 | 2086 | ||
| 1912 | if (this._hasDocument) { | 2087 | // Check in `window` instead of `document`, as we may be in ServiceWorker environment |
| 1913 | if (_document.location && _document.location.href) { | 2088 | if (_window.location && _window.location.href) { |
| 1914 | httpData.url = _document.location.href; | 2089 | httpData.url = _window.location.href; |
| 1915 | } | 2090 | } |
| 1916 | if (_document.referrer) { | 2091 | |
| 1917 | if (!httpData.headers) httpData.headers = {}; | 2092 | if (this._hasDocument && _document.referrer) { |
| 1918 | httpData.headers.Referer = _document.referrer; | 2093 | if (!httpData.headers) httpData.headers = {}; |
| 1919 | } | 2094 | httpData.headers.Referer = _document.referrer; |
| 1920 | } | 2095 | } |
| 1921 | 2096 | ||
| 1922 | return httpData; | 2097 | return httpData; |
| @@ -1949,7 +2124,7 @@ · 26 unmodified lines | |||
| 1949 | if ( | 2124 | if ( |
| 1950 | !last || | 2125 | !last || |
| 1951 | current.message !== last.message || // defined for captureMessage | 2126 | 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 |
| 1953 | ) | 2128 | ) |
| 1954 | return false; | 2129 | return false; |
| 1955 | 2130 | ||
| @@ -1982,8 +2157,14 @@ · 26 unmodified lines | |||
| 1982 | try { | 2157 | try { |
| 1983 | // If Retry-After is not in Access-Control-Expose-Headers, most | 2158 | // If Retry-After is not in Access-Control-Expose-Headers, most |
| 1984 | // browsers will throw an exception trying to access it | 2159 | // browsers will throw an exception trying to access it |
| 1985 | retry = request.getResponseHeader("Retry-After"); | 2160 | if (supportsFetch()) { |
| 1986 | retry = parseInt(retry, 10) * 1000; // Retry-After is returned in seconds | 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; | ||
| 1987 | } catch (e) { | 2168 | } catch (e) { |
| 1988 | /* eslint no-empty:0 */ | 2169 | /* eslint no-empty:0 */ |
| 1989 | } | 2170 | } |
| @@ -2037,9 +2218,6 @@ · 47 unmodified lines | |||
| 2037 | }; | 2218 | }; |
| 2038 | } | 2219 | } |
| 2039 | 2220 | ||
| 2040 | // If there are no tags/extra, strip the key from the payload alltogther. | ||
| 2041 | if (isEmptyObject(data.tags)) delete data.tags; | ||
| 2042 | |||
| 2043 | if (this._globalContext.user) { | 2221 | if (this._globalContext.user) { |
| 2044 | // sentry.interfaces.User | 2222 | // sentry.interfaces.User |
| 2045 | data.user = this._globalContext.user; | 2223 | data.user = this._globalContext.user; |
| @@ -2056,6 +2234,19 @@ · 10 unmodified lines | |||
| 2056 | if (globalOptions.serverName) | 2234 | if (globalOptions.serverName) |
| 2057 | data.server_name = globalOptions.serverName; | 2235 | data.server_name = globalOptions.serverName; |
| 2058 | 2236 | ||
| 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 | |||
| 2059 | if (isFunction(globalOptions.dataCallback)) { | 2250 | if (isFunction(globalOptions.dataCallback)) { |
| 2060 | data = globalOptions.dataCallback(data) || data; | 2251 | data = globalOptions.dataCallback(data) || data; |
| 2061 | } | 2252 | } |
| @@ -2093,6 +2284,10 @@ · 31 unmodified lines | |||
| 2093 | } | 2284 | } |
| 2094 | }, | 2285 | }, |
| 2095 | 2286 | ||
| 2287 | _sanitizeData: function (data) { | ||
| 2288 | return sanitize(data, this._globalOptions.sanitizeKeys); | ||
| 2289 | }, | ||
| 2290 | |||
| 2096 | _getUuid: function () { | 2291 | _getUuid: function () { |
| 2097 | return uuid4(); | 2292 | return uuid4(); |
| 2098 | }, | 2293 | }, |
| @@ -2197,6 +2392,61 @@ · 98 unmodified lines | |||
| 2197 | }, | 2392 | }, |
| 2198 | 2393 | ||
| 2199 | _makeRequest: function (opts) { | 2394 | _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 | |||
| 2200 | var request = | 2450 | var request = |
| 2201 | _window.XMLHttpRequest && new _window.XMLHttpRequest(); | 2451 | _window.XMLHttpRequest && new _window.XMLHttpRequest(); |
| 2202 | if (!request) return; | 2452 | if (!request) return; |
| @@ -2208,8 +2458,6 @@ · 5 unmodified lines | |||
| 2208 | 2458 | ||
| 2209 | if (!hasCORS) return; | 2459 | if (!hasCORS) return; |
| 2210 | 2460 | ||
| 2211 | var url = opts.url; | ||
| 2212 | |||
| 2213 | if ("withCredentials" in request) { | 2461 | if ("withCredentials" in request) { |
| 2214 | request.onreadystatechange = function () { | 2462 | request.onreadystatechange = function () { |
| 2215 | if (request.readyState !== 4) { | 2463 | if (request.readyState !== 4) { |
| @@ -2243,14 +2491,37 @@ · 27 unmodified lines | |||
| 2243 | } | 2491 | } |
| 2244 | } | 2492 | } |
| 2245 | 2493 | ||
| 2246 | // NOTE: auth is intentionally sent as part of query string (NOT as custom | 2494 | request.open("POST", url); |
| 2247 | // HTTP header) so as to avoid preflight CORS requests | 2495 | |
| 2248 | request.open("POST", url + "?" + urlencode(opts.auth)); | 2496 | if (evaluatedHeaders) { |
| 2497 | each(evaluatedHeaders, function (key, value) { | ||
| 2498 | request.setRequestHeader(key, value); | ||
| 2499 | }); | ||
| 2500 | } | ||
| 2501 | |||
| 2249 | request.send(stringify(opts.data)); | 2502 | request.send(stringify(opts.data)); |
| 2250 | }, | 2503 | }, |
| 2251 | 2504 | ||
| 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 | |||
| 2252 | _logDebug: function (level) { | 2519 | _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 | ) { | ||
| 2254 | // In IE<10 console methods do not have their own 'apply' method | 2525 | // In IE<10 console methods do not have their own 'apply' method |
| 2255 | Function.prototype.apply.call( | 2526 | Function.prototype.apply.call( |
| 2256 | this._originalConsoleMethods[level], | 2527 | this._originalConsoleMethods[level], |
| @@ -2288,7 +2559,7 @@ · 31 unmodified lines | |||
| 2288 | : {}, | 2559 | : {}, |
| 2289 | ); | 2560 | ); |
| 2290 | }, | 2561 | }, |
| 2291 | { 1: 1, 2: 2, 5: 5, 6: 6, 7: 7 }, | 2562 | { 1: 1, 2: 2, 5: 5, 6: 6, 7: 7, 8: 8 }, |
| 2292 | ], | 2563 | ], |
| 2293 | 4: [ | 2564 | 4: [ |
| 2294 | function (_dereq_, module, exports) { | 2565 | function (_dereq_, module, exports) { |
| @@ -2328,6 +2599,42 @@ · 33 unmodified lines | |||
| 2328 | Raven.afterLoad(); | 2599 | Raven.afterLoad(); |
| 2329 | 2600 | ||
| 2330 | module.exports = Raven; | 2601 | 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; | ||
| 2331 | }).call( | 2638 | }).call( |
| 2332 | this, | 2639 | this, |
| 2333 | typeof global !== "undefined" | 2640 | typeof global !== "undefined" |
| @@ -2344,6 +2651,8 @@ · 10 unmodified lines | |||
| 2344 | 5: [ | 2651 | 5: [ |
| 2345 | function (_dereq_, module, exports) { | 2652 | function (_dereq_, module, exports) { |
| 2346 | (function (global) { | 2653 | (function (global) { |
| 2654 | var stringify = _dereq_(7); | ||
| 2655 | |||
| 2347 | var _window = | 2656 | var _window = |
| 2348 | typeof window !== "undefined" | 2657 | typeof window !== "undefined" |
| 2349 | ? window | 2658 | ? window |
| @@ -2360,7 +2669,7 @@ · 10 unmodified lines | |||
| 2360 | // Yanked from https://git.io/vS8DV re-used under CC0 | 2669 | // Yanked from https://git.io/vS8DV re-used under CC0 |
| 2361 | // with some tiny modifications | 2670 | // with some tiny modifications |
| 2362 | function isError(value) { | 2671 | function isError(value) { |
| 2363 | switch ({}.toString.call(value)) { | 2672 | switch (Object.prototype.toString.call(value)) { |
| 2364 | case "[object Error]": | 2673 | case "[object Error]": |
| 2365 | return true; | 2674 | return true; |
| 2366 | case "[object Exception]": | 2675 | case "[object Exception]": |
| @@ -2374,8 +2683,20 @@ · 7 unmodified lines | |||
| 2374 | 2683 | ||
| 2375 | function isErrorEvent(value) { | 2684 | function isErrorEvent(value) { |
| 2376 | return ( | 2685 | return ( |
| 2377 | supportsErrorEvent() && | 2686 | Object.prototype.toString.call(value) === "[object ErrorEvent]" |
| 2378 | {}.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]" | ||
| 2379 | ); | 2700 | ); |
| 2380 | } | 2701 | } |
| 2381 | 2702 | ||
| @@ -2387,6 +2708,10 @@ · 5 unmodified lines | |||
| 2387 | return typeof what === "function"; | 2708 | return typeof what === "function"; |
| 2388 | } | 2709 | } |
| 2389 | 2710 | ||
| 2711 | function isPlainObject(what) { | ||
| 2712 | return Object.prototype.toString.call(what) === "[object Object]"; | ||
| 2713 | } | ||
| 2714 | |||
| 2390 | function isString(what) { | 2715 | function isString(what) { |
| 2391 | return Object.prototype.toString.call(what) === "[object String]"; | 2716 | return Object.prototype.toString.call(what) === "[object String]"; |
| 2392 | } | 2717 | } |
| @@ -2396,6 +2721,8 @@ · 3 unmodified lines | |||
| 2396 | } | 2721 | } |
| 2397 | 2722 | ||
| 2398 | function isEmptyObject(what) { | 2723 | function isEmptyObject(what) { |
| 2724 | if (!isPlainObject(what)) return false; | ||
| 2725 | |||
| 2399 | for (var _ in what) { | 2726 | for (var _ in what) { |
| 2400 | if (what.hasOwnProperty(_)) { | 2727 | if (what.hasOwnProperty(_)) { |
| 2401 | return false; | 2728 | return false; |
| @@ -2413,6 +2740,59 @@ · 11 unmodified lines | |||
| 2413 | } | 2740 | } |
| 2414 | } | 2741 | } |
| 2415 | 2742 | ||
| 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 | |||
| 2416 | function wrappedCallback(callback) { | 2796 | function wrappedCallback(callback) { |
| 2417 | function dataCallback(data, original) { | 2797 | function dataCallback(data, original) { |
| 2418 | var normalizedData = callback(data) || data; | 2798 | var normalizedData = callback(data) || data; |
| @@ -2470,9 +2850,15 @@ · 51 unmodified lines | |||
| 2470 | } | 2850 | } |
| 2471 | 2851 | ||
| 2472 | function truncate(str, max) { | 2852 | function truncate(str, max) { |
| 2473 | return !max || str.length <= max | 2853 | if (typeof max !== "number") { |
| 2474 | ? str | 2854 | throw new Error( |
| 2475 | : str.substr(0, max) + "\u2026"; | 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"; | ||
| 2476 | } | 2862 | } |
| 2477 | 2863 | ||
| 2478 | /** | 2864 | /** |
| @@ -2521,14 +2907,14 @@ · 42 unmodified lines | |||
| 2521 | return pairs.join("&"); | 2907 | return pairs.join("&"); |
| 2522 | } | 2908 | } |
| 2523 | 2909 | ||
| 2524 | // borrowed from https://datatracker.ietf.org/doc/html/rfc3986#appendix-B | 2910 | // borrowed from https://tools.ietf.org/html/rfc3986#appendix-B |
| 2525 | // intentionally using regex and not <a/> href parsing trick because React Native and other | 2911 | // intentionally using regex and not <a/> href parsing trick because React Native and other |
| 2526 | // environments where DOM might not be available | 2912 | // environments where DOM might not be available |
| 2527 | function parseUrl(url) { | 2913 | function parseUrl(url) { |
| 2914 | if (typeof url !== "string") return {}; | ||
| 2528 | var match = url.match( | 2915 | var match = url.match( |
| 2529 | /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/, | 2916 | /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/, |
| 2530 | ); | 2917 | ); |
| 2531 | if (!match) return {}; | ||
| 2532 | 2918 | ||
| 2533 | // coerce to undefined values to empty string so we don't get 'undefined' | 2919 | // coerce to undefined values to empty string so we don't get 'undefined' |
| 2534 | var query = match[6] || ""; | 2920 | var query = match[6] || ""; |
| @@ -2675,6 +3061,13 @@ · 140 unmodified lines | |||
| 2675 | return !!(!!a ^ !!b); | 3061 | return !!(!!a ^ !!b); |
| 2676 | } | 3062 | } |
| 2677 | 3063 | ||
| 3064 | /** | ||
| 3065 | * Returns true if both parameters are undefined | ||
| 3066 | */ | ||
| 3067 | function isBothUndefined(a, b) { | ||
| 3068 | return isUndefined(a) && isUndefined(b); | ||
| 3069 | } | ||
| 3070 | |||
| 2678 | /** | 3071 | /** |
| 2679 | * Returns true if the two input exception interfaces have the same content | 3072 | * Returns true if the two input exception interfaces have the same content |
| 2680 | */ | 3073 | */ |
| @@ -2687,6 +3080,9 @@ · 6 unmodified lines | |||
| 2687 | if (ex1.type !== ex2.type || ex1.value !== ex2.value) | 3080 | if (ex1.type !== ex2.type || ex1.value !== ex2.value) |
| 2688 | return false; | 3081 | return false; |
| 2689 | 3082 | ||
| 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 | |||
| 2690 | return isSameStacktrace(ex1.stacktrace, ex2.stacktrace); | 3086 | return isSameStacktrace(ex1.stacktrace, ex2.stacktrace); |
| 2691 | } | 3087 | } |
| 2692 | 3088 | ||
| @@ -2726,6 +3122,7 @@ · 33 unmodified lines | |||
| 2726 | * @param track {optional} record instrumentation to an array | 3122 | * @param track {optional} record instrumentation to an array |
| 2727 | */ | 3123 | */ |
| 2728 | function fill(obj, name, replacement, track) { | 3124 | function fill(obj, name, replacement, track) { |
| 3125 | if (obj == null) return; | ||
| 2729 | var orig = obj[name]; | 3126 | var orig = obj[name]; |
| 2730 | obj[name] = replacement(orig); | 3127 | obj[name] = replacement(orig); |
| 2731 | obj[name].__raven__ = true; | 3128 | obj[name].__raven__ = true; |
| @@ -2735,16 +3132,190 @@ · 3 unmodified lines | |||
| 2735 | } | 3132 | } |
| 2736 | } | 3133 | } |
| 2737 | 3134 | ||
| 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 | |||
| 2738 | module.exports = { | 3301 | module.exports = { |
| 2739 | isObject: isObject, | 3302 | isObject: isObject, |
| 2740 | isError: isError, | 3303 | isError: isError, |
| 2741 | isErrorEvent: isErrorEvent, | 3304 | isErrorEvent: isErrorEvent, |
| 3305 | isDOMError: isDOMError, | ||
| 3306 | isDOMException: isDOMException, | ||
| 2742 | isUndefined: isUndefined, | 3307 | isUndefined: isUndefined, |
| 2743 | isFunction: isFunction, | 3308 | isFunction: isFunction, |
| 3309 | isPlainObject: isPlainObject, | ||
| 2744 | isString: isString, | 3310 | isString: isString, |
| 2745 | isArray: isArray, | 3311 | isArray: isArray, |
| 2746 | isEmptyObject: isEmptyObject, | 3312 | isEmptyObject: isEmptyObject, |
| 2747 | supportsErrorEvent: supportsErrorEvent, | 3313 | supportsErrorEvent: supportsErrorEvent, |
| 3314 | supportsDOMError: supportsDOMError, | ||
| 3315 | supportsDOMException: supportsDOMException, | ||
| 3316 | supportsFetch: supportsFetch, | ||
| 3317 | supportsReferrerPolicy: supportsReferrerPolicy, | ||
| 3318 | supportsPromiseRejectionEvent: supportsPromiseRejectionEvent, | ||
| 2748 | wrappedCallback: wrappedCallback, | 3319 | wrappedCallback: wrappedCallback, |
| 2749 | each: each, | 3320 | each: each, |
| 2750 | objectMerge: objectMerge, | 3321 | objectMerge: objectMerge, |
| @@ -2760,6 +3331,10 @@ · 9 unmodified lines | |||
| 2760 | isSameStacktrace: isSameStacktrace, | 3331 | isSameStacktrace: isSameStacktrace, |
| 2761 | parseUrl: parseUrl, | 3332 | parseUrl: parseUrl, |
| 2762 | fill: fill, | 3333 | fill: fill, |
| 3334 | safeJoin: safeJoin, | ||
| 3335 | serializeException: serializeException, | ||
| 3336 | serializeKeysForMessage: serializeKeysForMessage, | ||
| 3337 | sanitize: sanitize, | ||
| 2763 | }; | 3338 | }; |
| 2764 | }).call( | 3339 | }).call( |
| 2765 | this, | 3340 | this, |
| @@ -2772,7 +3347,7 @@ · 6 unmodified lines | |||
| 2772 | : {}, | 3347 | : {}, |
| 2773 | ); | 3348 | ); |
| 2774 | }, | 3349 | }, |
| 2775 | {}, | 3350 | { 7: 7 }, |
| 2776 | ], | 3351 | ], |
| 2777 | 6: [ | 3352 | 6: [ |
| 2778 | function (_dereq_, module, exports) { | 3353 | function (_dereq_, module, exports) { |
| @@ -2780,14 +3355,14 @@ · 1 unmodified line | |||
| 2780 | var utils = _dereq_(5); | 3355 | var utils = _dereq_(5); |
| 2781 | 3356 | ||
| 2782 | /* | 3357 | /* |
| 2783 | TraceKit - Cross brower stack traces | 3358 | TraceKit - Cross brower stack traces |
| 2784 | 3359 | ||
| 2785 | This was originally forked from github.com/occ/TraceKit, but has since been | 3360 | 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 | 3361 | largely re-written and is now maintained as part of raven-js. Tests for |
| 2787 | this are in test/vendor. | 3362 | this are in test/vendor. |
| 2788 | 3363 | ||
| 2789 | MIT license | 3364 | MIT license |
| 2790 | */ | 3365 | */ |
| 2791 | 3366 | ||
| 2792 | var TraceKit = { | 3367 | var TraceKit = { |
| 2793 | collectWindowErrors: true, | 3368 | collectWindowErrors: true, |
| @@ -2815,10 +3390,25 @@ · 21 unmodified lines | |||
| 2815 | function getLocationHref() { | 3390 | function getLocationHref() { |
| 2816 | if (typeof document === "undefined" || document.location == null) | 3391 | if (typeof document === "undefined" || document.location == null) |
| 2817 | return ""; | 3392 | return ""; |
| 2818 | |||
| 2819 | return document.location.href; | 3393 | return document.location.href; |
| 2820 | } | 3394 | } |
| 2821 | 3395 | ||
| 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 | |||
| 2822 | /** | 3412 | /** |
| 2823 | * TraceKit.report: cross-browser processing of unhandled exceptions | 3413 | * TraceKit.report: cross-browser processing of unhandled exceptions |
| 2824 | * | 3414 | * |
| @@ -2925,7 +3515,7 @@ · 100 unmodified lines | |||
| 2925 | /** | 3515 | /** |
| 2926 | * Ensures all global unhandled exceptions are recorded. | 3516 | * Ensures all global unhandled exceptions are recorded. |
| 2927 | * Supported by Gecko and IE. | 3517 | * Supported by Gecko and IE. |
| 2928 | * @param {string} message Error message. | 3518 | * @param {string} msg Error message. |
| 2929 | * @param {string} url URL of script that generated the exception. | 3519 | * @param {string} url URL of script that generated the exception. |
| 2930 | * @param {(number|string)} lineNo The line number at which the error | 3520 | * @param {(number|string)} lineNo The line number at which the error |
| 2931 | * occurred. | 3521 | * occurred. |
| @@ -2933,8 +3523,12 @@ · 1 unmodified line | |||
| 2933 | * occurred. | 3523 | * occurred. |
| 2934 | * @param {?Error} ex The actual Error object. | 3524 | * @param {?Error} ex The actual Error object. |
| 2935 | */ | 3525 | */ |
| 2936 | function traceKitWindowOnError(message, url, lineNo, colNo, ex) { | 3526 | function traceKitWindowOnError(msg, url, lineNo, colNo, ex) { |
| 2937 | var stack = null; | 3527 | 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; | ||
| 2938 | 3532 | ||
| 2939 | if (lastExceptionStack) { | 3533 | if (lastExceptionStack) { |
| 2940 | TraceKit.computeStackTrace.augmentStackTraceWithInitialElement( | 3534 | TraceKit.computeStackTrace.augmentStackTraceWithInitialElement( |
| @@ -2944,13 +3538,13 @@ · 3 unmodified lines | |||
| 2944 | message, | 3538 | message, |
| 2945 | ); | 3539 | ); |
| 2946 | processLastException(); | 3540 | processLastException(); |
| 2947 | } else if (ex && utils.isError(ex)) { | 3541 | } else if (exception && utils.isError(exception)) { |
| 2948 | // non-string `ex` arg; attempt to extract stack trace | 3542 | // non-string `exception` arg; attempt to extract stack trace |
| 2949 | 3543 | ||
| 2950 | // New chrome and blink send along a real error object | 3544 | // New chrome and blink send along a real error object |
| 2951 | // Let's just report that like a normal error. | 3545 | // Let's just report that like a normal error. |
| 2952 | // See: https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror | 3546 | // See: https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror |
| 2953 | stack = TraceKit.computeStackTrace(ex); | 3547 | stack = TraceKit.computeStackTrace(exception); |
| 2954 | notifyHandlers(stack, true); | 3548 | notifyHandlers(stack, true); |
| 2955 | } else { | 3549 | } else { |
| 2956 | var location = { | 3550 | var location = { |
| @@ -2960,13 +3554,13 @@ · 3 unmodified lines | |||
| 2960 | }; | 3554 | }; |
| 2961 | 3555 | ||
| 2962 | var name = undefined; | 3556 | var name = undefined; |
| 2963 | var msg = message; // must be new var or will modify original `arguments` | ||
| 2964 | var groups; | 3557 | var groups; |
| 3558 | |||
| 2965 | if ({}.toString.call(message) === "[object String]") { | 3559 | if ({}.toString.call(message) === "[object String]") { |
| 2966 | var groups = message.match(ERROR_TYPES_RE); | 3560 | var groups = message.match(ERROR_TYPES_RE); |
| 2967 | if (groups) { | 3561 | if (groups) { |
| 2968 | name = groups[1]; | 3562 | name = groups[1]; |
| 2969 | msg = groups[2]; | 3563 | message = groups[2]; |
| 2970 | } | 3564 | } |
| 2971 | } | 3565 | } |
| 2972 | 3566 | ||
| @@ -2974,7 +3568,7 @@ · 1 unmodified line | |||
| 2974 | 3568 | ||
| 2975 | stack = { | 3569 | stack = { |
| 2976 | name: name, | 3570 | name: name, |
| 2977 | message: msg, | 3571 | message: message, |
| 2978 | url: getLocationHref(), | 3572 | url: getLocationHref(), |
| 2979 | stack: [location], | 3573 | stack: [location], |
| 2980 | }; | 3574 | }; |
| @@ -3163,20 +3757,22 @@ · 182 unmodified lines | |||
| 3163 | if (typeof ex.stack === "undefined" || !ex.stack) return; | 3757 | if (typeof ex.stack === "undefined" || !ex.stack) return; |
| 3164 | 3758 | ||
| 3165 | var chrome = | 3759 | var chrome = |
| 3166 | /^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i, | 3760 | /^\s*at (?:(.*?) ?\()?((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i; |
| 3167 | gecko = | 3761 | var winjs = |
| 3168 | /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i, | 3762 | /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i; |
| 3169 | winjs = | 3763 | // NOTE: blob urls are now supposed to always have an origin, therefore it's format |
| 3170 | /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i, | 3764 | // which is `blob:http://url/path/with-some-uuid`, is matched by `blob.*?:\/` as well |
| 3171 | // Used to additionally parse URL/line/column from eval frames | 3765 | var gecko = |
| 3172 | geckoEval = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i, | 3766 | /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|moz-extension).*?:\/.*?|\[native code\]|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i; |
| 3173 | chromeEval = /\((\S*)(?::(\d+))(?::(\d+))\)/, | 3767 | // Used to additionally parse URL/line/column from eval frames |
| 3174 | lines = ex.stack.split("\n"), | 3768 | var geckoEval = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i; |
| 3175 | stack = [], | 3769 | var chromeEval = /\((\S*)(?::(\d+))(?::(\d+))\)/; |
| 3176 | submatch, | 3770 | var lines = ex.stack.split("\n"); |
| 3177 | parts, | 3771 | var stack = []; |
| 3178 | element, | 3772 | var submatch; |
| 3179 | reference = /^(.*) is undefined$/.exec(ex.message); | 3773 | var parts; |
| 3774 | var element; | ||
| 3775 | var reference = /^(.*) is undefined$/.exec(ex.message); | ||
| 3180 | 3776 | ||
| 3181 | for (var i = 0, j = lines.length; i < j; ++i) { | 3777 | for (var i = 0, j = lines.length; i < j; ++i) { |
| 3182 | if ((parts = chrome.exec(lines[i]))) { | 3778 | if ((parts = chrome.exec(lines[i]))) { |
| @@ -3236,6 +3832,47 @@ · 53 unmodified lines | |||
| 3236 | element.func = UNKNOWN_FUNCTION; | 3832 | element.func = UNKNOWN_FUNCTION; |
| 3237 | } | 3833 | } |
| 3238 | 3834 | ||
| 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 | |||
| 3239 | stack.push(element); | 3876 | stack.push(element); |
| 3240 | } | 3877 | } |
| 3241 | 3878 | ||
| @@ -3449,15 +4086,15 @@ · 207 unmodified lines | |||
| 3449 | 7: [ | 4086 | 7: [ |
| 3450 | function (_dereq_, module, exports) { | 4087 | function (_dereq_, module, exports) { |
| 3451 | /* | 4088 | /* |
| 3452 | json-stringify-safe | 4089 | json-stringify-safe |
| 3453 | Like JSON.stringify, but doesn't throw on circular references. | 4090 | Like JSON.stringify, but doesn't throw on circular references. |
| 3454 | 4091 | ||
| 3455 | Originally forked from https://github.com/isaacs/json-stringify-safe | 4092 | 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 | 4093 | 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. | 4094 | and IE8 compatibility. Tests for this are in test/vendor. |
| 3458 | 4095 | ||
| 3459 | ISC license: https://github.com/isaacs/json-stringify-safe/blob/master/LICENSE | 4096 | ISC license: https://github.com/isaacs/json-stringify-safe/blob/master/LICENSE |
| 3460 | */ | 4097 | */ |
| 3461 | 4098 | ||
| 3462 | exports = module.exports = stringify; | 4099 | exports = module.exports = stringify; |
| 3463 | exports.getSerialize = serializer; | 4100 | exports.getSerialize = serializer; |
| @@ -3535,6 +4172,281 @@ · 71 unmodified lines | |||
| 3535 | }, | 4172 | }, |
| 3536 | {}, | 4173 | {}, |
| 3537 | ], | 4174 | ], |
| 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 | ], | ||
| 3538 | }, | 4450 | }, |
| 3539 | {}, | 4451 | {}, |
| 3540 | [4], | 4452 | [4], |