Skip to content

Commit

Permalink
circular refs don't crash it now
Browse files Browse the repository at this point in the history
  • Loading branch information
James Halliday committed Sep 4, 2010
1 parent 188ee17 commit 2cdd854
Showing 1 changed file with 27 additions and 2 deletions.
29 changes: 27 additions & 2 deletions lib/traverse.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,34 @@
module.exports = Traverse;
module.exports.Traverse = Traverse;

var sys = require('sys');

function Traverse (refObj) {
if (!(this instanceof Traverse)) return new Traverse(refObj);

// clone refObj for a properly immutable interface:
clone.refs = [];
clone.nodes = [];
function clone(ref) {
if (typeof ref == 'object' && ref !== null) {
var node = ref instanceof Array ? [] : {};
clone.refs.push(ref);
clone.nodes.push(node);

Object.keys(ref).forEach(function (key) {
node[key] = clone(ref[key]);
var i = clone.refs.indexOf(ref[key]);
if (i >= 0) {
node[key] = clone.nodes[i];
}
else {
node[key] = clone(ref[key]);
}

});

clone.refs.pop();
clone.nodes.pop();

// To make instanceof work:
node.__proto__ = ref.__proto__;
// Probably there are other attributes worth copying
Expand Down Expand Up @@ -47,9 +65,15 @@ function Traverse (refObj) {
state.node = x;
},
level : path.length,
circular : null
};

if (typeof node == 'object' && node !== null) {
state.isLeaf = Object.keys(node).length == 0
var circs = parents.filter(function (p) {
return node == p.node
});
if (circs.length) state.circular = circs[0];
}
else {
state.isLeaf = true;
Expand All @@ -59,7 +83,8 @@ function Traverse (refObj) {
state.notRoot = !state.isRoot;

f.call(state, node);
if (typeof state.node == 'object' && state.node !== null) {
if (typeof state.node == 'object'
&& state.node !== null && !state.circular) {
parents.push(state);
Object.keys(state.node).forEach(function (key) {
path.push(key);
Expand Down

0 comments on commit 2cdd854

Please sign in to comment.