@@ -26,6 +26,7 @@ const {
26
26
codes : {
27
27
ERR_CONSOLE_WRITABLE_STREAM ,
28
28
ERR_INVALID_ARG_TYPE ,
29
+ ERR_INVALID_ARG_VALUE ,
29
30
} ,
30
31
} = require ( 'internal/errors' ) ;
31
32
const { Buffer : { isBuffer } } = require ( 'buffer' ) ;
@@ -48,24 +49,32 @@ const {
48
49
} = Array ;
49
50
50
51
// Track amount of indentation required via `console.group()`.
51
- const kGroupIndent = Symbol ( 'groupIndent' ) ;
52
+ const kGroupIndent = Symbol ( 'kGroupIndent' ) ;
53
+
54
+ const kFormatForStderr = Symbol ( 'kFormatForStderr' ) ;
55
+ const kFormatForStdout = Symbol ( 'kFormatForStdout' ) ;
56
+ const kGetInspectOptions = Symbol ( 'kGetInspectOptions' ) ;
57
+ const kColorMode = Symbol ( 'kColorMode' ) ;
52
58
53
59
function Console ( options /* or: stdout, stderr, ignoreErrors = true */ ) {
54
60
if ( ! ( this instanceof Console ) ) {
55
61
return new Console ( ...arguments ) ;
56
62
}
57
63
58
- let stdout , stderr , ignoreErrors ;
64
+ let stdout , stderr , ignoreErrors , colorMode ;
59
65
if ( options && typeof options . write !== 'function' ) {
60
66
( {
61
67
stdout,
62
68
stderr = stdout ,
63
- ignoreErrors = true
69
+ ignoreErrors = true ,
70
+ colorMode = false
64
71
} = options ) ;
65
72
} else {
66
- stdout = options ;
67
- stderr = arguments [ 1 ] ;
68
- ignoreErrors = arguments [ 2 ] === undefined ? true : arguments [ 2 ] ;
73
+ return new Console ( {
74
+ stdout : options ,
75
+ stderr : arguments [ 1 ] ,
76
+ ignoreErrors : arguments [ 2 ]
77
+ } ) ;
69
78
}
70
79
71
80
if ( ! stdout || typeof stdout . write !== 'function' ) {
@@ -93,7 +102,11 @@ function Console(options /* or: stdout, stderr, ignoreErrors = true */) {
93
102
prop . value = createWriteErrorHandler ( stderr ) ;
94
103
Object . defineProperty ( this , '_stderrErrorHandler' , prop ) ;
95
104
105
+ if ( typeof colorMode !== 'boolean' && colorMode !== 'auto' )
106
+ throw new ERR_INVALID_ARG_VALUE ( 'colorMode' , colorMode ) ;
107
+
96
108
this [ kCounts ] = new Map ( ) ;
109
+ this [ kColorMode ] = colorMode ;
97
110
98
111
Object . defineProperty ( this , kGroupIndent , { writable : true } ) ;
99
112
this [ kGroupIndent ] = '' ;
@@ -155,13 +168,33 @@ function write(ignoreErrors, stream, string, errorhandler, groupIndent) {
155
168
}
156
169
}
157
170
171
+ const kColorInspectOptions = { colors : true } ;
172
+ const kNoColorInspectOptions = { } ;
173
+ Console . prototype [ kGetInspectOptions ] = function ( stream ) {
174
+ let color = this [ kColorMode ] ;
175
+ if ( color === 'auto' ) {
176
+ color = stream . isTTY && (
177
+ typeof stream . getColorDepth === 'function' ?
178
+ stream . getColorDepth ( ) > 2 : true ) ;
179
+ }
180
+
181
+ return color ? kColorInspectOptions : kNoColorInspectOptions ;
182
+ } ;
183
+
184
+ Console . prototype [ kFormatForStdout ] = function ( args ) {
185
+ const opts = this [ kGetInspectOptions ] ( this . _stdout ) ;
186
+ return util . formatWithOptions ( opts , ...args ) ;
187
+ } ;
188
+
189
+ Console . prototype [ kFormatForStderr ] = function ( args ) {
190
+ const opts = this [ kGetInspectOptions ] ( this . _stderr ) ;
191
+ return util . formatWithOptions ( opts , ...args ) ;
192
+ } ;
193
+
158
194
Console . prototype . log = function log ( ...args ) {
159
195
write ( this . _ignoreErrors ,
160
196
this . _stdout ,
161
- // The performance of .apply and the spread operator seems on par in V8
162
- // 6.3 but the spread operator, unlike .apply(), pushes the elements
163
- // onto the stack. That is, it makes stack overflows more likely.
164
- util . format . apply ( null , args ) ,
197
+ this [ kFormatForStdout ] ( args ) ,
165
198
this . _stdoutErrorHandler ,
166
199
this [ kGroupIndent ] ) ;
167
200
} ;
@@ -172,14 +205,16 @@ Console.prototype.dirxml = Console.prototype.log;
172
205
Console . prototype . warn = function warn ( ...args ) {
173
206
write ( this . _ignoreErrors ,
174
207
this . _stderr ,
175
- util . format . apply ( null , args ) ,
208
+ this [ kFormatForStderr ] ( args ) ,
176
209
this . _stderrErrorHandler ,
177
210
this [ kGroupIndent ] ) ;
178
211
} ;
179
212
Console . prototype . error = Console . prototype . warn ;
180
213
181
214
Console . prototype . dir = function dir ( object , options ) {
182
- options = Object . assign ( { customInspect : false } , options ) ;
215
+ options = Object . assign ( {
216
+ customInspect : false
217
+ } , this [ kGetInspectOptions ] ( this . _stdout ) , options ) ;
183
218
write ( this . _ignoreErrors ,
184
219
this . _stdout ,
185
220
util . inspect ( object , options ) ,
@@ -210,7 +245,7 @@ Console.prototype.timeEnd = function timeEnd(label = 'default') {
210
245
Console . prototype . trace = function trace ( ...args ) {
211
246
const err = {
212
247
name : 'Trace' ,
213
- message : util . format . apply ( null , args )
248
+ message : this [ kFormatForStderr ] ( args )
214
249
} ;
215
250
Error . captureStackTrace ( err , trace ) ;
216
251
this . error ( err . stack ) ;
0 commit comments