Browse Source

Make the output of sys.inspect a lot more compact.

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.
v0.7.4-release
Benjamin Thomas 15 years ago
committed by Ryan Dahl
parent
commit
de1521413e
  1. 3
      doc/api.txt
  2. 48
      lib/sys.js
  3. 60
      test/simple/test-sys.js

3
doc/api.txt

@ -222,7 +222,8 @@ shown too.
+ +
If +depth+ is provided, it tells +inspect+ how many times to recurse while If +depth+ is provided, it tells +inspect+ how many times to recurse while
formatting the object. This is useful for inspecting large complicated objects. 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)+:: +exec(command, callback)+::

48
lib/sys.js

@ -35,7 +35,7 @@ exports.inspect = function (obj, showHidden, depth) {
// Primitive types cannot have properties // Primitive types cannot have properties
switch (typeof value) { switch (typeof value) {
case 'undefined': return 'undefined'; 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 'number': return '' + value;
case 'boolean': return '' + value; case 'boolean': return '' + value;
} }
@ -95,7 +95,15 @@ exports.inspect = function (obj, showHidden, depth) {
return braces[0] + base + braces[1]; 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; var name, str;
if (value.__lookupGetter__) { if (value.__lookupGetter__) {
if (value.__lookupGetter__(key)) { if (value.__lookupGetter__(key)) {
@ -115,14 +123,16 @@ exports.inspect = function (obj, showHidden, depth) {
} }
if (!str) { if (!str) {
if (seen.indexOf(value[key]) < 0) { if (seen.indexOf(value[key]) < 0) {
if (typeof recurseTimes === 'undefined' || recurseTimes === null) { if ( recurseTimes === null) {
str = format(value[key]); str = format(value[key]);
} }
else if (recurseTimes > 0) { else {
str = format(value[key], recurseTimes - 1); str = format(value[key], recurseTimes - 1);
} }
else { if( str.indexOf('\n') > -1 ) {
str = value[key]; str = '\n' + str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n');
} }
} else { } else {
str = '[Circular]'; str = '[Circular]';
@ -133,14 +143,32 @@ exports.inspect = function (obj, showHidden, depth) {
return str; return str;
} }
name = JSON.stringify('' + key); 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; 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 () { exports.p = function () {

60
test/simple/test-sys.js

@ -4,8 +4,8 @@ process.mixin(require("sys"));
assert.equal("0", inspect(0)); assert.equal("0", inspect(0));
assert.equal("1", inspect(1)); assert.equal("1", inspect(1));
assert.equal("false", inspect(false)); assert.equal("false", inspect(false));
assert.equal('""', inspect("")); assert.equal("''", inspect(""));
assert.equal('"hello"', inspect("hello")); assert.equal("'hello'", inspect("hello"));
assert.equal("[Function]", inspect(function() {})); assert.equal("[Function]", inspect(function() {}));
assert.equal('undefined', inspect(undefined)); assert.equal('undefined', inspect(undefined));
assert.equal('null', inspect(null)); assert.equal('null', inspect(null));
@ -13,58 +13,68 @@ assert.equal('/foo(bar\\n)?/gi', inspect(/foo(bar\n)?/gi));
assert.equal('Sun, 14 Feb 2010 11:48:40 GMT', assert.equal('Sun, 14 Feb 2010 11:48:40 GMT',
inspect(new Date("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([]));
assert.equal('[]', inspect(Object.create([]))); assert.equal('[]', inspect(Object.create([])));
assert.equal('[\n 1,\n 2\n]', inspect([1, 2])); assert.equal('[ 1, 2 ]', inspect([1, 2]));
assert.equal('[\n 1,\n [\n 2,\n 3\n ]\n]', inspect([1, [2, 3]])); assert.equal('[ 1, [ 2, 3 ] ]', inspect([1, [2, 3]]));
assert.equal('{}', inspect({})); assert.equal('{}', inspect({}));
assert.equal('{\n "a": 1\n}', inspect({a: 1})); assert.equal('{ a: 1 }', inspect({a: 1}));
assert.equal('{\n "a": [Function]\n}', inspect({a: function() {}})); assert.equal('{ a: [Function] }', inspect({a: function() {}}));
assert.equal('{\n "a": 1,\n "b": 2\n}', inspect({a: 1, b: 2})); assert.equal('{ a: 1, b: 2 }', inspect({a: 1, b: 2}));
assert.equal('{\n "a": {}\n}', inspect({'a': {}})); assert.equal('{ a: {} }', inspect({'a': {}}));
assert.equal('{\n "a": {\n "b": 2\n }\n}', inspect({'a': {'b': 2}})); assert.equal('{ a: { b: 2 } }', inspect({'a': {'b': 2}}));
assert.equal('[\n 1,\n 2,\n 3,\n [length]: 3\n]', inspect([1,2,3], true)); assert.equal('{ a: { b: { c: [object Object] } } }', inspect({'a': {'b': { 'c': { 'd': 2 }}}}));
assert.equal('{\n \"a\": [object Object]\n}', inspect({'a': {'b': { 'c': 2}}},false,0)); assert.equal('{ a: { b: { c: { d: 2 } } } }', inspect({'a': {'b': { 'c': { 'd': 2 }}}}, false, null));
assert.equal('{\n \"a\": {\n \"b\": [object Object]\n }\n}', inspect({'a': {'b': { 'c': 2}}},false,1)); assert.equal('[ 1, 2, 3, [length]: 3 ]', inspect([1,2,3], true));
assert.equal("{\n \"visible\": 1\n}", 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}})) 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) inspect(Object.create({}, {visible:{value:1,enumerable:true},hidden:{value:2}}), true)
); );
// Objects without prototype // Objects without prototype
assert.equal( 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) inspect(Object.create(null, {name: {value: "Tim", enumerable: true}, hidden: {value: "secret"}}), true)
); );
assert.equal( assert.equal(
"{\n \"name\": \"Tim\"\n}", "{ name: 'Tim' }",
inspect(Object.create(null, {name: {value: "Tim", enumerable: true}, hidden: {value: "secret"}})) inspect(Object.create(null, {name: {value: "Tim", enumerable: true}, hidden: {value: "secret"}}))
); );
// Dynamic properties // Dynamic properties
assert.equal( assert.equal(
"{\n \"readonly\": [Getter],\n \"readwrite\": [Getter/Setter],\n \"writeonly\": [Setter]\n}", "{ readonly: [Getter] }",
inspect({get readonly(){},get readwrite(){},set readwrite(val){},set writeonly(val){}}) inspect({get readonly(){}})
);
assert.equal(
"{ readwrite: [Getter/Setter] }",
inspect({get readwrite(){},set readwrite(val){}})
);
assert.equal(
"{ writeonly: [Setter] }",
inspect({set writeonly(val){}})
); );
var value = {}; var value = {};
value['a'] = value; value['a'] = value;
assert.equal('{\n "a": [Circular]\n}', inspect(value)); assert.equal('{ a: [Circular] }', inspect(value));
value = Object.create([]); value = Object.create([]);
value.push(1); value.push(1);
assert.equal("[\n 1,\n \"length\": 1\n]", inspect(value)); assert.equal("[ 1, length: 1 ]", inspect(value));
// Array with dynamic properties // Array with dynamic properties
value = [1,2,3]; value = [1,2,3];
value.__defineGetter__('growingLength', function () { this.push(true); return this.length; }); value.__defineGetter__('growingLength', function () { this.push(true); return this.length; });
assert.equal( assert.equal(
"[\n 1,\n 2,\n 3,\n \"growingLength\": [Getter]\n]", "[ 1, 2, 3, growingLength: [Getter] ]",
inspect(value) inspect(value)
); );
@ -72,7 +82,7 @@ assert.equal(
value = function () {}; value = function () {};
value.aprop = 42; value.aprop = 42;
assert.equal( assert.equal(
"{ [Function]\n \"aprop\": 42\n}", "{ [Function] aprop: 42 }",
inspect(value) inspect(value)
); );
@ -80,7 +90,7 @@ assert.equal(
value = /123/ig; value = /123/ig;
value.aprop = 42; value.aprop = 42;
assert.equal( assert.equal(
"{ /123/gi\n \"aprop\": 42\n}", "{ /123/gi aprop: 42 }",
inspect(value) inspect(value)
); );
@ -88,6 +98,6 @@ assert.equal(
value = new Date("Sun, 14 Feb 2010 11:48:40 GMT"); value = new Date("Sun, 14 Feb 2010 11:48:40 GMT");
value.aprop = 42; value.aprop = 42;
assert.equal( 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) inspect(value)
); );

Loading…
Cancel
Save