@@ -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
MapPrototypeGetSize,
@@ -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,
@@ -588,10 +592,26 @@ function isInstanceof(object, proto) {
588
592
}
589
593
}
590
594
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
+
591
600
function getConstructorName ( obj , ctx , recurseTimes , protoProps ) {
592
601
let firstProto ;
593
602
const tmp = obj ;
594
603
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
+ }
595
615
const descriptor = ObjectGetOwnPropertyDescriptor ( obj , 'constructor' ) ;
596
616
if ( descriptor !== undefined &&
597
617
typeof descriptor . value === 'function' &&
@@ -949,7 +969,11 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
949
969
if ( noIterator ) {
950
970
keys = getKeys ( value , ctx . showHidden ) ;
951
971
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' ) {
953
977
if ( isArgumentsObject ( value ) ) {
954
978
braces [ 0 ] = '[Arguments] {' ;
955
979
} else if ( tag !== '' ) {
@@ -958,10 +982,6 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
958
982
if ( keys . length === 0 && protoProps === undefined ) {
959
983
return `${ braces [ 0 ] } }` ;
960
984
}
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' ) ;
965
985
} else if ( isRegExp ( value ) ) {
966
986
// Make RegExps say that they are RegExps
967
987
base = RegExpPrototypeToString (
0 commit comments