| 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 22 | // SOFTWARE. |
| 23 | function ErrorStackParser() { |
| 24 | let FIREFOX_SAFARI_STACK_REGEXP = /(^|@)\S+:\d+/; |
| 25 | let CHROME_IE_STACK_REGEXP = /^\s*at .*(\S+:\d+|\(native\))/m; |
| 26 | let SAFARI_NATIVE_CODE_REGEXP = /^(eval@)?(\[native code])?$/; |
| 27 | |
| 28 | return { |
| 29 | /** |
| 30 | * Given an Error object, extract the most information from it. |
| 31 | * @private |
| 32 | * @param {Error} error object |
| 33 | * @return {Array} of stack frames |
| 34 | */ |
| 35 | parse: function ErrorStackParser$$parse(error) { |
| 36 | if ( |
| 37 | typeof error.stacktrace !== 'undefined' || |
| 38 | typeof error['opera#sourceloc'] !== 'undefined' |
| 39 | ) { |
| 40 | return this.parseOpera(error); |
| 41 | } else if (error.stack && error.stack.match(CHROME_IE_STACK_REGEXP)) { |
| 42 | return this.parseV8OrIE(error); |
| 43 | } else if (error.stack) { |
| 44 | return this.parseFFOrSafari(error); |
| 45 | } else { |
| 46 | // throw new Error('Cannot parse given Error object'); |
| 47 | } |
| 48 | }, |
| 49 | |
| 50 | // Separate line and column numbers from a string of the form: (URI:Line:Column) |
| 51 | extractLocation: function ErrorStackParser$$extractLocation(urlLike) { |
| 52 | // Fail-fast but return locations like "(native)" |
| 53 | if (urlLike.indexOf(':') === -1) { |
| 54 | return [urlLike]; |
| 55 | } |
| 56 | |
| 57 | let regExp = /(.+?)(?::(\d+))?(?::(\d+))?$/; |
| 58 | let parts = regExp.exec(urlLike.replace(/[()]/g, '')); |
| 59 | return [parts[1], parts[2] || undefined, parts[3] || undefined]; |
| 60 | }, |
| 61 | |
| 62 | parseV8OrIE: function ErrorStackParser$$parseV8OrIE(error) { |
| 63 | let filtered = error.stack.split('\n').filter(function(line) { |
| 64 | return !!line.match(CHROME_IE_STACK_REGEXP); |
| 65 | }, this); |
| 66 | |
| 67 | return filtered.map(function(line) { |
| 68 | if (line.indexOf('(eval ') > -1) { |
| 69 | // Throw away eval information until we implement stacktrace.js/stackframe#8 |
| 70 | line = line |
| 71 | .replace(/eval code/g, 'eval') |
| 72 | .replace(/(\(eval at [^()]*)|(\),.*$)/g, ''); |
| 73 | } |
| 74 | let sanitizedLine = line |
| 75 | .replace(/^\s+/, '') |
| 76 | .replace(/\(eval code/g, '('); |
| 77 | |
| 78 | // capture and preseve the parenthesized location "(/foo/my bar.js:12:87)" in |
| 79 | // case it has spaces in it, as the string is split on \s+ later on |
| 80 | let location = sanitizedLine.match(/ (\((.+):(\d+):(\d+)\)$)/); |