@@ -22,8 +22,11 @@ const {
2222 DatePrototypeToISOString,
2323 DatePrototypeToString,
2424 ErrorPrototypeToString,
25+ Function,
26+ FunctionPrototype,
2527 FunctionPrototypeBind,
2628 FunctionPrototypeCall,
29+ FunctionPrototypeSymbolHasInstance,
2730 FunctionPrototypeToString,
2831 JSONStringify,
2932 MapPrototypeEntries,
@@ -50,6 +53,7 @@ const {
5053 ObjectGetPrototypeOf,
5154 ObjectIs,
5255 ObjectKeys,
56+ ObjectPrototype,
5357 ObjectPrototypeHasOwnProperty,
5458 ObjectPrototypePropertyIsEnumerable,
5559 ObjectSeal,
@@ -593,10 +597,26 @@ function isInstanceof(object, proto) {
593597 }
594598}
595599
600+ // Special-case for some builtin prototypes in case their `constructor` property has been tampered.
601+ const wellKnownPrototypes = new SafeMap ( ) ;
602+ wellKnownPrototypes . set ( ObjectPrototype , { name : 'Object' , constructor : Object } ) ;
603+ wellKnownPrototypes . set ( FunctionPrototype , { name : 'Function' , constructor : Function } ) ;
604+
596605function getConstructorName ( obj , ctx , recurseTimes , protoProps ) {
597606 let firstProto ;
598607 const tmp = obj ;
599608 while ( obj || isUndetectableObject ( obj ) ) {
609+ const wellKnownPrototypeNameAndConstructor = wellKnownPrototypes . get ( obj ) ;
610+ if ( wellKnownPrototypeNameAndConstructor != null ) {
611+ const { name, constructor } = wellKnownPrototypeNameAndConstructor ;
612+ if ( FunctionPrototypeSymbolHasInstance ( constructor , tmp ) ) {
613+ if ( protoProps !== undefined && firstProto !== obj ) {
614+ addPrototypeProperties (
615+ ctx , tmp , firstProto || tmp , recurseTimes , protoProps ) ;
616+ }
617+ return name ;
618+ }
619+ }
600620 const descriptor = ObjectGetOwnPropertyDescriptor ( obj , 'constructor' ) ;
601621 if ( descriptor !== undefined &&
602622 typeof descriptor . value === 'function' &&
@@ -954,7 +974,11 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
954974 if ( noIterator ) {
955975 keys = getKeys ( value , ctx . showHidden ) ;
956976 braces = [ '{' , '}' ] ;
957- if ( constructor === 'Object' ) {
977+ if ( typeof value === 'function' ) {
978+ base = getFunctionBase ( value , constructor , tag ) ;
979+ if ( keys . length === 0 && protoProps === undefined )
980+ return ctx . stylize ( base , 'special' ) ;
981+ } else if ( constructor === 'Object' ) {
958982 if ( isArgumentsObject ( value ) ) {
959983 braces [ 0 ] = '[Arguments] {' ;
960984 } else if ( tag !== '' ) {
@@ -963,10 +987,6 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
963987 if ( keys . length === 0 && protoProps === undefined ) {
964988 return `${ braces [ 0 ] } }` ;
965989 }
966- } else if ( typeof value === 'function' ) {
967- base = getFunctionBase ( value , constructor , tag ) ;
968- if ( keys . length === 0 && protoProps === undefined )
969- return ctx . stylize ( base , 'special' ) ;
970990 } else if ( isRegExp ( value ) ) {
971991 // Make RegExps say that they are RegExps
972992 base = RegExpPrototypeToString (
0 commit comments