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