Skip to content

Commit 82b8355

Browse files
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 <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Michaël Zasso <[email protected]>
1 parent 2fb34b6 commit 82b8355

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
@@ -198,6 +198,7 @@ function ensureDebugIsInitialized() {
198198

199199
function inspectPromise(p) {
200200
ensureDebugIsInitialized();
201+
// Only create a mirror if the object is a Promise.
201202
if (!binding.isPromise(p))
202203
return null;
203204
const mirror = Debug.MakeMirror(p, true);
@@ -299,16 +300,19 @@ function formatValue(ctx, value, recurseTimes) {
299300
var base = '', empty = false, braces;
300301
var formatter = formatObject;
301302

303+
// We can't compare constructors for various objects using a comparison like
304+
// `constructor === Array` because the object could have come from a different
305+
// context and thus the constructor won't match. Instead we check the
306+
// constructor names (including those up the prototype chain where needed) to
307+
// determine object types.
302308
if (Array.isArray(value)) {
303-
// We can't use `constructor === Array` because this could
304-
// have come from a Debug context.
305-
// Otherwise, an Array will print "Array [...]".
309+
// Unset the constructor to prevent "Array [...]" for ordinary arrays.
306310
if (constructor && constructor.name === 'Array')
307311
constructor = null;
308312
braces = ['[', ']'];
309313
empty = value.length === 0;
310314
formatter = formatArray;
311-
} else if (value instanceof Set) {
315+
} else if (objectToString(value) === '[object Set]') {
312316
braces = ['{', '}'];
313317
// With `showHidden`, `length` will display as a hidden property for
314318
// arrays. For consistency's sake, do the same for `size`, even though this
@@ -317,7 +321,7 @@ function formatValue(ctx, value, recurseTimes) {
317321
keys.unshift('size');
318322
empty = value.size === 0;
319323
formatter = formatSet;
320-
} else if (value instanceof Map) {
324+
} else if (objectToString(value) === '[object Map]') {
321325
braces = ['{', '}'];
322326
// Ditto.
323327
if (ctx.showHidden)
@@ -347,8 +351,7 @@ function formatValue(ctx, value, recurseTimes) {
347351
'buffer');
348352
}
349353
} else {
350-
// Only create a mirror if the object superficially looks like a Promise.
351-
var promiseInternals = value instanceof Promise && inspectPromise(value);
354+
var promiseInternals = inspectPromise(value);
352355
if (promiseInternals) {
353356
braces = ['{', '}'];
354357
formatter = formatPromise;
@@ -364,7 +367,8 @@ function formatValue(ctx, value, recurseTimes) {
364367
empty = false;
365368
formatter = formatCollectionIterator;
366369
} else {
367-
if (constructor === Object)
370+
// Unset the constructor to prevent "Object {...}" for ordinary objects.
371+
if (constructor && constructor.name === 'Object')
368372
constructor = null;
369373
braces = ['{', '}'];
370374
empty = true; // No other data than keys.

test/parallel/test-util-inspect.js

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

195195
assert.strictEqual(util.inspect(valsOutput), '[ [ 1, 2 ] ]');
196196

197+
// test for other constructors in different context
198+
var obj = require('vm').runInNewContext('(function(){return {}})()', {});
199+
assert.strictEqual(util.inspect(obj), '{}');
200+
obj = require('vm').runInNewContext('var m=new Map();m.set(1,2);m', {});
201+
assert.strictEqual(util.inspect(obj), 'Map { 1 => 2 }');
202+
obj = require('vm').runInNewContext('var s=new Set();s.add(1);s.add(2);s', {});
203+
assert.strictEqual(util.inspect(obj), 'Set { 1, 2 }');
204+
obj = require('vm').runInNewContext('fn=function(){};new Promise(fn,fn)', {});
205+
assert.strictEqual(util.inspect(obj), 'Promise { <pending> }');
206+
197207
// test for property descriptors
198208
var getter = Object.create(null, {
199209
a: {

0 commit comments

Comments
 (0)