Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From a0db2d73d6d6099c5bc810d60bcce192c6d81dbe Mon Sep 17 00:00:00 2001
- From: Xavier Shay <xavier@rhnh.net>
- Date: Tue, 1 Dec 2009 21:20:14 +1100
- Subject: [PATCH] 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
- ---
- lib/sys.js | 84 +++++++++++++++++++++++++++++++++++-----------
- test/mjsunit/test-sys.js | 26 ++++++++++++++
- 2 files changed, 90 insertions(+), 20 deletions(-)
- create mode 100644 test/mjsunit/test-sys.js
- diff --git a/lib/sys.js b/lib/sys.js
- index da749db..16e2606 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);
- @@ -88,3 +73,62 @@ exports.inherits = function (ctor, superCtor) {
- ctor.prototype = new tempCtor();
- ctor.prototype.constructor = ctor;
- };
- +
- +/**
- + * 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 0000000..8a0aa35
- --- /dev/null
- +++ b/test/mjsunit/test-sys.js
- @@ -0,0 +1,26 @@
- +process.mixin(require("./common"));
- +process.mixin(require("sys"));
- +
- +assertEquals("0", inspect(0));
- +assertEquals("1", inspect(1));
- +assertEquals("false", inspect(false));
- +assertEquals('""', inspect(""));
- +assertEquals('"hello"', inspect("hello"));
- +assertEquals("[Function]", inspect(function() {}));
- +assertEquals('undefined', inspect(undefined));
- +assertEquals('null', inspect(null));
- +
- +assertEquals('[]', inspect([]));
- +assertEquals('[\n 1,\n 2\n]', inspect([1, 2]));
- +assertEquals('[\n 1,\n [\n 2,\n 3\n ]\n]', inspect([1, [2, 3]]));
- +
- +assertEquals('{}', inspect({}));
- +assertEquals('{\n "a": 1\n}', inspect({a: 1}));
- +assertEquals('{\n "a": [Function]\n}', inspect({a: function() {}}));
- +assertEquals('{\n "a": 1,\n "b": 2\n}', inspect({a: 1, b: 2}));
- +assertEquals('{\n "a": {}\n}', inspect({'a': {}}));
- +assertEquals('{\n "a": {\n "b": 2\n }\n}', inspect({'a': {'b': 2}}));
- +
- +var value = {}
- +value['a'] = value;
- +assertEquals('{\n "a": [Circular]\n}', inspect(value));
- --
- 1.6.2.4
Add Comment
Please, Sign In to add comment