@@ -15,61 +15,68 @@ import type {ConsoleMessage} from '../third_party/index.js';
1515
1616export interface ConsoleFormatterOptions {
1717 fetchDetailedData ?: boolean ;
18- id ? : number ;
18+ id : number ;
1919 devTools ?: TargetUniverse ;
20+ resolvedArgsForTesting ?: unknown [ ] ;
2021 resolvedStackTraceForTesting ?: DevTools . DevTools . StackTrace . StackTrace . StackTrace ;
2122}
2223
2324export class ConsoleFormatter {
24- #msg: ConsoleMessage | SymbolizedError ;
25- #resolvedArgs: unknown [ ] = [ ] ;
26- #resolvedStackTrace?: DevTools . DevTools . StackTrace . StackTrace . StackTrace ;
27- #id?: number ;
28-
29- private constructor (
30- msg : ConsoleMessage | SymbolizedError ,
31- options ?: ConsoleFormatterOptions ,
32- ) {
33- this . #msg = msg ;
34- this . #id = options ?. id ;
35- this . #resolvedStackTrace = options ?. resolvedStackTraceForTesting ;
25+ readonly #id: number ;
26+ readonly #type: string ;
27+ readonly #text: string ;
28+
29+ readonly #argCount: number ;
30+ readonly #resolvedArgs: unknown [ ] ;
31+
32+ readonly #stack?: DevTools . DevTools . StackTrace . StackTrace . StackTrace ;
33+ readonly #cause?: SymbolizedError ; // eslint-disable-line no-unused-private-class-members
34+
35+ private constructor ( params : {
36+ id : number ;
37+ type : string ;
38+ text : string ;
39+ argCount ?: number ;
40+ resolvedArgs ?: unknown [ ] ;
41+ stack ?: DevTools . DevTools . StackTrace . StackTrace . StackTrace ;
42+ cause ?: SymbolizedError ;
43+ } ) {
44+ this . #id = params . id ;
45+ this . #type = params . type ;
46+ this . #text = params . text ;
47+ this . #argCount = params . argCount ?? 0 ;
48+ this . #resolvedArgs = params . resolvedArgs ?? [ ] ;
49+ this . #stack = params . stack ;
50+ this . #cause = params . cause ;
3651 }
3752
3853 static async from (
3954 msg : ConsoleMessage | UncaughtError ,
40- options ? : ConsoleFormatterOptions ,
55+ options : ConsoleFormatterOptions ,
4156 ) : Promise < ConsoleFormatter > {
4257 if ( msg instanceof UncaughtError ) {
43- return new ConsoleFormatter (
44- await SymbolizedError . fromDetails ( {
45- devTools : options ?. devTools ,
46- details : msg . details ,
47- targetId : msg . targetId ,
48- includeStackAndCause : options ?. fetchDetailedData ,
49- resolvedStackTraceForTesting : options ?. resolvedStackTraceForTesting ,
50- } ) ,
51- options ,
52- ) ;
58+ const error = await SymbolizedError . fromDetails ( {
59+ devTools : options ?. devTools ,
60+ details : msg . details ,
61+ targetId : msg . targetId ,
62+ includeStackAndCause : options ?. fetchDetailedData ,
63+ resolvedStackTraceForTesting : options ?. resolvedStackTraceForTesting ,
64+ } ) ;
65+ return new ConsoleFormatter ( {
66+ id : options . id ,
67+ type : 'error' ,
68+ text : error . message ,
69+ stack : error . stackTrace ,
70+ cause : error . cause ,
71+ } ) ;
5372 }
5473
55- const formatter = new ConsoleFormatter ( msg , options ) ;
56- if ( options ?. fetchDetailedData ) {
57- await formatter . #loadDetailedData( options ?. devTools ) ;
58- }
59- return formatter ;
60- }
61-
62- #isConsoleMessage(
63- msg : ConsoleMessage | SymbolizedError ,
64- ) : msg is ConsoleMessage {
65- // No `instanceof` as tests mock `ConsoleMessage`.
66- return 'args' in msg && typeof msg . args === 'function' ;
67- }
68-
69- async #loadDetailedData( devTools ?: TargetUniverse ) : Promise < void > {
70- if ( this . #isConsoleMessage( this . #msg) ) {
71- this . #resolvedArgs = await Promise . all (
72- this . #msg. args ( ) . map ( async ( arg , i ) => {
74+ let resolvedArgs : unknown [ ] = [ ] ;
75+ if ( options . resolvedArgsForTesting ) {
76+ resolvedArgs = options . resolvedArgsForTesting ;
77+ } else if ( options . fetchDetailedData ) {
78+ resolvedArgs = await Promise . all (
79+ msg . args ( ) . map ( async ( arg , i ) => {
7380 try {
7481 return await arg . jsonValue ( ) ;
7582 } catch {
@@ -79,80 +86,55 @@ export class ConsoleFormatter {
7986 ) ;
8087 }
8188
82- if ( devTools ) {
89+ let stack : DevTools . DevTools . StackTrace . StackTrace . StackTrace | undefined ;
90+ if ( options . resolvedStackTraceForTesting ) {
91+ stack = options . resolvedStackTraceForTesting ;
92+ } else if ( options . fetchDetailedData && options . devTools ) {
8393 try {
84- if ( this . #isConsoleMessage( this . #msg) ) {
85- this . #resolvedStackTrace = await createStackTraceForConsoleMessage (
86- devTools ,
87- this . #msg,
88- ) ;
89- }
94+ stack = await createStackTraceForConsoleMessage ( options . devTools , msg ) ;
9095 } catch {
9196 // ignore
9297 }
9398 }
99+
100+ return new ConsoleFormatter ( {
101+ id : options . id ,
102+ type : msg . type ( ) ,
103+ text : msg . text ( ) ,
104+ argCount : resolvedArgs . length || msg . args ( ) . length ,
105+ resolvedArgs,
106+ stack,
107+ } ) ;
94108 }
95109
96110 // The short format for a console message.
97111 toString ( ) : string {
98- const type = this . #getType( ) ;
99- const text = this . #getText( ) ;
100- const argsCount = this . #getArgsCount( ) ;
101- const idPart = this . #id !== undefined ? `msgid=${ this . #id} ` : '' ;
102- return `${ idPart } [${ type } ] ${ text } (${ argsCount } args)` ;
112+ return `msgid=${ this . #id} [${ this . #type} ] ${ this . #text} (${ this . #argCount} args)` ;
103113 }
104114
105115 // The verbose format for a console message, including all details.
106116 toStringDetailed ( ) : string {
107117 const result = [
108- this . #id !== undefined ? `ID: ${ this . #id} ` : '' ,
109- `Message: ${ this . #getType ( ) } > ${ this . #getText ( ) } ` ,
118+ `ID: ${ this . #id} ` ,
119+ `Message: ${ this . #type } > ${ this . #text } ` ,
110120 this . #formatArgs( ) ,
111- this . #formatStackTrace(
112- this . #msg instanceof SymbolizedError
113- ? this . #msg. stackTrace
114- : this . #resolvedStackTrace,
115- ) ,
121+ this . #formatStackTrace( this . #stack) ,
116122 ] . filter ( line => ! ! line ) ;
117123 return result . join ( '\n' ) ;
118124 }
119125
120- #getType( ) : string {
121- if ( ! this . #isConsoleMessage( this . #msg) ) {
122- return 'error' ;
123- }
124- return this . #msg. type ( ) ;
125- }
126-
127- #getText( ) : string {
128- if ( ! this . #isConsoleMessage( this . #msg) ) {
129- return this . #msg. message ;
130- }
131- return this . #msg. text ( ) ;
132- }
133-
134126 #getArgs( ) : unknown [ ] {
135- if ( ! this . #isConsoleMessage( this . #msg) ) {
136- return [ ] ;
137- }
138127 if ( this . #resolvedArgs. length > 0 ) {
139128 const args = [ ...this . #resolvedArgs] ;
140129 // If there is no text, the first argument serves as text (see formatMessage).
141- if ( ! this . #msg . text ( ) ) {
130+ if ( ! this . #text) {
142131 args . shift ( ) ;
143132 }
144133 return args ;
145134 }
146135 return [ ] ;
147136 }
148137
149- #getArgsCount( ) : number {
150- if ( ! this . #isConsoleMessage( this . #msg) ) {
151- return 0 ;
152- }
153- return this . #resolvedArgs. length || this . #msg. args ( ) . length ;
154- }
155-
156138 #formatArg( arg : unknown ) {
157139 return typeof arg === 'object' ? JSON . stringify ( arg ) : String ( arg ) ;
158140 }
@@ -215,22 +197,22 @@ export class ConsoleFormatter {
215197 }
216198 toJSON ( ) : object {
217199 return {
218- type : this . #getType ( ) ,
219- text : this . #getText ( ) ,
220- argsCount : this . #getArgsCount ( ) ,
200+ type : this . #type ,
201+ text : this . #text ,
202+ argsCount : this . #argCount ,
221203 id : this . #id,
222204 } ;
223205 }
224206
225207 toJSONDetailed ( ) : object {
226208 return {
227209 id : this . #id,
228- type : this . #getType ( ) ,
229- text : this . #getText ( ) ,
210+ type : this . #type ,
211+ text : this . #text ,
230212 args : this . #getArgs( ) . map ( arg =>
231213 typeof arg === 'object' ? arg : String ( arg ) ,
232214 ) ,
233- stackTrace : this . #resolvedStackTrace ,
215+ stackTrace : this . #stack ,
234216 } ;
235217 }
236218}
0 commit comments