Skip to content

Commit

Permalink
inspect: Limit maximum depth of printed objects
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanGoncharov committed Mar 15, 2019
1 parent 68058b2 commit ad35c41
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 9 deletions.
21 changes: 21 additions & 0 deletions src/jsutils/__tests__/inspect-test.js
Expand Up @@ -55,6 +55,9 @@ describe('inspect', () => {
expect(inspect([1, NaN])).to.equal('[1, NaN]');
expect(inspect([['a', 'b'], 'c'])).to.equal('[["a", "b"], "c"]');

expect(inspect([[[]]])).to.equal('[[[]]]');
expect(inspect([[['a']]])).to.equal('[[[Array]]]');

expect(inspect([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])).to.equal(
'[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]',
);
Expand All @@ -74,6 +77,9 @@ describe('inspect', () => {
expect(inspect({ a: 1, b: 2 })).to.equal('{ a: 1, b: 2 }');
expect(inspect({ array: [null, 0] })).to.equal('{ array: [null, 0] }');

expect(inspect({ a: { b: {} } })).to.equal('{ a: { b: {} } }');
expect(inspect({ a: { b: { c: 1 } } })).to.equal('{ a: { b: [Object] } }');

const map = Object.create(null);
map['a'] = true;
map['b'] = null;
Expand Down Expand Up @@ -125,4 +131,19 @@ describe('inspect', () => {

expect(inspect(object)).to.equal('Hello World!');
});

it('Use class names for the shortform of an object', () => {
class Foo {
foo: string;

constructor() {
this.foo = 'bar';
}
}

expect(inspect([[new Foo()]])).to.equal('[[[Foo]]]');

(Foo.prototype: any)[Symbol.toStringTag] = 'Bar';
expect(inspect([[new Foo()]])).to.equal('[[[Bar]]]');
});
});
43 changes: 34 additions & 9 deletions src/jsutils/inspect.js
Expand Up @@ -10,15 +10,16 @@
import nodejsCustomInspectSymbol from './nodejsCustomInspectSymbol';

const MAX_ARRAY_LENGTH = 10;
const MAX_RECURSIVE_DEPTH = 2;

/**
* Used to print values in error messages.
*/
export default function inspect(value: mixed): string {
return formatValue(value);
return formatValue(value, 0);
}

function formatValue(value) {
function formatValue(value, recurseTimes) {
switch (typeof value) {
case 'string':
return JSON.stringify(value);
Expand All @@ -33,12 +34,12 @@ function formatValue(value) {
const customValue = customInspectFn.call(value);
return typeof customValue === 'string'
? customValue
: formatValue(customValue);
: formatValue(customValue, recurseTimes);
} else if (Array.isArray(value)) {
return formatArray(value);
return formatArray(value, recurseTimes);
}

return formatObject(value);
return formatObject(value, recurseTimes);
}

return String(value);
Expand All @@ -47,31 +48,39 @@ function formatValue(value) {
}
}

function formatObject(object) {
function formatObject(object, recurseTimes) {
const keys = Object.keys(object);
if (keys.length === 0) {
return '{}';
}

if (recurseTimes === MAX_RECURSIVE_DEPTH) {
return '[' + getObjectTag(object) + ']';
}

const properties = keys.map(key => {
const value = formatValue(object[key]);
const value = formatValue(object[key], recurseTimes + 1);
return key + ': ' + value;
});

return '{ ' + properties.join(', ') + ' }';
}

function formatArray(array) {
function formatArray(array, recurseTimes) {
if (array.length === 0) {
return '[]';
}

if (recurseTimes === MAX_RECURSIVE_DEPTH) {
return '[Array]';
}

const len = Math.min(MAX_ARRAY_LENGTH, array.length);
const remaining = array.length - len;
const items = [];

for (let i = 0; i < len; ++i) {
items.push(formatValue(array[i]));
items.push(formatValue(array[i], recurseTimes + 1));
}

if (remaining === 1) {
Expand All @@ -94,3 +103,19 @@ function getCustomFn(object) {
return object.inspect;
}
}

function getObjectTag(object) {
const tag = Object.prototype.toString
.call(object)
.replace(/^\[object /, '')
.replace(/]$/, '');

if (tag === 'Object' && typeof object.constructor === 'function') {
const name = object.constructor.name;
if (typeof name === 'string') {
return name;
}
}

return tag;
}

0 comments on commit ad35c41

Please sign in to comment.