1
+ import type { StackFrameLite } from 'error-stack-parser-es/lite'
1
2
import { parseStack } from 'error-stack-parser-es/lite'
2
3
import { getTrace } from 'trace-record'
3
- import type { MergedRecordRegexInfo , RecordRegexInfo , RegexCallsDurations , RegexDoctorDumpFiltersOptions , RegexDoctorDumpOptions , RegexInfo } from './types'
4
+ import type { MergedRecordRegexInfo , RecordRegexInfo , RegexCall , RegexCallsDurations , RegexDoctorDumpFiltersOptions , RegexDoctorDumpOptions , RegexDoctorResult , RegexInfo } from './types'
4
5
import { extractPackagePath , normalizeFilepath } from './shared/path'
6
+ import type { RegexDoctor } from './doctor'
5
7
6
8
const defaultFilters : Required < RegexDoctorDumpFiltersOptions > = {
7
9
top : 20 ,
@@ -13,11 +15,13 @@ const defaultFilters: Required<RegexDoctorDumpFiltersOptions> = {
13
15
}
14
16
15
17
export function dump (
16
- map : Map < RegExp , RecordRegexInfo > ,
18
+ doctor : RegexDoctor ,
17
19
options : RegexDoctorDumpOptions = { } ,
18
- ) {
20
+ ) : RegexDoctorResult {
21
+ const map = doctor . map
19
22
const {
20
23
limitCalls = 5 ,
24
+ limitInputLength = 500 ,
21
25
// stacktrace = true,
22
26
} = options
23
27
@@ -26,7 +30,7 @@ export function dump(
26
30
...defaultFilters ,
27
31
}
28
32
29
- let totalDuration = 0
33
+ let totalExecution = 0
30
34
const uniqueMap = new Map < string , MergedRecordRegexInfo > ( )
31
35
32
36
Array . from ( map . values ( ) )
@@ -60,7 +64,7 @@ export function dump(
60
64
let infos = Array . from ( uniqueMap . values ( ) )
61
65
infos . forEach ( ( info ) => {
62
66
info . durations = getDurations ( info )
63
- totalDuration += info . durations . sum
67
+ totalExecution += info . durations . sum
64
68
} )
65
69
infos . sort ( ( a , b ) => b . durations ! . sum - a . durations ! . sum )
66
70
@@ -85,20 +89,56 @@ export function dump(
85
89
. sort ( ( a , b ) => b . duration - a . duration )
86
90
87
91
const files = new Set < string > ( )
92
+ const traces = new Map < string , { idx : number , trace : StackFrameLite [ ] } > ( )
93
+
94
+ let infos = calls . map ( ( call ) : RegexCall => {
95
+ let traceIdx : number | undefined
96
+ if ( call . stack ) {
97
+ if ( traces . has ( call . stack ) ) {
98
+ traceIdx = traces . get ( call . stack ) ! . idx
99
+ }
100
+ else {
101
+ const trace = parseStacktrace ( call . stack )
102
+ if ( trace && trace [ 0 ] ) {
103
+ files . add ( `${ normalizeFilepath ( trace [ 0 ] . file ! ) } :${ trace [ 0 ] . line ! } :${ trace [ 0 ] . col ! } ` )
104
+ traceIdx = traces . size
105
+ traces . set ( call . stack , { idx : traceIdx , trace } )
106
+ }
107
+ }
108
+ }
88
109
89
- let infos = calls . map ( ( call ) => {
90
- // TODO: group by unique stacks
91
- const trace = call . stack
92
- ? parseStack ( call . stack , { slice : [ 1 , 10 ] } ) . filter ( frame => frame . file )
93
- : undefined
94
-
95
- if ( trace && trace [ 0 ] )
96
- files . add ( `${ normalizeFilepath ( trace [ 0 ] . file ! ) } :${ trace [ 0 ] . line ! } :${ trace [ 0 ] . col ! } ` )
97
-
110
+ let input : RegexCall [ 'input' ]
111
+ if ( call . input != null ) {
112
+ input = [ ]
113
+ if ( call . input . length <= limitInputLength ) {
114
+ input . push ( call . input )
115
+ }
116
+ else if ( call . index != null ) {
117
+ const index = Math . max ( 0 , Math . round ( call . index - limitInputLength * 0.3 ) )
118
+ if ( index > 0 )
119
+ input . push ( index )
120
+ const snippet = call . input . slice ( index , index + limitInputLength )
121
+ input . push ( snippet )
122
+ const rest = call . inputLength - index - snippet . length
123
+ if ( rest > 0 )
124
+ input . push ( rest )
125
+ }
126
+ else {
127
+ const snippet = call . input . slice ( 0 , limitInputLength )
128
+ input . push ( snippet )
129
+ const rest = call . inputLength - snippet . length
130
+ if ( rest > 0 )
131
+ input . push ( rest )
132
+ }
133
+ }
98
134
return {
99
135
duration : call . duration ,
100
136
inputLength : call . inputLength ,
101
- trace,
137
+ input,
138
+ trace : traceIdx ,
139
+ matched : call . matched ,
140
+ index : call . index ,
141
+ groups : call . groups ,
102
142
}
103
143
} )
104
144
@@ -124,6 +164,9 @@ export function dump(
124
164
copies : info . copies ,
125
165
calls : info . calls . length ,
126
166
callsInfos : infos ,
167
+ traces : Array . from ( traces . values ( ) )
168
+ . sort ( ( a , b ) => a . idx - b . idx )
169
+ . map ( ( { trace } ) => trace ) ,
127
170
durations : info . durations || getDurations ( info ) ,
128
171
filesCalled,
129
172
filesCreated : info . filesCreated ,
@@ -135,7 +178,8 @@ export function dump(
135
178
return {
136
179
count : map . size ,
137
180
countUnique : uniqueMap . size ,
138
- totalDuration,
181
+ totalDuration : doctor . duration ,
182
+ totalExecution,
139
183
regexInfos : infos . map ( ( info , idx ) => dumpInfo ( info , idx ) ) ,
140
184
cwd : options . cwd ,
141
185
}
@@ -161,3 +205,17 @@ function getDurations(info: RecordRegexInfo): RegexCallsDurations {
161
205
max,
162
206
}
163
207
}
208
+
209
+ const traceCache : Map < string , StackFrameLite [ ] | undefined > = new Map ( )
210
+
211
+ function parseStacktrace ( string ?: string ) {
212
+ if ( ! string )
213
+ return
214
+ if ( traceCache . has ( string ) )
215
+ return traceCache . get ( string )
216
+ const trace = string
217
+ ? parseStack ( string , { slice : [ 1 , 10 ] } ) . filter ( frame => frame . file )
218
+ : undefined
219
+ traceCache . set ( string , trace )
220
+ return trace
221
+ }
0 commit comments