Skip to content

Commit 2d5380e

Browse files
mscdexMyles Borins
authored and
Myles Borins
committed
util: fix constructor/instanceof checks
These new checks are similar to the one introduced in 089d688, but for other types of objects. Specifically, if an object was created in a different context, the constructor object will not be the same as the constructor object in the current context, so we have to compare constructor names instead. PR-URL: #3385 Reviewed-By: Evan Lucas <evanlucas@me.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Michaël Zasso <mic.besace@gmail.com>
1 parent b9c6996 commit 2d5380e

File tree

2 files changed

+22
-8
lines changed

2 files changed

+22
-8
lines changed

lib/util.js

+12-8
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ function ensureDebugIsInitialized() {
195195

196196
function inspectPromise(p) {
197197
ensureDebugIsInitialized();
198+
// Only create a mirror if the object is a Promise.
198199
if (!binding.isPromise(p))
199200
return null;
200201
const mirror = Debug.MakeMirror(p, true);
@@ -289,16 +290,19 @@ function formatValue(ctx, value, recurseTimes) {
289290
var constructor = getConstructorOf(value);
290291
var base = '', empty = false, braces, formatter;
291292

293+
// We can't compare constructors for various objects using a comparison like
294+
// `constructor === Array` because the object could have come from a different
295+
// context and thus the constructor won't match. Instead we check the
296+
// constructor names (including those up the prototype chain where needed) to
297+
// determine object types.
292298
if (Array.isArray(value)) {
293-
// We can't use `constructor === Array` because this could
294-
// have come from a Debug context.
295-
// Otherwise, an Array will print "Array [...]".
299+
// Unset the constructor to prevent "Array [...]" for ordinary arrays.
296300
if (constructor && constructor.name === 'Array')
297301
constructor = null;
298302
braces = ['[', ']'];
299303
empty = value.length === 0;
300304
formatter = formatArray;
301-
} else if (value instanceof Set) {
305+
} else if (objectToString(value) === '[object Set]') {
302306
braces = ['{', '}'];
303307
// With `showHidden`, `length` will display as a hidden property for
304308
// arrays. For consistency's sake, do the same for `size`, even though this
@@ -307,16 +311,15 @@ function formatValue(ctx, value, recurseTimes) {
307311
keys.unshift('size');
308312
empty = value.size === 0;
309313
formatter = formatSet;
310-
} else if (value instanceof Map) {
314+
} else if (objectToString(value) === '[object Map]') {
311315
braces = ['{', '}'];
312316
// Ditto.
313317
if (ctx.showHidden)
314318
keys.unshift('size');
315319
empty = value.size === 0;
316320
formatter = formatMap;
317321
} else {
318-
// Only create a mirror if the object superficially looks like a Promise.
319-
var promiseInternals = value instanceof Promise && inspectPromise(value);
322+
var promiseInternals = inspectPromise(value);
320323
if (promiseInternals) {
321324
braces = ['{', '}'];
322325
formatter = formatPromise;
@@ -332,7 +335,8 @@ function formatValue(ctx, value, recurseTimes) {
332335
empty = false;
333336
formatter = formatCollectionIterator;
334337
} else {
335-
if (constructor === Object)
338+
// Unset the constructor to prevent "Object {...}" for ordinary objects.
339+
if (constructor && constructor.name === 'Object')
336340
constructor = null;
337341
braces = ['{', '}'];
338342
empty = true; // No other data than keys.

test/parallel/test-util-inspect.js

+10
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,16 @@ for (const o of vals) {
141141

142142
assert.strictEqual(util.inspect(valsOutput), '[ [ 1, 2 ] ]');
143143

144+
// test for other constructors in different context
145+
var obj = require('vm').runInNewContext('(function(){return {}})()', {});
146+
assert.strictEqual(util.inspect(obj), '{}');
147+
obj = require('vm').runInNewContext('var m=new Map();m.set(1,2);m', {});
148+
assert.strictEqual(util.inspect(obj), 'Map { 1 => 2 }');
149+
obj = require('vm').runInNewContext('var s=new Set();s.add(1);s.add(2);s', {});
150+
assert.strictEqual(util.inspect(obj), 'Set { 1, 2 }');
151+
obj = require('vm').runInNewContext('fn=function(){};new Promise(fn,fn)', {});
152+
assert.strictEqual(util.inspect(obj), 'Promise { <pending> }');
153+
144154
// test for property descriptors
145155
var getter = Object.create(null, {
146156
a: {

0 commit comments

Comments
 (0)