@@ -26,6 +26,7 @@ const {
2626 codes : {
2727 ERR_CONSOLE_WRITABLE_STREAM ,
2828 ERR_INVALID_ARG_TYPE ,
29+ ERR_INVALID_ARG_VALUE ,
2930 } ,
3031} = require ( 'internal/errors' ) ;
3132const { previewMapIterator, previewSetIterator } = require ( 'internal/v8' ) ;
@@ -49,24 +50,32 @@ const {
4950} = Array ;
5051
5152// 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' ) ;
5359
5460function Console ( options /* or: stdout, stderr, ignoreErrors = true */ ) {
5561 if ( ! ( this instanceof Console ) ) {
5662 return new Console ( ...arguments ) ;
5763 }
5864
59- let stdout , stderr , ignoreErrors ;
65+ let stdout , stderr , ignoreErrors , colorMode ;
6066 if ( options && typeof options . write !== 'function' ) {
6167 ( {
6268 stdout,
6369 stderr = stdout ,
64- ignoreErrors = true
70+ ignoreErrors = true ,
71+ colorMode = false
6572 } = options ) ;
6673 } 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+ } ) ;
7079 }
7180
7281 if ( ! stdout || typeof stdout . write !== 'function' ) {
@@ -94,7 +103,11 @@ function Console(options /* or: stdout, stderr, ignoreErrors = true */) {
94103 prop . value = createWriteErrorHandler ( stderr ) ;
95104 Object . defineProperty ( this , '_stderrErrorHandler' , prop ) ;
96105
106+ if ( typeof colorMode !== 'boolean' && colorMode !== 'auto' )
107+ throw new ERR_INVALID_ARG_VALUE ( 'colorMode' , colorMode ) ;
108+
97109 this [ kCounts ] = new Map ( ) ;
110+ this [ kColorMode ] = colorMode ;
98111
99112 Object . defineProperty ( this , kGroupIndent , { writable : true } ) ;
100113 this [ kGroupIndent ] = '' ;
@@ -156,13 +169,33 @@ function write(ignoreErrors, stream, string, errorhandler, groupIndent) {
156169 }
157170}
158171
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+
159195Console . prototype . log = function log ( ...args ) {
160196 write ( this . _ignoreErrors ,
161197 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 ) ,
166199 this . _stdoutErrorHandler ,
167200 this [ kGroupIndent ] ) ;
168201} ;
@@ -173,14 +206,16 @@ Console.prototype.dirxml = Console.prototype.log;
173206Console . prototype . warn = function warn ( ...args ) {
174207 write ( this . _ignoreErrors ,
175208 this . _stderr ,
176- util . format . apply ( null , args ) ,
209+ this [ kFormatForStderr ] ( args ) ,
177210 this . _stderrErrorHandler ,
178211 this [ kGroupIndent ] ) ;
179212} ;
180213Console . prototype . error = Console . prototype . warn ;
181214
182215Console . 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 ) ;
184219 write ( this . _ignoreErrors ,
185220 this . _stdout ,
186221 util . inspect ( object , options ) ,
@@ -211,7 +246,7 @@ Console.prototype.timeEnd = function timeEnd(label = 'default') {
211246Console . prototype . trace = function trace ( ...args ) {
212247 const err = {
213248 name : 'Trace' ,
214- message : util . format . apply ( null , args )
249+ message : this [ kFormatForStderr ] ( args )
215250 } ;
216251 Error . captureStackTrace ( err , trace ) ;
217252 this . error ( err . stack ) ;
@@ -220,7 +255,7 @@ Console.prototype.trace = function trace(...args) {
220255Console . prototype . assert = function assert ( expression , ...args ) {
221256 if ( ! expression ) {
222257 args [ 0 ] = `Assertion failed${ args . length === 0 ? '' : `: ${ args [ 0 ] } ` } ` ;
223- this . warn ( util . format . apply ( null , args ) ) ;
258+ this . warn ( this [ kFormatForStderr ] ( args ) ) ;
224259 }
225260} ;
226261
0 commit comments