dumper should use a new circular-refs cache for every call

This commit is contained in:
Jeff Williams 2013-11-26 18:31:02 -08:00
parent 522a377845
commit d3cff64ec0

View File

@ -8,53 +8,58 @@
var util = require('util'); var util = require('util');
var seenItems = []; function ObjectWalker() {
function seen(object) { this.seenItems = [];
if (seenItems.indexOf(object) !== -1) { }
ObjectWalker.prototype.seen = function(object) {
if (this.seenItems.indexOf(object) !== -1) {
return true; return true;
} }
return false; return false;
} };
// some objects are unwalkable, like Java native objects // some objects are unwalkable, like Java native objects
function isUnwalkable(o) { ObjectWalker.prototype.isUnwalkable = function(o) {
return (o && typeof o === 'object' && typeof o.constructor === 'undefined'); return (o && typeof o === 'object' && typeof o.constructor === 'undefined');
} };
function isFunction(o) { ObjectWalker.prototype.isFunction = function(o) {
return (o && typeof o === 'function' || o instanceof Function); return (o && typeof o === 'function' || o instanceof Function);
} };
function isObject(o) { ObjectWalker.prototype.isObject = function(o) {
return o && o instanceof Object || return o && o instanceof Object ||
(o && typeof o.constructor !== 'undefined' && o.constructor.name === 'Object'); (o && typeof o.constructor !== 'undefined' && o.constructor.name === 'Object');
} };
function checkCircularRefs(o, func) { ObjectWalker.prototype.checkCircularRefs = function(o, func) {
if ( seen(o) ) { if ( this.seen(o) ) {
return '<CircularRef>'; return '<CircularRef>';
} }
else { else {
seenItems.push(o); this.seenItems.push(o);
return func(o); return func(o);
} }
} };
function walk(o) { ObjectWalker.prototype.walk = function(o) {
var result; var result;
if ( isUnwalkable(o) ) { var self = this;
if ( this.isUnwalkable(o) ) {
result = '<Object>'; result = '<Object>';
} }
else if ( o === undefined ) { else if ( o === undefined ) {
result = 'undefined'; result = 'undefined';
} }
else if ( Array.isArray(o) ) { else if ( Array.isArray(o) ) {
result = checkCircularRefs(o, function(arr) { result = this.checkCircularRefs(o, function(arr) {
var newArray = []; var newArray = [];
arr.forEach(function(item) { arr.forEach(function(item) {
newArray.push( walk(item) ); newArray.push( self.walk(item) );
}); });
return newArray; return newArray;
@ -69,14 +74,14 @@ function walk(o) {
else if ( util.isError(o) ) { else if ( util.isError(o) ) {
result = { message: o.message }; result = { message: o.message };
} }
else if ( isFunction(o) ) { else if ( this.isFunction(o) ) {
result = '<Function' + (o.name ? ' ' + o.name : '') + '>'; result = '<Function' + (o.name ? ' ' + o.name : '') + '>';
} }
else if ( isObject(o) && o !== null ) { else if ( this.isObject(o) && o !== null ) {
result = checkCircularRefs(o, function(obj) { result = this.checkCircularRefs(o, function(obj) {
var newObj = {}; var newObj = {};
Object.keys(obj).forEach(function(key) { Object.keys(obj).forEach(function(key) {
newObj[key] = walk(obj[key]); newObj[key] = self.walk(obj[key]);
}); });
return newObj; return newObj;
@ -88,11 +93,11 @@ function walk(o) {
} }
return result; return result;
} };
/** /**
* @param {*} object * @param {*} object
*/ */
exports.dump = function(object) { exports.dump = function(object) {
return JSON.stringify(walk(object), null, 4); return JSON.stringify(new ObjectWalker().walk(object), null, 4);
}; };