@@ -22,8 +22,11 @@ const {
22
22
DatePrototypeToISOString,
23
23
DatePrototypeToString,
24
24
ErrorPrototypeToString,
25
+ Function,
26
+ FunctionPrototype,
25
27
FunctionPrototypeBind,
26
28
FunctionPrototypeCall,
29
+ FunctionPrototypeSymbolHasInstance,
27
30
FunctionPrototypeToString,
28
31
JSONStringify,
29
32
MapPrototypeEntries,
@@ -50,6 +53,7 @@ const {
50
53
ObjectGetPrototypeOf,
51
54
ObjectIs,
52
55
ObjectKeys,
56
+ ObjectPrototype,
53
57
ObjectPrototypeHasOwnProperty,
54
58
ObjectPrototypePropertyIsEnumerable,
55
59
ObjectSeal,
@@ -593,10 +597,26 @@ function isInstanceof(object, proto) {
593
597
}
594
598
}
595
599
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
+
596
605
function getConstructorName ( obj , ctx , recurseTimes , protoProps ) {
597
606
let firstProto ;
598
607
const tmp = obj ;
599
608
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
+ }
600
620
const descriptor = ObjectGetOwnPropertyDescriptor ( obj , 'constructor' ) ;
601
621
if ( descriptor !== undefined &&
602
622
typeof descriptor . value === 'function' &&
@@ -954,7 +974,11 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
954
974
if ( noIterator ) {
955
975
keys = getKeys ( value , ctx . showHidden ) ;
956
976
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' ) {
958
982
if ( isArgumentsObject ( value ) ) {
959
983
braces [ 0 ] = '[Arguments] {' ;
960
984
} else if ( tag !== '' ) {
@@ -963,10 +987,6 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
963
987
if ( keys . length === 0 && protoProps === undefined ) {
964
988
return `${ braces [ 0 ] } }` ;
965
989
}
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' ) ;
970
990
} else if ( isRegExp ( value ) ) {
971
991
// Make RegExps say that they are RegExps
972
992
base = RegExpPrototypeToString (
0 commit comments