Skip to content

Commit

Permalink
Make the output of sys.inspect a lot more compact.
Browse files Browse the repository at this point in the history
See:
http://groups.google.com/group/nodejs/browse_thread/thread/ac060521e27fef65

By default now, sys.inspect doesn't recurse more than two times.  Pass
in null as the third parameter to make it recurse indefinitely.
  • Loading branch information
Benjamin Thomas authored and ry committed Feb 26, 2010
1 parent a2714be commit de15214
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 36 deletions.
3 changes: 2 additions & 1 deletion doc/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ shown too.
+
If +depth+ is provided, it tells +inspect+ how many times to recurse while
formatting the object. This is useful for inspecting large complicated objects.
The defualt is to recurse indefinitely.
The default is to only recurse twice. To make it recurse indefinitely, pass
in +null+ for +depth+.


+exec(command, callback)+::
Expand Down
48 changes: 38 additions & 10 deletions lib/sys.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ exports.inspect = function (obj, showHidden, depth) {
// Primitive types cannot have properties
switch (typeof value) {
case 'undefined': return 'undefined';
case 'string': return JSON.stringify(value);
case 'string': return JSON.stringify(value).replace(/'/g, "\\'").replace(/\\"/g, '"').replace(/(^"|"$)/g, "'");
case 'number': return '' + value;
case 'boolean': return '' + value;
}
Expand Down Expand Up @@ -95,7 +95,15 @@ exports.inspect = function (obj, showHidden, depth) {
return braces[0] + base + braces[1];
}

return braces[0] + base + "\n" + (keys.map(function (key) {
if( recurseTimes < 0 ) {
if (value instanceof RegExp) {
return '' + value;
} else {
return "[object Object]";
}
}

output = keys.map(function (key) {
var name, str;
if (value.__lookupGetter__) {
if (value.__lookupGetter__(key)) {
Expand All @@ -115,14 +123,16 @@ exports.inspect = function (obj, showHidden, depth) {
}
if (!str) {
if (seen.indexOf(value[key]) < 0) {
if (typeof recurseTimes === 'undefined' || recurseTimes === null) {
if ( recurseTimes === null) {
str = format(value[key]);
}
else if (recurseTimes > 0) {
else {
str = format(value[key], recurseTimes - 1);
}
else {
str = value[key];
if( str.indexOf('\n') > -1 ) {
str = '\n' + str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n');
}
} else {
str = '[Circular]';
Expand All @@ -133,14 +143,32 @@ exports.inspect = function (obj, showHidden, depth) {
return str;
}
name = JSON.stringify('' + key);
if( name.match(/^"([a-zA-Z_0-9]+)"$/) ) {
name = name.substr(1, name.length-2);
}
else {
name = name.replace(/'/g, "\\'").replace(/\\"/g, '"').replace(/(^"|"$)/g, "'");
}
}

return name + ": " + str;
}).join(",\n")).split("\n").map(function (line) {
return ' ' + line;
}).join('\n') + "\n" + braces[1];
});


var length = output.reduce(function(prev, cur) {
return prev + cur.length + 1;
},0);

if( length > 50 ) {
output = braces[0] + (base === '' ? '' : base + '\n,') + ' ' + output.join('\n, ') + '\n' +braces[1];
}
else {
output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}

return output;
}
return format(obj, depth);
return format(obj, (typeof depth === 'undefined' ? 2 : depth));
};

exports.p = function () {
Expand Down
60 changes: 35 additions & 25 deletions test/simple/test-sys.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,90 +4,100 @@ process.mixin(require("sys"));
assert.equal("0", inspect(0));
assert.equal("1", inspect(1));
assert.equal("false", inspect(false));
assert.equal('""', inspect(""));
assert.equal('"hello"', inspect("hello"));
assert.equal("''", inspect(""));
assert.equal("'hello'", inspect("hello"));
assert.equal("[Function]", inspect(function() {}));
assert.equal('undefined', inspect(undefined));
assert.equal('null', inspect(null));
assert.equal('/foo(bar\\n)?/gi', inspect(/foo(bar\n)?/gi));
assert.equal('Sun, 14 Feb 2010 11:48:40 GMT',
inspect(new Date("Sun, 14 Feb 2010 11:48:40 GMT")));

assert.equal("\"\\n\\u0001\"", inspect("\n\u0001"));
assert.equal("'\\n\\u0001'", inspect("\n\u0001"));

assert.equal('[]', inspect([]));
assert.equal('[]', inspect(Object.create([])));
assert.equal('[\n 1,\n 2\n]', inspect([1, 2]));
assert.equal('[\n 1,\n [\n 2,\n 3\n ]\n]', inspect([1, [2, 3]]));
assert.equal('[ 1, 2 ]', inspect([1, 2]));
assert.equal('[ 1, [ 2, 3 ] ]', inspect([1, [2, 3]]));

assert.equal('{}', inspect({}));
assert.equal('{\n "a": 1\n}', inspect({a: 1}));
assert.equal('{\n "a": [Function]\n}', inspect({a: function() {}}));
assert.equal('{\n "a": 1,\n "b": 2\n}', inspect({a: 1, b: 2}));
assert.equal('{\n "a": {}\n}', inspect({'a': {}}));
assert.equal('{\n "a": {\n "b": 2\n }\n}', inspect({'a': {'b': 2}}));
assert.equal('[\n 1,\n 2,\n 3,\n [length]: 3\n]', inspect([1,2,3], true));
assert.equal('{\n \"a\": [object Object]\n}', inspect({'a': {'b': { 'c': 2}}},false,0));
assert.equal('{\n \"a\": {\n \"b\": [object Object]\n }\n}', inspect({'a': {'b': { 'c': 2}}},false,1));
assert.equal("{\n \"visible\": 1\n}",
assert.equal('{ a: 1 }', inspect({a: 1}));
assert.equal('{ a: [Function] }', inspect({a: function() {}}));
assert.equal('{ a: 1, b: 2 }', inspect({a: 1, b: 2}));
assert.equal('{ a: {} }', inspect({'a': {}}));
assert.equal('{ a: { b: 2 } }', inspect({'a': {'b': 2}}));
assert.equal('{ a: { b: { c: [object Object] } } }', inspect({'a': {'b': { 'c': { 'd': 2 }}}}));
assert.equal('{ a: { b: { c: { d: 2 } } } }', inspect({'a': {'b': { 'c': { 'd': 2 }}}}, false, null));
assert.equal('[ 1, 2, 3, [length]: 3 ]', inspect([1,2,3], true));
assert.equal('{ a: [object Object] }', inspect({'a': {'b': { 'c': 2}}},false,0));
assert.equal('{ a: { b: [object Object] } }', inspect({'a': {'b': { 'c': 2}}},false,1));
assert.equal("{ visible: 1 }",
inspect(Object.create({}, {visible:{value:1,enumerable:true},hidden:{value:2}}))
);
assert.equal("{\n [hidden]: 2,\n \"visible\": 1\n}",
assert.equal("{ [hidden]: 2, visible: 1 }",
inspect(Object.create({}, {visible:{value:1,enumerable:true},hidden:{value:2}}), true)
);

// Objects without prototype
assert.equal(
"{\n [hidden]: \"secret\",\n \"name\": \"Tim\"\n}",
"{ [hidden]: 'secret', name: 'Tim' }",
inspect(Object.create(null, {name: {value: "Tim", enumerable: true}, hidden: {value: "secret"}}), true)
);
assert.equal(
"{\n \"name\": \"Tim\"\n}",
"{ name: 'Tim' }",
inspect(Object.create(null, {name: {value: "Tim", enumerable: true}, hidden: {value: "secret"}}))
);


// Dynamic properties
assert.equal(
"{\n \"readonly\": [Getter],\n \"readwrite\": [Getter/Setter],\n \"writeonly\": [Setter]\n}",
inspect({get readonly(){},get readwrite(){},set readwrite(val){},set writeonly(val){}})
"{ readonly: [Getter] }",
inspect({get readonly(){}})
);
assert.equal(
"{ readwrite: [Getter/Setter] }",
inspect({get readwrite(){},set readwrite(val){}})
);
assert.equal(
"{ writeonly: [Setter] }",
inspect({set writeonly(val){}})
);

var value = {};
value['a'] = value;
assert.equal('{\n "a": [Circular]\n}', inspect(value));
assert.equal('{ a: [Circular] }', inspect(value));
value = Object.create([]);
value.push(1);
assert.equal("[\n 1,\n \"length\": 1\n]", inspect(value));
assert.equal("[ 1, length: 1 ]", inspect(value));

// Array with dynamic properties
value = [1,2,3];
value.__defineGetter__('growingLength', function () { this.push(true); return this.length; });
assert.equal(
"[\n 1,\n 2,\n 3,\n \"growingLength\": [Getter]\n]",
"[ 1, 2, 3, growingLength: [Getter] ]",
inspect(value)
);

// Function with properties
value = function () {};
value.aprop = 42;
assert.equal(
"{ [Function]\n \"aprop\": 42\n}",
"{ [Function] aprop: 42 }",
inspect(value)
);

// Regular expressions with properties
value = /123/ig;
value.aprop = 42;
assert.equal(
"{ /123/gi\n \"aprop\": 42\n}",
"{ /123/gi aprop: 42 }",
inspect(value)
);

// Dates with properties
value = new Date("Sun, 14 Feb 2010 11:48:40 GMT");
value.aprop = 42;
assert.equal(
"{ Sun, 14 Feb 2010 11:48:40 GMT\n \"aprop\": 42\n}",
"{ Sun, 14 Feb 2010 11:48:40 GMT aprop: 42 }",
inspect(value)
);

0 comments on commit de15214

Please sign in to comment.