@@ -8,6 +8,7 @@ var setSize = hasSet && setSizeDescriptor && typeof setSizeDescriptor.get === 'f
88var setForEach = hasSet && Set . prototype . forEach ;
99var booleanValueOf = Boolean . prototype . valueOf ;
1010var objectToString = Object . prototype . toString ;
11+ var getPrototype = Object . getPrototypeOf || function ( o ) { return o . __proto__ ; } ;
1112
1213var inspectCustom = require ( './util.inspect' ) . custom ;
1314var inspectSymbol = ( inspectCustom && isSymbol ( inspectCustom ) ) ? inspectCustom : null ;
@@ -112,9 +113,12 @@ module.exports = function inspect_ (obj, opts, depth, seen) {
112113 return markBoxed ( inspect ( String ( obj ) ) ) ;
113114 }
114115 if ( ! isDate ( obj ) && ! isRegExp ( obj ) ) {
116+ var typeString = getTypeString ( obj ) ;
117+ var prefix = typeString ? typeString + ' ' : '' ;
115118 var xs = arrObjKeys ( obj , inspect ) ;
116- if ( xs . length === 0 ) return '{}' ;
117- return '{ ' + xs . join ( ', ' ) + ' }' ;
119+ return xs . length === 0
120+ ? prefix + '{}'
121+ : prefix + '{ ' + xs . join ( ', ' ) + ' }' ;
118122 }
119123 return String ( obj ) ;
120124} ;
@@ -237,3 +241,34 @@ function arrObjKeys (obj, inspect) {
237241 }
238242 return xs ;
239243}
244+
245+ // Returns the object's constructor name or null if it is a plain object
246+ // or doesn't have a prototype.
247+ function getTypeString ( o ) {
248+ if ( Object . prototype . toString ( o ) !== '[object Object]' ) return null ;
249+ var prototype = getPrototype ( o ) ;
250+ if ( ! prototype ) return null ;
251+
252+ var constructorName = o . constructor ? o . constructor . name : null ;
253+ var isPlainObject = constructorName === 'Object' && looksLikeObjectPrototype ( prototype ) ;
254+ if ( isPlainObject ) {
255+ return null ;
256+ }
257+
258+ return constructorName ;
259+ }
260+
261+ // Indicates whether the specified object appears to be Object.prototype,
262+ // regardless of the object's realm.
263+ function looksLikeObjectPrototype ( o ) {
264+ if ( o === Object . prototype ) return true ;
265+
266+ // Cross-realm objects use a different Object, so we have to use a heuristic.
267+ return ! getPrototype ( o )
268+ && o . hasOwnProperty ( 'hasOwnProperty' )
269+ && o . hasOwnProperty ( 'isPrototypeOf' )
270+ && o . hasOwnProperty ( 'propertyIsEnumerable' )
271+ && o . hasOwnProperty ( 'toLocaleString' )
272+ && o . hasOwnProperty ( 'toString' )
273+ && o . hasOwnProperty ( 'valueOf' ) ;
274+ }
0 commit comments