11'use strict' ;
22
33const uv = process . binding ( 'uv' ) ;
4+ const Debug = require ( 'vm' ) . runInDebugContext ( 'Debug' ) ;
45
56const formatRegExp = / % [ s d j % ] / g;
67exports . format = function ( f ) {
@@ -192,6 +193,14 @@ function arrayToHash(array) {
192193}
193194
194195
196+ function inspectPromise ( p ) {
197+ var mirror = Debug . MakeMirror ( p , true ) ;
198+ if ( ! mirror . isPromise ( ) )
199+ return null ;
200+ return { status : mirror . status ( ) , value : mirror . promiseValue ( ) . value_ } ;
201+ }
202+
203+
195204function formatValue ( ctx , value , recurseTimes ) {
196205 // Provide a hook for user-specified inspect functions.
197206 // Check that value is an object with an inspect function on it
@@ -276,14 +285,43 @@ function formatValue(ctx, value, recurseTimes) {
276285 }
277286 }
278287
279- var base = '' , array = false , braces = [ '{' , '}' ] ;
288+ var base = '' , empty = false , braces , formatter ;
280289
281- // Make Array say that they are Array
282290 if ( Array . isArray ( value ) ) {
283- array = true ;
284291 braces = [ '[' , ']' ] ;
292+ empty = value . length === 0 ;
293+ formatter = formatArray ;
294+ } else if ( value instanceof Set ) {
295+ braces = [ 'Set {' , '}' ] ;
296+ // With `showHidden`, `length` will display as a hidden property for
297+ // arrays. For consistency's sake, do the same for `size`, even though this
298+ // property isn't selected by Object.getOwnPropertyNames().
299+ if ( ctx . showHidden )
300+ keys . unshift ( 'size' ) ;
301+ empty = value . size === 0 ;
302+ formatter = formatSet ;
303+ } else if ( value instanceof Map ) {
304+ braces = [ 'Map {' , '}' ] ;
305+ // Ditto.
306+ if ( ctx . showHidden )
307+ keys . unshift ( 'size' ) ;
308+ empty = value . size === 0 ;
309+ formatter = formatMap ;
310+ } else {
311+ // Only create a mirror if the object superficially looks like a Promise.
312+ var promiseInternals = value instanceof Promise && inspectPromise ( value ) ;
313+ if ( promiseInternals ) {
314+ braces = [ 'Promise {' , '}' ] ;
315+ formatter = formatPromise ;
316+ } else {
317+ braces = [ '{' , '}' ] ;
318+ empty = true ; // No other data than keys.
319+ formatter = formatObject ;
320+ }
285321 }
286322
323+ empty = empty === true && keys . length === 0 ;
324+
287325 // Make functions say that they are functions
288326 if ( typeof value === 'function' ) {
289327 var n = value . name ? ': ' + value . name : '' ;
@@ -323,7 +361,7 @@ function formatValue(ctx, value, recurseTimes) {
323361 base = ' ' + '[Boolean: ' + formatted + ']' ;
324362 }
325363
326- if ( keys . length === 0 && ( ! array || value . length === 0 ) ) {
364+ if ( empty === true ) {
327365 return braces [ 0 ] + base + braces [ 1 ] ;
328366 }
329367
@@ -337,14 +375,7 @@ function formatValue(ctx, value, recurseTimes) {
337375
338376 ctx . seen . push ( value ) ;
339377
340- var output ;
341- if ( array ) {
342- output = formatArray ( ctx , value , recurseTimes , visibleKeys , keys ) ;
343- } else {
344- output = keys . map ( function ( key ) {
345- return formatProperty ( ctx , value , recurseTimes , visibleKeys , key , array ) ;
346- } ) ;
347- }
378+ var output = formatter ( ctx , value , recurseTimes , visibleKeys , keys ) ;
348379
349380 ctx . seen . pop ( ) ;
350381
@@ -397,6 +428,13 @@ function formatError(value) {
397428}
398429
399430
431+ function formatObject ( ctx , value , recurseTimes , visibleKeys , keys ) {
432+ return keys . map ( function ( key ) {
433+ return formatProperty ( ctx , value , recurseTimes , visibleKeys , key , false ) ;
434+ } ) ;
435+ }
436+
437+
400438function formatArray ( ctx , value , recurseTimes , visibleKeys , keys ) {
401439 var output = [ ] ;
402440 for ( var i = 0 , l = value . length ; i < l ; ++ i ) {
@@ -417,6 +455,59 @@ function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
417455}
418456
419457
458+ function formatSet ( ctx , value , recurseTimes , visibleKeys , keys ) {
459+ var output = [ ] ;
460+ value . forEach ( function ( v ) {
461+ var nextRecurseTimes = recurseTimes === null ? null : recurseTimes - 1 ;
462+ var str = formatValue ( ctx , v , nextRecurseTimes ) ;
463+ output . push ( str ) ;
464+ } ) ;
465+ keys . forEach ( function ( key ) {
466+ output . push ( formatProperty ( ctx , value , recurseTimes , visibleKeys ,
467+ key , false ) ) ;
468+ } ) ;
469+ return output ;
470+ }
471+
472+
473+ function formatMap ( ctx , value , recurseTimes , visibleKeys , keys ) {
474+ var output = [ ] ;
475+ value . forEach ( function ( v , k ) {
476+ var nextRecurseTimes = recurseTimes === null ? null : recurseTimes - 1 ;
477+ var str = formatValue ( ctx , k , nextRecurseTimes ) ;
478+ str += ' => ' ;
479+ str += formatValue ( ctx , v , nextRecurseTimes ) ;
480+ output . push ( str ) ;
481+ } ) ;
482+ keys . forEach ( function ( key ) {
483+ output . push ( formatProperty ( ctx , value , recurseTimes , visibleKeys ,
484+ key , false ) ) ;
485+ } ) ;
486+ return output ;
487+ }
488+
489+ function formatPromise ( ctx , value , recurseTimes , visibleKeys , keys ) {
490+ var output = [ ] ;
491+ var internals = inspectPromise ( value ) ;
492+ if ( internals . status === 'pending' ) {
493+ output . push ( '<pending>' ) ;
494+ } else {
495+ var nextRecurseTimes = recurseTimes === null ? null : recurseTimes - 1 ;
496+ var str = formatValue ( ctx , internals . value , nextRecurseTimes ) ;
497+ if ( internals . status === 'rejected' ) {
498+ output . push ( '<rejected> ' + str ) ;
499+ } else {
500+ output . push ( str ) ;
501+ }
502+ }
503+ keys . forEach ( function ( key ) {
504+ output . push ( formatProperty ( ctx , value , recurseTimes , visibleKeys ,
505+ key , false ) ) ;
506+ } ) ;
507+ return output ;
508+ }
509+
510+
420511function formatProperty ( ctx , value , recurseTimes , visibleKeys , key , array ) {
421512 var name , str , desc ;
422513 desc = Object . getOwnPropertyDescriptor ( value , key ) || { value : value [ key ] } ;
@@ -488,7 +579,10 @@ function reduceToSingleString(output, base, braces) {
488579
489580 if ( length > 60 ) {
490581 return braces [ 0 ] +
491- ( base === '' ? '' : base + '\n ' ) +
582+ // If the opening "brace" is too large, like in the case of "Set {",
583+ // we need to force the first item to be on the next line or the
584+ // items will not line up correctly.
585+ ( base === '' && braces [ 0 ] . length === 1 ? '' : base + '\n ' ) +
492586 ' ' +
493587 output . join ( ',\n ' ) +
494588 ' ' +
0 commit comments