1
1
/*@internal */
2
2
/** Tracing events for the compiler. */
3
3
namespace ts . tracing {
4
- type WriteFn = ( data : string ) => void ;
4
+ let fs : typeof import ( "fs" ) | false | undefined ;
5
5
6
- let write : WriteFn | undefined ;
6
+ let traceCount = 0 ;
7
+ let traceFd : number | undefined ;
7
8
8
- /** Enables (and resets) tracing events for the compiler. */
9
- export function startTracing ( w : WriteFn ) {
10
- write = w ;
11
- write ( `[\n` ) ;
9
+ let legendPath : string | undefined ;
10
+ const legend : TraceRecord [ ] = [ ] ;
11
+
12
+ /** Starts tracing for the given project (unless the `fs` module is unavailable). */
13
+ export function startTracing ( configFilePath : string | undefined , traceDir : string , isBuildMode : boolean ) {
14
+ Debug . assert ( ! traceFd , "Tracing already started" ) ;
15
+
16
+ if ( fs === undefined ) {
17
+ try {
18
+ fs = require ( "fs" ) ;
19
+ }
20
+ catch {
21
+ fs = false ;
22
+ }
23
+ }
24
+
25
+ if ( ! fs ) {
26
+ return ;
27
+ }
28
+
29
+ if ( legendPath === undefined ) {
30
+ legendPath = combinePaths ( traceDir , "legend.json" ) ;
31
+ }
32
+
33
+ // Note that writing will fail later on if it exists and is not a directory
34
+ if ( ! fs . existsSync ( traceDir ) ) {
35
+ fs . mkdirSync ( traceDir , { recursive : true } ) ;
36
+ }
37
+
38
+ const countPart = isBuildMode ? `.${ ++ traceCount } ` : `` ;
39
+ const tracePath = combinePaths ( traceDir , `trace${ countPart } .json` ) ;
40
+ const typesPath = combinePaths ( traceDir , `types${ countPart } .json` ) ;
41
+
42
+ legend . push ( {
43
+ configFilePath,
44
+ tracePath,
45
+ typesPath,
46
+ } ) ;
47
+
48
+ traceFd = fs . openSync ( tracePath , "w" ) ;
49
+ fs . writeSync ( traceFd , `[\n` ) ;
12
50
}
13
51
14
- /** Disables tracing events for the compiler. */
15
- export function stopTracing ( ) {
52
+ /** Stops tracing for the in-progress project and dumps the type catalog (unless the `fs` module is unavailable). */
53
+ export function stopTracing ( typeCatalog : readonly Type [ ] ) {
54
+ if ( ! traceFd ) {
55
+ Debug . assert ( ! fs , "Tracing is not in progress" ) ;
56
+ return ;
57
+ }
58
+
59
+ Debug . assert ( fs ) ;
60
+
16
61
// This both indicates that the trace is untruncated and conveniently
17
62
// ensures that the last array element won't have a trailing comma.
18
- write ?.( `{"pid":1,"tid":1,"ph":"i","ts":${ 1000 * timestamp ( ) } ,"name":"done","s":"g"}\n` ) ;
19
- write ?.( `]\n` ) ;
20
- write = undefined ;
63
+ fs . writeSync ( traceFd , `{"pid":1,"tid":1,"ph":"i","ts":${ 1000 * timestamp ( ) } ,"name":"done","s":"g"}\n` ) ;
64
+ fs . writeSync ( traceFd , `]\n` ) ;
65
+
66
+ fs . closeSync ( traceFd ) ;
67
+ traceFd = undefined ;
68
+
69
+ if ( typeCatalog ) {
70
+ dumpTypes ( typeCatalog ) ;
71
+ }
72
+ else {
73
+ // We pre-computed this path for convenience, but clear it
74
+ // now that the file won't be created.
75
+ legend [ legend . length - 1 ] . typesPath = undefined ;
76
+ }
21
77
}
22
78
23
79
export function isTracing ( ) {
24
- return ! ! write ;
80
+ return ! ! traceFd ;
25
81
}
26
82
27
83
export const enum Phase {
@@ -33,15 +89,25 @@ namespace ts.tracing {
33
89
}
34
90
35
91
export function begin ( phase : Phase , name : string , args : object ) {
92
+ if ( ! traceFd ) {
93
+ return ;
94
+ }
95
+ Debug . assert ( fs ) ;
96
+
36
97
performance . mark ( "beginTracing" ) ;
37
- write ?. ( `{"pid":1,"tid":1,"ph":"B","cat":"${ phase } ","ts":${ 1000 * timestamp ( ) } ,"name":"${ name } ","args":{ "ts": ${ JSON . stringify ( args ) } }},\n` ) ;
98
+ fs . writeSync ( traceFd , `{"pid":1,"tid":1,"ph":"B","cat":"${ phase } ","ts":${ 1000 * timestamp ( ) } ,"name":"${ name } ","args":{ "ts": ${ JSON . stringify ( args ) } }},\n` ) ;
38
99
performance . mark ( "endTracing" ) ;
39
100
performance . measure ( "Tracing" , "beginTracing" , "endTracing" ) ;
40
101
}
41
102
42
103
export function end ( ) {
104
+ if ( ! traceFd ) {
105
+ return ;
106
+ }
107
+ Debug . assert ( fs ) ;
108
+
43
109
performance . mark ( "beginTracing" ) ;
44
- write ?. ( `{"pid":1,"tid":1,"ph":"E","ts":${ 1000 * timestamp ( ) } },\n` ) ;
110
+ fs . writeSync ( traceFd , `{"pid":1,"tid":1,"ph":"E","ts":${ 1000 * timestamp ( ) } },\n` ) ;
45
111
performance . mark ( "endTracing" ) ;
46
112
performance . measure ( "Tracing" , "beginTracing" , "endTracing" ) ;
47
113
}
@@ -53,13 +119,18 @@ namespace ts.tracing {
53
119
} ;
54
120
}
55
121
56
- export function dumpTypes ( types : readonly Type [ ] , write : WriteFn ) {
122
+ function dumpTypes ( types : readonly Type [ ] ) {
123
+ Debug . assert ( fs ) ;
124
+
57
125
performance . mark ( "beginDumpTypes" ) ;
58
126
59
- const numTypes = types . length ;
127
+ const typesPath = legend [ legend . length - 1 ] . typesPath ! ;
128
+ const typesFd = fs . openSync ( typesPath , "w" ) ;
129
+
130
+ // Cleverness: no line break here so that the type ID will match the line number
131
+ fs . writeSync ( typesFd , "[" ) ;
60
132
61
- // Cleverness: no line break hear so that the type ID will match the line number
62
- write ( "[" ) ;
133
+ const numTypes = types . length ;
63
134
for ( let i = 0 ; i < numTypes ; i ++ ) {
64
135
const type = types [ i ] ;
65
136
const objectFlags = ( type as any ) . objectFlags ;
@@ -127,14 +198,32 @@ namespace ts.tracing {
127
198
display,
128
199
} ;
129
200
130
- write ( JSON . stringify ( descriptor ) ) ;
201
+ fs . writeSync ( typesFd , JSON . stringify ( descriptor ) ) ;
131
202
if ( i < numTypes - 1 ) {
132
- write ( ",\n" ) ;
203
+ fs . writeSync ( typesFd , ",\n" ) ;
133
204
}
134
205
}
135
- write ( "]\n" ) ;
206
+
207
+ fs . writeSync ( typesFd , "]\n" ) ;
208
+
209
+ fs . closeSync ( typesFd ) ;
136
210
137
211
performance . mark ( "endDumpTypes" ) ;
138
212
performance . measure ( "Dump types" , "beginDumpTypes" , "endDumpTypes" ) ;
139
213
}
214
+
215
+ export function dumpLegend ( ) {
216
+ if ( ! legendPath ) {
217
+ return ;
218
+ }
219
+ Debug . assert ( fs ) ;
220
+
221
+ fs . writeFileSync ( legendPath , JSON . stringify ( legend ) ) ;
222
+ }
223
+
224
+ interface TraceRecord {
225
+ configFilePath ?: string ;
226
+ tracePath : string ;
227
+ typesPath ?: string ;
228
+ }
140
229
}
0 commit comments