diff --git a/doc/api.txt b/doc/api.txt index c61564eb79..f173a9e2e2 100644 --- a/doc/api.txt +++ b/doc/api.txt @@ -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)+:: diff --git a/lib/sys.js b/lib/sys.js index 8d5404b048..9c05342e48 100644 --- a/lib/sys.js +++ b/lib/sys.js @@ -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; } @@ -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)) { @@ -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]'; @@ -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 () { diff --git a/test/simple/test-sys.js b/test/simple/test-sys.js index 5236fb7eb0..06fd6943e0 100644 --- a/test/simple/test-sys.js +++ b/test/simple/test-sys.js @@ -4,8 +4,8 @@ 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)); @@ -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', 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) ); @@ -72,7 +82,7 @@ assert.equal( value = function () {}; value.aprop = 42; assert.equal( - "{ [Function]\n \"aprop\": 42\n}", + "{ [Function] aprop: 42 }", inspect(value) ); @@ -80,7 +90,7 @@ assert.equal( value = /123/ig; value.aprop = 42; assert.equal( - "{ /123/gi\n \"aprop\": 42\n}", + "{ /123/gi aprop: 42 }", inspect(value) ); @@ -88,6 +98,6 @@ assert.equal( 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) );