@@ -27,63 +27,69 @@ function extractLocation(urlLike: string) {
2727 return [ parts [ 1 ] , parts [ 2 ] || undefined , parts [ 3 ] || undefined ]
2828}
2929
30- export function parseStacktrace ( e : ErrorWithDiff , full = false ) : ParsedStack [ ] {
31- if ( ! e )
32- return [ ]
30+ // Based on https://github.com/stacktracejs/error-stack-parser
31+ // Credit to stacktracejs
32+ export function parseSingleStack ( raw : string ) : ParsedStack | null {
33+ let line = raw . trim ( )
3334
34- if ( e . stacks )
35- return e . stacks
35+ if ( line . includes ( '(eval ' ) )
36+ line = line . replace ( / e v a l c o d e / g , 'eval' ) . replace ( / ( \( e v a l a t [ ^ ( ) ] * ) | ( , . * $ ) / g , '' )
3637
37- const stackStr = e . stack || e . stackStr || ''
38- const stackFrames = stackStr
39- . split ( '\n' )
40- // Based on https://github.com/stacktracejs/error-stack-parser
41- // Credit to stacktracejs
42- . map ( ( raw ) : ParsedStack | null => {
43- let line = raw . trim ( )
38+ let sanitizedLine = line
39+ . replace ( / ^ \s + / , '' )
40+ . replace ( / \( e v a l c o d e / g, '(' )
41+ . replace ( / ^ .* ?\s + / , '' )
4442
45- if ( line . includes ( '(eval ' ) )
46- line = line . replace ( / e v a l c o d e / g, 'eval' ) . replace ( / ( \( e v a l a t [ ^ ( ) ] * ) | ( , .* $ ) / g, '' )
43+ // capture and preserve the parenthesized location "(/foo/my bar.js:12:87)" in
44+ // case it has spaces in it, as the string is split on \s+ later on
45+ const location = sanitizedLine . match ( / ( \( .+ \) $ ) / )
4746
48- let sanitizedLine = line
49- . replace ( / ^ \s + / , '' )
50- . replace ( / \( e v a l c o d e / g, '(' )
51- . replace ( / ^ .* ?\s + / , '' )
47+ // remove the parenthesized location from the line, if it was matched
48+ sanitizedLine = location ? sanitizedLine . replace ( location [ 0 ] , '' ) : sanitizedLine
5249
53- // capture and preserve the parenthesized location "(/foo/my bar.js:12:87)" in
54- // case it has spaces in it, as the string is split on \s+ later on
55- const location = sanitizedLine . match ( / ( \( .+ \) $ ) / )
50+ // if a location was matched, pass it to extractLocation() otherwise pass all sanitizedLine
51+ // because this line doesn't have function name
52+ const [ url , lineNumber , columnNumber ] = extractLocation ( location ? location [ 1 ] : sanitizedLine )
53+ let method = ( location && sanitizedLine ) || ''
54+ let file = url && [ 'eval' , '<anonymous>' ] . includes ( url ) ? undefined : url
5655
57- // remove the parenthesized location from the line, if it was matched
58- sanitizedLine = location ? sanitizedLine . replace ( location [ 0 ] , '' ) : sanitizedLine
56+ if ( ! file || ! lineNumber || ! columnNumber )
57+ return null
5958
60- // if a location was matched, pass it to extractLocation() otherwise pass all sanitizedLine
61- // because this line doesn't have function name
62- const [ url , lineNumber , columnNumber ] = extractLocation ( location ? location [ 1 ] : sanitizedLine )
63- let method = ( location && sanitizedLine ) || ''
64- let file = url && [ 'eval' , '<anonymous>' ] . includes ( url ) ? undefined : url
59+ if ( method . startsWith ( 'async ' ) )
60+ method = method . slice ( 6 )
6561
66- if ( ! file || ! lineNumber || ! columnNumber )
67- return null
62+ if ( file . startsWith ( 'file://' ) )
63+ file = file . slice ( 7 )
6864
69- if ( method . startsWith ( 'async ' ) )
70- method = method . slice ( 6 )
65+ // normalize Windows path (\ -> / )
66+ file = resolve ( file )
7167
72- if ( file . startsWith ( 'file://' ) )
73- file = file . slice ( 7 )
68+ return {
69+ method,
70+ file,
71+ line : parseInt ( lineNumber ) ,
72+ column : parseInt ( columnNumber ) ,
73+ }
74+ }
7475
75- // normalize Windows path (\ -> /)
76- file = resolve ( file )
76+ export function parseStacktrace ( e : ErrorWithDiff , full = false ) : ParsedStack [ ] {
77+ if ( ! e )
78+ return [ ]
79+
80+ if ( e . stacks )
81+ return e . stacks
82+
83+ const stackStr = e . stack || e . stackStr || ''
84+ const stackFrames = stackStr
85+ . split ( '\n' )
86+ . map ( ( raw ) : ParsedStack | null => {
87+ const stack = parseSingleStack ( raw )
7788
78- if ( ! full && stackIgnorePatterns . some ( p => file && file . includes ( p ) ) )
89+ if ( ! stack || ( ! full && stackIgnorePatterns . some ( p => stack . file . includes ( p ) ) ) )
7990 return null
8091
81- return {
82- method,
83- file,
84- line : parseInt ( lineNumber ) ,
85- column : parseInt ( columnNumber ) ,
86- }
92+ return stack
8793 } )
8894 . filter ( notNullish )
8995
0 commit comments