demo/dist/demo.js
function computeStackTraceFromStackProp(ex) {
	    if (typeof ex.stack === 'undefined' || !ex.stack) return;
	    var chrome = /^\s*at (?:(.*?) ?\()?((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
	    var winjs = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i; // NOTE: blob urls are now supposed to always have an origin, therefore it's format
	    // which is `blob:http://url/path/with-some-uuid`, is matched by `blob.*?:\/` as well

	    var gecko = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|moz-extension).*?:\/.*?|\[native code\]|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i; // Used to additionally parse URL/line/column from eval frames

	    var geckoEval = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
	    var chromeEval = /\((\S*)(?::(\d+))(?::(\d+))\)/;
	    var lines = ex.stack.split('\n');
	    var stack = [];
	    var submatch;
	    var parts;
	    var element;
	    var reference = /^(.*) is undefined$/.exec(ex.message);

	    for (var i = 0, j = lines.length; i < j; ++i) {
	      if (parts = chrome.exec(lines[i])) {
	        var isNative = parts[2] && parts[2].indexOf('native') === 0; // start of line

	        var isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line

	        if (isEval && (submatch = chromeEval.exec(parts[2]))) {
	          // throw out eval line/column and use top-most line/column number
	          parts[2] = submatch[1]; // url

	          parts[3] = submatch[2]; // line

	          parts[4] = submatch[3]; // column
	        }

	        element = {
	          url: !isNative ? parts[2] : null,
	          func: parts[1] || UNKNOWN_FUNCTION,
	          args: isNative ? [parts[2]] : [],
	          line: parts[3] ? +parts[3] : null,
	          column: parts[4] ? +parts[4] : null
	        };
	      } else if (parts = winjs.exec(lines[i])) {
	        element = {
	          url: parts[2],
	          func: parts[1] || UNKNOWN_FUNCTION,
	          args: [],
	          line: +parts[3],
	          column: parts[4] ? +parts[4] : null
	        };
	      } else if (parts = gecko.exec(lines[i])) {
	        var isEval = parts[3] && parts[3].indexOf(' > eval') > -1;

	        if (isEval && (submatch = geckoEval.exec(parts[3]))) {
	          // throw out eval line/column and use top-most line number
	          parts[3] = submatch[1];
	          parts[4] = submatch[2];
	          parts[5] = null; // no column when eval
	        } else if (i === 0 && !parts[5] && typeof ex.columnNumber !== 'undefined') {
	          // FireFox uses this awesome columnNumber property for its top frame
	          // Also note, Firefox's column number is 0-based and everything else expects 1-based,
	          // so adding 1
	          // NOTE: this hack doesn't work if top-most frame is eval
	          stack[0].column = ex.columnNumber + 1;
	        }

	        element = {
	          url: parts[3],
	          func: parts[1] || UNKNOWN_FUNCTION,
	          args: parts[2] ? parts[2].split(',') : [],
	          line: parts[4] ? +parts[4] : null,
	          column: parts[5] ? +parts[5] : null
	        };
	      } else {
	        continue;
	      }

	      if (!element.func && element.line) {
	        element.func = UNKNOWN_FUNCTION;
	      }

	      if (element.url && element.url.substr(0, 5) === 'blob:') {
	        // Special case for handling JavaScript loaded into a blob.
	        // We use a synchronous AJAX request here as a blob is already in
	        // memory - it's not making a network request.  This will generate a warning
	        // in the browser console, but there has already been an error so that's not
	        // that much of an issue.
	        var xhr = new XMLHttpRequest();
	        xhr.open('GET', element.url, false);
	        xhr.send(null); // If we failed to download the source, skip this patch

	        if (xhr.status === 200) {
	          var source = xhr.responseText || ''; // We trim the source down to the last 300 characters as sourceMappingURL is always at the end of the file.
	          // Why 300? To be in line with: https://github.com/getsentry/sentry/blob/4af29e8f2350e20c28a6933354e4f42437b4ba42/src/sentry/lang/javascript/processor.py#L164-L175

	          source = source.slice(-300); // Now we dig out the source map URL

	          var sourceMaps = source.match(/\/\/# sourceMappingURL=(.*)$/); // If we don't find a source map comment or we find more than one, continue on to the next element.

	          if (sourceMaps) {
	            var sourceMapAddress = sourceMaps[1]; // Now we check to see if it's a relative URL.
	            // If it is, convert it to an absolute one.

	            if (sourceMapAddress.charAt(0) === '~') {
	              sourceMapAddress = getLocationOrigin() + sourceMapAddress.slice(1);
	            } // Now we strip the '.map' off of the end of the URL and update the
	            // element so that Sentry can match the map to the blob.


	            element.url = sourceMapAddress.slice(0, -4);
	          }
	        }
	      }

	      stack.push(element);
	    }

	    if (!stack.length) {
	      return null;
	    }

	    return {
	      name: ex.name,
	      message: ex.message,
	      url: getLocationHref(),
	      stack: stack
	    };
	  }
function computeStackTraceFromStackProp(ex) {
	    if (typeof ex.stack === 'undefined' || !ex.stack) return;
	    var chrome = /^\s*at (?:(.*?) ?\()?((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
	    var winjs = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i; // NOTE: blob urls are now supposed to always have an origin, therefore it's format
	    // which is `blob:http://url/path/with-some-uuid`, is matched by `blob.*?:\/` as well

	    var gecko = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|moz-extension).*?:\/.*?|\[native code\]|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i; // Used to additionally parse URL/line/column from eval frames

	    var geckoEval = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
	    var chromeEval = /\((\S*)(?::(\d+))(?::(\d+))\)/;
	    var lines = ex.stack.split('\n');
	    var stack = [];
	    var submatch;
	    var parts;
	    var element;
	    var reference = /^(.*) is undefined$/.exec(ex.message);

	    for (var i = 0, j = lines.length; i < j; ++i) {
	      if (parts = chrome.exec(lines[i])) {
	        var isNative = parts[2] && parts[2].indexOf('native') === 0; // start of line

	        var isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line

	        if (isEval && (submatch = chromeEval.exec(parts[2]))) {
	          // throw out eval line/column and use top-most line/column number
	          parts[2] = submatch[1]; // url

	          parts[3] = submatch[2]; // line

	          parts[4] = submatch[3]; // column
	        }

	        element = {
	          url: !isNative ? parts[2] : null,
	          func: parts[1] || UNKNOWN_FUNCTION,
	          args: isNative ? [parts[2]] : [],
	          line: parts[3] ? +parts[3] : null,
	          column: parts[4] ? +parts[4] : null
	        };
	      } else if (parts = winjs.exec(lines[i])) {
	        element = {
	          url: parts[2],
	          func: parts[1] || UNKNOWN_FUNCTION,
	          args: [],
	          line: +parts[3],
	          column: parts[4] ? +parts[4] : null
	        };
	      } else if (parts = gecko.exec(lines[i])) {
	        var isEval = parts[3] && parts[3].indexOf(' > eval') > -1;

	        if (isEval && (submatch = geckoEval.exec(parts[3]))) {
	          // throw out eval line/column and use top-most line number
	          parts[3] = submatch[1];
	          parts[4] = submatch[2];
	          parts[5] = null; // no column when eval
	        } else if (i === 0 && !parts[5] && typeof ex.columnNumber !== 'undefined') {
	          // FireFox uses this awesome columnNumber property for its top frame
	          // Also note, Firefox's column number is 0-based and everything else expects 1-based,
	          // so adding 1
	          // NOTE: this hack doesn't work if top-most frame is eval
	          stack[0].column = ex.columnNumber + 1;
	        }

	        element = {
	          url: parts[3],
	          func: parts[1] || UNKNOWN_FUNCTION,
	          args: parts[2] ? parts[2].split(',') : [],
	          line: parts[4] ? +parts[4] : null,
	          column: parts[5] ? +parts[5] : null
	        };
	      } else {
	        continue;
	      }

	      if (!element.func && element.line) {
	        element.func = UNKNOWN_FUNCTION;
	      }

	      if (element.url && element.url.substr(0, 5) === 'blob:') {
	        // Special case for handling JavaScript loaded into a blob.
	        // We use a synchronous AJAX request here as a blob is already in
	        // memory - it's not making a network request.  This will generate a warning
	        // in the browser console, but there has already been an error so that's not
	        // that much of an issue.
	        var xhr = new XMLHttpRequest();
	        xhr.open('GET', element.url, false);
	        xhr.send(null); // If we failed to download the source, skip this patch

	        if (xhr.status === 200) {
	          var source = xhr.responseText || ''; // We trim the source down to the last 300 characters as sourceMappingURL is always at the end of the file.
	          // Why 300? To be in line with: https://github.com/getsentry/sentry/blob/4af29e8f2350e20c28a6933354e4f42437b4ba42/src/sentry/lang/javascript/processor.py#L164-L175

	          source = source.slice(-300); // Now we dig out the source map URL

	          var sourceMaps = source.match(/\/\/# sourceMappingURL=(.*)$/); // If we don't find a source map comment or we find more than one, continue on to the next element.

	          if (sourceMaps) {
	            var sourceMapAddress = sourceMaps[1]; // Now we check to see if it's a relative URL.
	            // If it is, convert it to an absolute one.

	            if (sourceMapAddress.charAt(0) === '~') {
	              sourceMapAddress = getLocationOrigin() + sourceMapAddress.slice(1);
	            } // Now we strip the '.map' off of the end of the URL and update the
	            // element so that Sentry can match the map to the blob.


	            element.url = sourceMapAddress.slice(0, -4);
	          }
	        }
	      }

	      stack.push(element);
	    }

	    if (!stack.length) {
	      return null;
	    }

	    return {
	      name: ex.name,
	      message: ex.message,
	      url: getLocationHref(),
	      stack: stack
	    };
	  }
function computeStackTraceFromStackProp ( ex ) { if ( typeof ex . stack === 'undefined' || ! ex . stack ) return ; var chrome = / ^\s*at (?:(.*?) ?\()?((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$ / i ; var winjs = / ^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$ / i ; // NOTE: blob urls are now supposed to always have an origin, therefore it's format // which is `blob:http://url/path/with-some-uuid`, is matched by `blob.*?:\/` as well var gecko = / ^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|moz-extension).*?:\/.*?|\[native code\]|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$ / i ; // Used to additionally parse URL/line/column from eval frames var geckoEval = / (\S+) line (\d+)(?: > eval line \d+)* > eval / i ; var chromeEval = / \((\S*)(?::(\d+))(?::(\d+))\) / ; var lines = ex . stack . split ( '\n' ) ; var stack = [ ] ; var submatch ; var parts ; var element ; var reference = / ^(.*) is undefined$ / . exec ( ex . message ) ; for ( var i = 0 , j = lines . length ; i < j ; ++ i ) { if ( parts = chrome . exec ( lines [ i ] ) ) { var isNative = parts [ 2 ] && parts [ 2 ] . indexOf ( 'native' ) === 0 ; // start of line var isEval = parts [ 2 ] && parts [ 2 ] . indexOf ( 'eval' ) === 0 ; // start of line if ( isEval && ( submatch = chromeEval . exec ( parts [ 2 ] ) ) ) { // throw out eval line/column and use top-most line/column number parts [ 2 ] = submatch [ 1 ] ; // url parts [ 3 ] = submatch [ 2 ] ; // line parts [ 4 ] = submatch [ 3 ] ; // column } element = { url : ! isNative ? parts [ 2 ] : null , func : parts [ 1 ] || UNKNOWN_FUNCTION , args : isNative ? [ parts [ 2 ] ] : [ ] , line : parts [ 3 ] ? + parts [ 3 ] : null , column : parts [ 4 ] ? + parts [ 4 ] : null } ; } else if ( parts = winjs . exec ( lines [ i ] ) ) { element = { url : parts [ 2 ] , func : parts [ 1 ] || UNKNOWN_FUNCTION , args : [ ] , line : + parts [ 3 ] , column : parts [ 4 ] ? + parts [ 4 ] : null } ; } else if ( parts = gecko . exec ( lines [ i ] ) ) { var isEval = parts [ 3 ] && parts [ 3 ] . indexOf ( ' > eval' ) > - 1 ; if ( isEval && ( submatch = geckoEval . exec ( parts [ 3 ] ) ) ) { // throw out eval line/column and use top-most line number parts [ 3 ] = submatch [ 1 ] ; parts [ 4 ] = submatch [ 2 ] ; parts [ 5 ] = null ; // no column when eval } else if ( i === 0 && ! parts [ 5 ] && typeof ex . columnNumber !== 'undefined' ) { // FireFox uses this awesome columnNumber property for its top frame // Also note, Firefox's column number is 0-based and everything else expects 1-based, // so adding 1 // NOTE: this hack doesn't work if top-most frame is eval stack [ 0 ] . column = ex . columnNumber + 1 ; } element = { url : parts [ 3 ] , func : parts [ 1 ] || UNKNOWN_FUNCTION , args : parts [ 2 ] ? parts [ 2 ] . split ( ',' ) : [ ] , line : parts [ 4 ] ? + parts [ 4 ] : null , column : parts [ 5 ] ? + parts [ 5 ] : null } ; } else { continue ; } if ( ! element . func && element . line ) { element . func = UNKNOWN_FUNCTION ; } if ( element . url && element . url . substr ( 0 , 5 ) === 'blob:' ) { // Special case for handling JavaScript loaded into a blob. // We use a synchronous AJAX request here as a blob is already in // memory - it's not making a network request.  This will generate a warning // in the browser console, but there has already been an error so that's not // that much of an issue. var xhr = new XMLHttpRequest ( ) ; xhr . open ( 'GET' , element . url , false ) ; xhr . send ( null ) ; // If we failed to download the source, skip this patch if ( xhr . status === 200 ) { var source = xhr . responseText || '' ; // We trim the source down to the last 300 characters as sourceMappingURL is always at the end of the file. // Why 300? To be in line with: https://github.com/getsentry/sentry/blob/4af29e8f2350e20c28a6933354e4f42437b4ba42/src/sentry/lang/javascript/processor.py#L164-L175 source = source . slice ( - 300 ) ; // Now we dig out the source map URL var sourceMaps = source . match ( / \/\/# sourceMappingURL=(.*)$ / ) ; // If we don't find a source map comment or we find more than one, continue on to the next element. if ( sourceMaps ) { var sourceMapAddress = sourceMaps [ 1 ] ; // Now we check to see if it's a relative URL. // If it is, convert it to an absolute one. if ( sourceMapAddress . charAt ( 0 ) === '~' ) { sourceMapAddress = getLocationOrigin ( ) + sourceMapAddress . slice ( 1 ) ; } // Now we strip the '.map' off of the end of the URL and update the // element so that Sentry can match the map to the blob. element . url = sourceMapAddress . slice ( 0 , - 4 ) ; } } } stack . push ( element ) ; } if ( ! stack . length ) { return null ; } return { name : ex . name , message : ex . message , url : getLocationHref ( ) , stack : stack } ; }
Contents of Exception in various browsers.  SAFARI: ex.message = Can't find variable: qq ex.line = 59 ex.sourceId = 580238192 ex.sourceURL = http://... ex.expressionBeginOffset = 96 ex.expressionCaretOffset = 98 ex.expressionEndOffset = 98 ex.name = ReferenceError  FIREFOX: ex.message = qq is not defined ex.fileName = http://... ex.lineNumber = 59 ex.columnNumber = 69 ex.stack = ...stack trace... (see the example below) ex.name = ReferenceError  CHROME: ex.message = qq is not defined ex.name = ReferenceError ex.type = not_defined ex.arguments = ['aa'] ex.stack = ...stack trace...  INTERNET EXPLORER: ex.message = ... ex.name = ReferenceError  OPERA: ex.message = ...message... (see the example below) ex.name = ReferenceError ex.opera#sourceloc = 11  (pretty much useless, duplicates the info in ex.message) ex.stacktrace = n/a; see 'opera:config#UserPrefs|Exceptions Have Stacktrace' 
Computes stack trace information from the stack property.
Chrome and Gecko use this property.
@param {Error} ex
@return {?Object.<string, *>} Stack trace information.
Contents of Exception in various browsers . SAFARI : ex . message = Can t find variable : qq ex . line = 59 ex . sourceId = 580238192 ex . sourceURL = http : // ... ex . expressionBeginOffset = 96 ex . expressionCaretOffset = 98 ex . expressionEndOffset = 98 ex . name = ReferenceError FIREFOX : ex . message = qq is not defined ex . fileName = http : // ... ex . lineNumber = 59 ex . columnNumber = 69 ex . stack = ... stack trace ... ( see the example below ) ex . name = ReferenceError CHROME : ex . message = qq is not defined ex . name = ReferenceError ex . type = not_defined ex . arguments = [ aa ] ex . stack = ... stack trace ... INTERNET EXPLORER : ex . message = ... ex . name = ReferenceError OPERA : ex . message = ... message ... ( see the example below ) ex . name = ReferenceError ex . opera#sourceloc = 11 ( pretty much useless duplicates the info in ex . message ) ex . stacktrace = n / a ; see opera : config#UserPrefs|Exceptions Have Stacktrace Computes stack trace information from the stack property . Chrome and Gecko use this property .