@@ -72,7 +72,6 @@ const {
7272 customInspectSymbol,
7373 deprecate,
7474 getSystemErrorName : internalErrorName ,
75- getIdentificationOf,
7675 isError,
7776 promisify,
7877 join,
@@ -397,6 +396,35 @@ function stylizeNoColor(str, styleType) {
397396 return str ;
398397}
399398
399+ function getConstructorName ( obj ) {
400+ while ( obj ) {
401+ const descriptor = Object . getOwnPropertyDescriptor ( obj , 'constructor' ) ;
402+ if ( descriptor !== undefined &&
403+ typeof descriptor . value === 'function' &&
404+ descriptor . value . name !== '' ) {
405+ return descriptor . value . name ;
406+ }
407+
408+ obj = Object . getPrototypeOf ( obj ) ;
409+ }
410+
411+ return '' ;
412+ }
413+
414+ function getPrefix ( constructor , tag ) {
415+ if ( constructor !== '' ) {
416+ if ( tag !== '' && constructor !== tag ) {
417+ return `${ constructor } [${ tag } ] ` ;
418+ }
419+ return `${ constructor } ` ;
420+ }
421+
422+ if ( tag !== '' )
423+ return `[${ tag } ] ` ;
424+
425+ return '' ;
426+ }
427+
400428function formatValue ( ctx , value , recurseTimes , ln ) {
401429 // Primitive types cannot have properties
402430 if ( typeof value !== 'object' && typeof value !== 'function' ) {
@@ -476,15 +504,10 @@ function formatValue(ctx, value, recurseTimes, ln) {
476504
477505 const keyLength = keys . length + symbols . length ;
478506
479- const { constructor, tag } = getIdentificationOf ( value ) ;
480- let prefix = '' ;
481- if ( constructor && tag && constructor !== tag )
482- prefix = `${ constructor } [${ tag } ] ` ;
483- else if ( constructor )
484- prefix = `${ constructor } ` ;
485- else if ( tag )
486- prefix = `[${ tag } ] ` ;
487-
507+ const constructor = getConstructorName ( value ) ;
508+ let tag = value [ Symbol . toStringTag ] ;
509+ if ( typeof tag !== 'string' )
510+ tag = '' ;
488511 let base = '' ;
489512 let formatter = formatObject ;
490513 let braces ;
@@ -497,22 +520,25 @@ function formatValue(ctx, value, recurseTimes, ln) {
497520 noIterator = false ;
498521 if ( Array . isArray ( value ) ) {
499522 // Only set the constructor for non ordinary ("Array [...]") arrays.
523+ const prefix = getPrefix ( constructor , tag ) ;
500524 braces = [ `${ prefix === 'Array ' ? '' : prefix } [` , ']' ] ;
501525 if ( value . length === 0 && keyLength === 0 )
502526 return `${ braces [ 0 ] } ]` ;
503527 formatter = formatArray ;
504528 } else if ( isSet ( value ) ) {
529+ const prefix = getPrefix ( constructor , tag ) ;
505530 if ( value . size === 0 && keyLength === 0 )
506531 return `${ prefix } {}` ;
507532 braces = [ `${ prefix } {` , '}' ] ;
508533 formatter = formatSet ;
509534 } else if ( isMap ( value ) ) {
535+ const prefix = getPrefix ( constructor , tag ) ;
510536 if ( value . size === 0 && keyLength === 0 )
511537 return `${ prefix } {}` ;
512538 braces = [ `${ prefix } {` , '}' ] ;
513539 formatter = formatMap ;
514540 } else if ( isTypedArray ( value ) ) {
515- braces = [ `${ prefix } [` , ']' ] ;
541+ braces = [ `${ getPrefix ( constructor , tag ) } [` , ']' ] ;
516542 formatter = formatTypedArray ;
517543 } else if ( isMapIterator ( value ) ) {
518544 braces = [ `[${ tag } ] {` , '}' ] ;
@@ -544,11 +570,16 @@ function formatValue(ctx, value, recurseTimes, ln) {
544570 }
545571 if ( noIterator ) {
546572 braces = [ '{' , '}' ] ;
547- if ( prefix === 'Object ' ) {
573+ if ( constructor === 'Object' ) {
548574 if ( isArgumentsObject ( value ) ) {
549575 braces [ 0 ] = '[Arguments] {' ;
550576 if ( keyLength === 0 )
551577 return '[Arguments] {}' ;
578+ } else if ( tag !== '' ) {
579+ braces [ 0 ] = `${ getPrefix ( constructor , tag ) } {` ;
580+ if ( keyLength === 0 ) {
581+ return `${ braces [ 0 ] } }` ;
582+ }
552583 } else if ( keyLength === 0 ) {
553584 return '{}' ;
554585 }
@@ -580,27 +611,28 @@ function formatValue(ctx, value, recurseTimes, ln) {
580611 // Fast path for ArrayBuffer and SharedArrayBuffer.
581612 // Can't do the same for DataView because it has a non-primitive
582613 // .buffer property that we need to recurse for.
614+ const prefix = getPrefix ( constructor , tag ) ;
583615 if ( keyLength === 0 )
584616 return prefix +
585617 `{ byteLength: ${ formatNumber ( ctx . stylize , value . byteLength ) } }` ;
586618 braces [ 0 ] = `${ prefix } {` ;
587619 keys . unshift ( 'byteLength' ) ;
588620 } else if ( isDataView ( value ) ) {
589- braces [ 0 ] = `${ prefix } {` ;
621+ braces [ 0 ] = `${ getPrefix ( constructor , tag ) } {` ;
590622 // .buffer goes last, it's not a primitive like the others.
591623 keys . unshift ( 'byteLength' , 'byteOffset' , 'buffer' ) ;
592624 } else if ( isPromise ( value ) ) {
593- braces [ 0 ] = `${ prefix } {` ;
625+ braces [ 0 ] = `${ getPrefix ( constructor , tag ) } {` ;
594626 formatter = formatPromise ;
595627 } else if ( isWeakSet ( value ) ) {
596- braces [ 0 ] = `${ prefix } {` ;
628+ braces [ 0 ] = `${ getPrefix ( constructor , tag ) } {` ;
597629 if ( ctx . showHidden ) {
598630 formatter = formatWeakSet ;
599631 } else {
600632 extra = '[items unknown]' ;
601633 }
602634 } else if ( isWeakMap ( value ) ) {
603- braces [ 0 ] = `${ prefix } {` ;
635+ braces [ 0 ] = `${ getPrefix ( constructor , tag ) } {` ;
604636 if ( ctx . showHidden ) {
605637 formatter = formatWeakMap ;
606638 } else {
@@ -639,9 +671,9 @@ function formatValue(ctx, value, recurseTimes, ln) {
639671 } else if ( keyLength === 0 ) {
640672 if ( isExternal ( value ) )
641673 return ctx . stylize ( '[External]' , 'special' ) ;
642- return `${ prefix } {}` ;
674+ return `${ getPrefix ( constructor , tag ) } {}` ;
643675 } else {
644- braces [ 0 ] = `${ prefix } {` ;
676+ braces [ 0 ] = `${ getPrefix ( constructor , tag ) } {` ;
645677 }
646678 }
647679 }
@@ -676,8 +708,8 @@ function formatNumber(fn, value) {
676708function formatPrimitive ( fn , value , ctx ) {
677709 if ( typeof value === 'string' ) {
678710 if ( ctx . compact === false &&
679- value . length > MIN_LINE_LENGTH &&
680- ctx . indentationLvl + value . length > ctx . breakLength ) {
711+ ctx . indentationLvl + value . length > ctx . breakLength &&
712+ value . length > MIN_LINE_LENGTH ) {
681713 // eslint-disable-next-line max-len
682714 const minLineLength = Math . max ( ctx . breakLength - ctx . indentationLvl , MIN_LINE_LENGTH ) ;
683715 // eslint-disable-next-line max-len
@@ -696,9 +728,9 @@ function formatPrimitive(fn, value, ctx) {
696728 // eslint-disable-next-line max-len, node-core/no-unescaped-regexp-dot
697729 readableRegExps [ divisor ] = new RegExp ( `(.|\\n){1,${ divisor } }(\\s|$)|(\\n|.)+?(\\s|$)` , 'gm' ) ;
698730 }
699- const indent = ' ' . repeat ( ctx . indentationLvl ) ;
700731 const matches = value . match ( readableRegExps [ divisor ] ) ;
701732 if ( matches . length > 1 ) {
733+ const indent = ' ' . repeat ( ctx . indentationLvl ) ;
702734 res += `${ fn ( strEscape ( matches [ 0 ] ) , 'string' ) } +\n` ;
703735 for ( var i = 1 ; i < matches . length - 1 ; i ++ ) {
704736 res += `${ indent } ${ fn ( strEscape ( matches [ i ] ) , 'string' ) } +\n` ;
0 commit comments