@@ -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 MapPrototypeGetSize,
@@ -50,6 +53,7 @@ const {
5053 ObjectGetPrototypeOf,
5154 ObjectIs,
5255 ObjectKeys,
56+ ObjectPrototype,
5357 ObjectPrototypeHasOwnProperty,
5458 ObjectPrototypePropertyIsEnumerable,
5559 ObjectSeal,
@@ -588,10 +592,26 @@ function isInstanceof(object, proto) {
588592 }
589593}
590594
595+ // Special-case for some builtin prototypes in case their `constructor` property has been tampered.
596+ const wellKnownPrototypes = new SafeMap ( ) ;
597+ wellKnownPrototypes . set ( ObjectPrototype , { name : 'Object' , constructor : Object } ) ;
598+ wellKnownPrototypes . set ( FunctionPrototype , { name : 'Function' , constructor : Function } ) ;
599+
591600function getConstructorName ( obj , ctx , recurseTimes , protoProps ) {
592601 let firstProto ;
593602 const tmp = obj ;
594603 while ( obj || isUndetectableObject ( obj ) ) {
604+ const wellKnownPrototypeNameAndConstructor = wellKnownPrototypes . get ( obj ) ;
605+ if ( wellKnownPrototypeNameAndConstructor != null ) {
606+ const { name, constructor } = wellKnownPrototypeNameAndConstructor ;
607+ if ( FunctionPrototypeSymbolHasInstance ( constructor , tmp ) ) {
608+ if ( protoProps !== undefined && firstProto !== obj ) {
609+ addPrototypeProperties (
610+ ctx , tmp , firstProto || tmp , recurseTimes , protoProps ) ;
611+ }
612+ return name ;
613+ }
614+ }
595615 const descriptor = ObjectGetOwnPropertyDescriptor ( obj , 'constructor' ) ;
596616 if ( descriptor !== undefined &&
597617 typeof descriptor . value === 'function' &&
@@ -949,7 +969,11 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
949969 if ( noIterator ) {
950970 keys = getKeys ( value , ctx . showHidden ) ;
951971 braces = [ '{' , '}' ] ;
952- if ( constructor === 'Object' ) {
972+ if ( typeof value === 'function' ) {
973+ base = getFunctionBase ( value , constructor , tag ) ;
974+ if ( keys . length === 0 && protoProps === undefined )
975+ return ctx . stylize ( base , 'special' ) ;
976+ } else if ( constructor === 'Object' ) {
953977 if ( isArgumentsObject ( value ) ) {
954978 braces [ 0 ] = '[Arguments] {' ;
955979 } else if ( tag !== '' ) {
@@ -958,10 +982,6 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
958982 if ( keys . length === 0 && protoProps === undefined ) {
959983 return `${ braces [ 0 ] } }` ;
960984 }
961- } else if ( typeof value === 'function' ) {
962- base = getFunctionBase ( value , constructor , tag ) ;
963- if ( keys . length === 0 && protoProps === undefined )
964- return ctx . stylize ( base , 'special' ) ;
965985 } else if ( isRegExp ( value ) ) {
966986 // Make RegExps say that they are RegExps
967987 base = RegExpPrototypeToString (
0 commit comments