Skip to content

Commit

Permalink
util: fix iterable types with special prototype
Browse files Browse the repository at this point in the history
The fallback should only be taken for a null prototype. If an
iterable data type (e.g., Array) has a prototype without
`Symbol.iterator`, just try the best to visualize it as object.

Fixes: nodejs#25451
  • Loading branch information
BridgeAR committed Jan 16, 2019
1 parent 27f6d04 commit e00c69c
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 16 deletions.
28 changes: 12 additions & 16 deletions lib/internal/util/inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -463,28 +463,22 @@ function clazzWithNullPrototype(clazz, name) {
function noPrototypeIterator(ctx, value, recurseTimes) {
let newVal;
if (isSet(value)) {
const clazz = Object.getPrototypeOf(value) ||
clazzWithNullPrototype(Set, 'Set');
const clazz = clazzWithNullPrototype(Set, 'Set');
newVal = new clazz(setValues(value));
} else if (isMap(value)) {
const clazz = Object.getPrototypeOf(value) ||
clazzWithNullPrototype(Map, 'Map');
const clazz = clazzWithNullPrototype(Map, 'Map');
newVal = new clazz(mapEntries(value));
} else if (Array.isArray(value)) {
const clazz = Object.getPrototypeOf(value) ||
clazzWithNullPrototype(Array, 'Array');
const clazz = clazzWithNullPrototype(Array, 'Array');
newVal = new clazz(value.length);
} else if (isTypedArray(value)) {
let clazz = Object.getPrototypeOf(value);
if (!clazz) {
const constructor = findTypedConstructor(value);
clazz = clazzWithNullPrototype(constructor, constructor.name);
}
const constructor = findTypedConstructor(value);
const clazz = clazzWithNullPrototype(constructor, constructor.name);
newVal = new clazz(value);
}
if (newVal) {
if (newVal !== undefined) {
Object.defineProperties(newVal, Object.getOwnPropertyDescriptors(value));
return formatValue(ctx, newVal, recurseTimes);
return formatRaw(ctx, newVal, recurseTimes);
}
}

Expand Down Expand Up @@ -728,9 +722,11 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
} else {
// The input prototype got manipulated. Special handle these. We have to
// rebuild the information so we are able to display everything.
const specialIterator = noPrototypeIterator(ctx, value, recurseTimes);
if (specialIterator) {
return specialIterator;
if (constructor === null) {
const specialIterator = noPrototypeIterator(ctx, value, recurseTimes);
if (specialIterator) {
return specialIterator;
}
}
if (isMapIterator(value)) {
braces = [`[${tag || 'Map Iterator'}] {`, '}'];
Expand Down
10 changes: 10 additions & 0 deletions test/parallel/test-util-inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -1853,6 +1853,16 @@ assert.strictEqual(
util.inspect(new StorageObject()),
'<[Object: null prototype] {}> {}'
);

obj = [1, 2, 3];
Object.setPrototypeOf(obj, Number.prototype);
assert.strictEqual(inspect(obj), "Number { '0': 1, '1': 2, '2': 3 }");

Object.setPrototypeOf(obj, Object.create(null));
assert.strictEqual(
inspect(obj),
"<[Object: null prototype] {}> { '0': 1, '1': 2, '2': 3 }"
);
}

// Check that the fallback always works.
Expand Down

0 comments on commit e00c69c

Please sign in to comment.