Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Shay <xavier@rhnh.net>2009-12-01 13:20:14 +0300
committerRyan Dahl <ry@tinyclouds.org>2009-12-06 14:19:23 +0300
commit34c02357ff8e00c35e493754943f599dba0b0f29 (patch)
tree7003b983dbf541015b0273a5f01f6666bebe129e
parent4d818f1fd3454f972ef6e0a4f32ed26585804dd5 (diff)
sys.inspect is totally more awesome now
- No longer relies on JSON.stringify, so it can output nulls and functions - Handles circular references better - Has tests
-rw-r--r--lib/sys.js84
-rw-r--r--test/mjsunit/test-sys.js26
2 files changed, 90 insertions, 20 deletions
diff --git a/lib/sys.js b/lib/sys.js
index f755d71638f..9c4dc6d944b 100644
--- a/lib/sys.js
+++ b/lib/sys.js
@@ -17,26 +17,11 @@ exports.error = function (x) {
/**
* Echos the value of a value. Trys to print the value out
* in the best way possible given the different types.
- *
+ *
* @param {Object} value The object to print out
*/
exports.inspect = function (value) {
- if (value === 0) return "0";
- if (value === false) return "false";
- if (value === "") return '""';
- if (typeof(value) == "function") return "[Function]";
- if (value === undefined) return;
-
- try {
- return JSON.stringify(value, undefined, 1);
- } catch (e) {
- // TODO make this recusrive and do a partial JSON output of object.
- if (e.message.search("circular")) {
- return "[Circular Object]";
- } else {
- throw e;
- }
- }
+ return formatter(value, '', []);
};
exports.p = function (x) {
@@ -50,13 +35,13 @@ exports.exec = function (command) {
var promise = new process.Promise();
child.addListener("output", function (chunk) {
- if (chunk) stdout += chunk;
+ if (chunk) stdout += chunk;
});
child.addListener("error", function (chunk) {
- if (chunk) stderr += chunk;
+ if (chunk) stderr += chunk;
});
-
+
child.addListener("exit", function (code) {
if (code == 0) {
promise.emitSuccess(stdout, stderr);
@@ -82,3 +67,62 @@ exports.exec = function (command) {
* @param {function} superCtor Constructor function to inherit prototype from
*/
exports.inherits = process.inherits;
+
+/**
+ * A recursive function to format an object - used by inspect.
+ *
+ * @param {Object} value
+ * the value to format
+ * @param {String} indent
+ * the indent level of any nested objects, since they are formatted over
+ * more than one line
+ * @param {Array} parents
+ * contains all objects above the current one in the heirachy, used to
+ * prevent getting stuck in a loop on circular references
+ */
+var formatter = function(value, indent, parents) {
+ switch(typeof(value)) {
+ case 'string': return '"' + value + '"';
+ case 'number': return '' + value;
+ case 'function': return '[Function]';
+ case 'boolean': return '' + value;
+ case 'undefined': return 'undefined';
+ case 'object':
+ if (value == null) return 'null';
+ if (parents.indexOf(value) >= 0) return '[Circular]';
+ parents.push(value);
+
+ if (value instanceof Array) {
+ return formatObject(value, indent, parents, '[]', function(x, f) {
+ return f(value[x]);
+ });
+ } else {
+ return formatObject(value, indent, parents, '{}', function(x, f) {
+ return f(x) + ': ' + f(value[x]);
+ });
+ }
+ return buffer;
+ default:
+ throw('inspect unimplemented for ' + typeof(value));
+ }
+}
+
+/**
+ * Helper function for formatting either an array or an object, used internally by formatter
+ */
+var formatObject = function(obj, indent, parents, parenthesis, entryFormatter) {
+ var buffer = parenthesis[0];
+ var values = [];
+
+ var localFormatter = function(value) {
+ return formatter(value, indent + ' ', parents);
+ };
+ for (x in obj) {
+ values.push(indent + ' ' + entryFormatter(x, localFormatter));
+ }
+ if (values.length > 0) {
+ buffer += "\n" + values.join(",\n") + "\n" + indent;
+ }
+ buffer += parenthesis[1];
+ return buffer;
+}
diff --git a/test/mjsunit/test-sys.js b/test/mjsunit/test-sys.js
new file mode 100644
index 00000000000..14ce55157b8
--- /dev/null
+++ b/test/mjsunit/test-sys.js
@@ -0,0 +1,26 @@
+process.mixin(require("./common"));
+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("[Function]", inspect(function() {}));
+assert.equal('undefined', inspect(undefined));
+assert.equal('null', inspect(null));
+
+assert.equal('[]', inspect([]));
+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('{}', 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}}));
+
+var value = {}
+value['a'] = value;
+assert.equal('{\n "a": [Circular]\n}', inspect(value));