@@ -50,27 +50,41 @@ import {
50
50
51
51
const REGISTER_SIZE = 32 ;
52
52
53
- export type ConsoleLogEntry = string | ConsoleLogEntry [ ] ;
54
- export type ConsoleLogs = ConsoleLogEntry [ ] ;
53
+ /** The decoded string representation of the arguments supplied to console.log */
54
+ export type ConsoleLogArgs = string [ ] ;
55
+ export type ConsoleLogs = ConsoleLogArgs [ ] ;
55
56
56
57
export class ConsoleLogger {
57
58
/**
58
59
* Temporary code to print console.sol messages that come from EDR
59
60
*/
60
- public getDecodedLogs ( messages : Buffer [ ] ) : string [ ] {
61
+ public static getDecodedLogs ( messages : Buffer [ ] ) : string [ ] {
61
62
const logs : string [ ] = [ ] ;
62
63
63
64
for ( const message of messages ) {
64
- const log = this . _maybeConsoleLog ( message ) ;
65
+ const log = ConsoleLogger . _maybeConsoleLog ( message ) ;
65
66
if ( log !== undefined ) {
66
- logs . push ( consoleLogToString ( log ) ) ;
67
+ logs . push ( ConsoleLogger . format ( log ) ) ;
67
68
}
68
69
}
69
70
70
71
return logs ;
71
72
}
72
73
73
- private _maybeConsoleLog ( calldata : Buffer ) : ConsoleLogs | undefined {
74
+ /**
75
+ * Returns a formatted string using the first argument as a `printf`-like
76
+ * format string which can contain zero or more format specifiers.
77
+ *
78
+ * If there are more arguments passed than the number of specifiers, the
79
+ * extra arguments are concatenated to the returned string, separated by spaces.
80
+ */
81
+ public static format ( args : ConsoleLogArgs = [ ] ) : string {
82
+ return util . format ( ...args ) ;
83
+ }
84
+
85
+ private static _maybeConsoleLog (
86
+ calldata : Buffer
87
+ ) : ConsoleLogArgs | undefined {
74
88
const selector = bytesToInt ( calldata . slice ( 0 , 4 ) ) ;
75
89
const parameters = calldata . slice ( 4 ) ;
76
90
@@ -79,15 +93,10 @@ export class ConsoleLogger {
79
93
return ;
80
94
}
81
95
82
- const consoleLogs = this . _decode ( parameters , argTypes ) ;
83
-
84
- this . _replaceNumberFormatSpecifiers ( consoleLogs ) ;
85
-
86
- return consoleLogs ;
87
- }
96
+ const decodedArgs = ConsoleLogger . _decode ( parameters , argTypes ) ;
88
97
89
- private _replaceNumberFormatSpecifiers ( consoleLogs : ConsoleLogs ) {
90
98
/**
99
+ * The first argument is interpreted as the format string, which may need adjusting.
91
100
* Replace the occurrences of %d and %i with %s. This is necessary because if the arguments passed are numbers,
92
101
* they could be too large to be formatted as a Number or an Integer, so it is safer to use a String.
93
102
* %d and %i are replaced only if there is an odd number of % before the d or i.
@@ -99,15 +108,18 @@ export class ConsoleLogger {
99
108
* (?<!%) negative look-behind to make this work.
100
109
* The (?:) is just to avoid capturing that inner group.
101
110
*/
102
- if ( consoleLogs . length > 0 && typeof consoleLogs [ 0 ] === "string" ) {
103
- consoleLogs [ 0 ] = consoleLogs [ 0 ] . replace (
111
+ if ( decodedArgs . length > 0 ) {
112
+ decodedArgs [ 0 ] = decodedArgs [ 0 ] . replace (
104
113
/ ( (?< ! % ) (?: % % ) * ) ( % [ d i ] ) / g,
105
114
"$1%s"
106
115
) ;
107
116
}
117
+
118
+ return decodedArgs ;
108
119
}
109
120
110
- private _decode ( data : Buffer , types : string [ ] ) : ConsoleLogs {
121
+ /** Decodes parameters from `data` according to `types` into their string representation. */
122
+ private static _decode ( data : Buffer , types : string [ ] ) : string [ ] {
111
123
return types . map ( ( type , i ) => {
112
124
const position : number = i * 32 ;
113
125
switch ( types [ i ] ) {
@@ -221,16 +233,3 @@ export class ConsoleLogger {
221
233
} ) ;
222
234
}
223
235
}
224
-
225
- export function consoleLogToString ( log : ConsoleLogs ) : string {
226
- if ( log === undefined ) {
227
- return "" ;
228
- }
229
-
230
- // special case for console.log()
231
- if ( log . length === 0 ) {
232
- return "" ;
233
- }
234
-
235
- return util . format ( log [ 0 ] , ...log . slice ( 1 ) ) ;
236
- }
0 commit comments