Skip to content

Commit

Permalink
took out up-front cloning, only fails date test
Browse files Browse the repository at this point in the history
  • Loading branch information
James Halliday committed May 29, 2011
1 parent f95bf5e commit 718d01b
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 47 deletions.
29 changes: 24 additions & 5 deletions index.js
Expand Up @@ -5,11 +5,11 @@ function Traverse (obj) {
}

Traverse.prototype.map = function (cb) {
return walk(this.clone(), cb);
return walk(this.value, cb, true);
};

Traverse.prototype.forEach = function (cb) {
this.value = walk(this.value, cb);
this.value = walk(this.value, cb, false);
return this.value;
};

Expand Down Expand Up @@ -89,9 +89,10 @@ Traverse.prototype.clone = function () {
})(this.value);
};

function walk (root, cb) {
function walk (root, cb, immutable) {
var path = [];
var parents = [];
if (immutable) root = copy(root);

(function walker (node) {
var modifiers = {};
Expand Down Expand Up @@ -148,7 +149,7 @@ function walk (root, cb) {
state.notRoot = !state.isRoot;

// use return values to update if defined
var ret = cb.call(state, node);
var ret = cb.call(state, state.node);
if (ret !== undefined && state.update) state.update(ret);
if (modifiers.before) modifiers.before.call(state, state.node);

Expand All @@ -162,7 +163,11 @@ function walk (root, cb) {

if (modifiers.pre) modifiers.pre.call(state, state.node[key], key);

var child = walker(state.node[key]);
var child = walker(
immutable ? copy(state.node[key]) : state.node[key]
);
if (immutable) state.node[child.key] = child.node;

child.isLast = i == keys.length - 1;
child.isFirst = i == 0;

Expand All @@ -188,3 +193,17 @@ Object.keys(Traverse.prototype).forEach(function (key) {
return t[key].apply(t, args);
};
});

function copy (node) {
if (Array.isArray(node)) {
return node.slice();
}
else if (typeof node === 'object') {
var cp = Object.create(node.__proto__);
Object.keys(node).forEach(function (key) {
cp[key] = node[key];
});
return cp;
}
else return node;
}
24 changes: 12 additions & 12 deletions test/circular.js
Expand Up @@ -25,13 +25,13 @@ exports.deepCirc = function () {
var times = 0;
Traverse(obj).forEach(function (x) {
if (this.circular) {
assert.eql(this.circular.path, []);
assert.eql(this.path, [ 'y', 2 ]);
assert.deepEqual(this.circular.path, []);
assert.deepEqual(this.path, [ 'y', 2 ]);
times ++;
}
});

assert.eql(times, 1);
assert.deepEqual(times, 1);
};

exports.doubleCirc = function () {
Expand All @@ -46,13 +46,13 @@ exports.doubleCirc = function () {
}
});

assert.eql(circs[0].self.path, [ 'x', 3, 2 ]);
assert.eql(circs[0].circ.path, []);
assert.deepEqual(circs[0].self.path, [ 'x', 3, 2 ]);
assert.deepEqual(circs[0].circ.path, []);

assert.eql(circs[1].self.path, [ 'y', 2 ]);
assert.eql(circs[1].circ.path, []);
assert.deepEqual(circs[1].self.path, [ 'y', 2 ]);
assert.deepEqual(circs[1].circ.path, []);

assert.eql(circs.length, 2);
assert.deepEqual(circs.length, 2);
};

exports.circDubForEach = function () {
Expand All @@ -64,7 +64,7 @@ exports.circDubForEach = function () {
if (this.circular) this.update('...');
});

assert.eql(obj, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] });
assert.deepEqual(obj, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] });
};

exports.circDubMap = function () {
Expand All @@ -78,7 +78,7 @@ exports.circDubMap = function () {
}
});

assert.eql(c, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] });
assert.deepEqual(c, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] });
};

exports.circClone = function () {
Expand All @@ -93,6 +93,6 @@ exports.circClone = function () {
assert.ok(clone.y[2] !== obj);
assert.ok(clone.x[3][2] === clone);
assert.ok(clone.x[3][2] !== obj);
assert.eql(clone.x.slice(0,3), [1,2,3]);
assert.eql(clone.y.slice(0,2), [4,5]);
assert.deepEqual(clone.x.slice(0,3), [1,2,3]);
assert.deepEqual(clone.y.slice(0,2), [4,5]);
};
4 changes: 2 additions & 2 deletions test/date.js
Expand Up @@ -11,7 +11,7 @@ exports.dateEach = function () {
counts[t] = (counts[t] || 0) + 1;
});

assert.eql(counts, {
assert.deepEqual(counts, {
object : 1,
Date : 1,
number : 2,
Expand All @@ -26,7 +26,7 @@ exports.dateMap = function () {
});

assert.ok(obj.x !== res.x);
assert.eql(res, {
assert.deepEqual(res, {
x : obj.x,
y : 110,
z : 105,
Expand Down
8 changes: 4 additions & 4 deletions test/interface.js
Expand Up @@ -4,7 +4,7 @@ var Traverse = require('traverse');
exports['interface map'] = function () {
var obj = { a : [ 5,6,7 ], b : { c : [8] } };

assert.eql(
assert.deepEqual(
Traverse.paths(obj)
.sort()
.map(function (path) { return path.join('/') })
Expand All @@ -14,7 +14,7 @@ exports['interface map'] = function () {
'a a/0 a/1 a/2 b b/c b/c/0'
);

assert.eql(
assert.deepEqual(
Traverse.nodes(obj),
[
{ a: [ 5, 6, 7 ], b: { c: [ 8 ] } },
Expand All @@ -23,7 +23,7 @@ exports['interface map'] = function () {
]
);

assert.eql(
assert.deepEqual(
Traverse.map(obj, function (node) {
if (typeof node == 'number') {
return node + 1000;
Expand All @@ -37,6 +37,6 @@ exports['interface map'] = function () {

var nodes = 0;
Traverse.forEach(obj, function (node) { nodes ++ });
assert.eql(nodes, 8);
assert.deepEqual(nodes, 8);
};

8 changes: 4 additions & 4 deletions test/json.js
Expand Up @@ -24,22 +24,22 @@ exports['json test'] = function () {
'obj.foo[3] replaced with "[Function]"'
);

assert.eql(scrubbed, {
assert.deepEqual(scrubbed, {
moo : '[Function]',
foo : [ 2, 3, 4, "[Function]" ]
}, 'Full JSON string matches');

assert.eql(
assert.deepEqual(
typeof obj.moo, 'function',
'Original obj.moo still a function'
);

assert.eql(
assert.deepEqual(
typeof obj.foo[3], 'function',
'Original obj.foo[3] still a function'
);

assert.eql(callbacks, {
assert.deepEqual(callbacks, {
54: { id: 54, f : obj.moo, path: [ 'moo' ] },
55: { id: 55, f : obj.foo[3], path: [ 'foo', '3' ] },
}, 'Check the generated callbacks list');
Expand Down
36 changes: 18 additions & 18 deletions test/mutability.js
Expand Up @@ -8,8 +8,8 @@ exports.mutate = function () {
this.update(x * 10);
}
});
assert.eql(obj, res);
assert.eql(obj, { a : 1, b : 20, c : [ 3, 40 ] });
assert.deepEqual(obj, res);
assert.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] });
};

exports.mutateT = function () {
Expand All @@ -19,8 +19,8 @@ exports.mutateT = function () {
this.update(x * 10);
}
});
assert.eql(obj, res);
assert.eql(obj, { a : 1, b : 20, c : [ 3, 40 ] });
assert.deepEqual(obj, res);
assert.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] });
};

exports.map = function () {
Expand All @@ -30,8 +30,8 @@ exports.map = function () {
this.update(x * 10);
}
});
assert.eql(obj, { a : 1, b : 2, c : [ 3, 4 ] });
assert.eql(res, { a : 1, b : 20, c : [ 3, 40 ] });
assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] });
assert.deepEqual(res, { a : 1, b : 20, c : [ 3, 40 ] });
};

exports.mapT = function () {
Expand All @@ -41,30 +41,30 @@ exports.mapT = function () {
this.update(x * 10);
}
});
assert.eql(obj, { a : 1, b : 2, c : [ 3, 4 ] });
assert.eql(res, { a : 1, b : 20, c : [ 3, 40 ] });
assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] });
assert.deepEqual(res, { a : 1, b : 20, c : [ 3, 40 ] });
};

exports.clone = function () {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = Traverse(obj).clone();
assert.eql(obj, res);
assert.deepEqual(obj, res);
assert.ok(obj !== res);
obj.a ++;
assert.eql(res.a, 1);
assert.deepEqual(res.a, 1);
obj.c.push(5);
assert.eql(res.c, [ 3, 4 ]);
assert.deepEqual(res.c, [ 3, 4 ]);
};

exports.cloneT = function () {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = Traverse.clone(obj);
assert.eql(obj, res);
assert.deepEqual(obj, res);
assert.ok(obj !== res);
obj.a ++;
assert.eql(res.a, 1);
assert.deepEqual(res.a, 1);
obj.c.push(5);
assert.eql(res.c, [ 3, 4 ]);
assert.deepEqual(res.c, [ 3, 4 ]);
};

exports.reduce = function () {
Expand All @@ -73,8 +73,8 @@ exports.reduce = function () {
if (this.isLeaf) acc.push(x);
return acc;
}, []);
assert.eql(obj, { a : 1, b : 2, c : [ 3, 4 ] });
assert.eql(res, [ 1, 2, 3, 4 ]);
assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] });
assert.deepEqual(res, [ 1, 2, 3, 4 ]);
};

exports.reduceInit = function () {
Expand All @@ -83,6 +83,6 @@ exports.reduceInit = function () {
if (this.isRoot) assert.fail('got root');
return acc;
});
assert.eql(obj, { a : 1, b : 2, c : [ 3, 4 ] });
assert.eql(res, obj);
assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] });
assert.deepEqual(res, obj);
};
4 changes: 2 additions & 2 deletions test/negative.js
Expand Up @@ -7,12 +7,12 @@ exports['negative update test'] = function () {
if (x < 0) this.update(x + 128);
});

assert.eql(fixed,
assert.deepEqual(fixed,
[ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ],
'Negative values += 128'
);

assert.eql(obj,
assert.deepEqual(obj,
[ 5, 6, -3, [ 7, 8, -2, 1 ], { f: 10, g: -13 } ],
'Original references not modified'
);
Expand Down

0 comments on commit 718d01b

Please sign in to comment.