From 5c6f161f2006df87f231317f3413bc38ad799b7d Mon Sep 17 00:00:00 2001 From: Stephen Sugden Date: Wed, 2 May 2012 11:43:12 -0700 Subject: [PATCH 1/4] Fix crash when node is a string and this.update is called with an object. --- index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/index.js b/index.js index b629542..86e27b6 100644 --- a/index.js +++ b/index.js @@ -191,6 +191,8 @@ function walk (root, cb, immutable) { && state.node !== null && !state.circular) { parents.push(state); + if (!state.keys) state.keys = Object_keys(state.node); + forEach(state.keys, function (key, i) { path.push(key); From 3857dcaeaceca9a739300b0b846c1094ddf3b26f Mon Sep 17 00:00:00 2001 From: Stephen Sugden Date: Wed, 2 May 2012 12:00:52 -0700 Subject: [PATCH 2/4] Update state with the current node before recursing --- index.js | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/index.js b/index.js index 86e27b6..02070b8 100644 --- a/index.js +++ b/index.js @@ -159,26 +159,30 @@ function walk (root, cb, immutable) { }; if (!alive) return state; - - if (typeof node === 'object' && node !== null) { - state.keys = Object_keys(node); - - state.isLeaf = state.keys.length == 0; - - for (var i = 0; i < parents.length; i++) { - if (parents[i].node_ === node_) { - state.circular = parents[i]; - break; + + function updateState() { + if (typeof state.node === 'object' && state.node !== null) { + state.keys = Object_keys(state.node); + + state.isLeaf = state.keys.length == 0; + + for (var i = 0; i < parents.length; i++) { + if (parents[i].node_ === node_) { + state.circular = parents[i]; + break; + } } } + else { + state.isLeaf = true; + } + + state.notLeaf = !state.isLeaf; + state.notRoot = !state.isRoot; } - else { - state.isLeaf = true; - } - - state.notLeaf = !state.isLeaf; - state.notRoot = !state.isRoot; - + + updateState(); + // use return values to update if defined var ret = cb.call(state, state.node); if (ret !== undefined && state.update) state.update(ret); @@ -190,9 +194,9 @@ function walk (root, cb, immutable) { if (typeof state.node == 'object' && state.node !== null && !state.circular) { parents.push(state); - - if (!state.keys) state.keys = Object_keys(state.node); - + + updateState(); + forEach(state.keys, function (key, i) { path.push(key); From ee66cd1c71db7701769323548916ce860f442d03 Mon Sep 17 00:00:00 2001 From: Stephen Sugden Date: Sun, 17 Jun 2012 17:40:46 -0700 Subject: [PATCH 3/4] Only set state.keys when necessary state.keys is set when (a) a non-primitive value is initially traversed, (b) a primitive value is replaced with an object or vice-versa. --- index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 02070b8..42ade02 100644 --- a/index.js +++ b/index.js @@ -162,7 +162,9 @@ function walk (root, cb, immutable) { function updateState() { if (typeof state.node === 'object' && state.node !== null) { - state.keys = Object_keys(state.node); + if (!state.keys || state.node_ !== state.node) { + state.keys = Object_keys(state.node) + } state.isLeaf = state.keys.length == 0; @@ -175,6 +177,7 @@ function walk (root, cb, immutable) { } else { state.isLeaf = true; + state.keys = null; } state.notLeaf = !state.isLeaf; From 28d5fb64e44237e21c01904d6e46b34626d66d33 Mon Sep 17 00:00:00 2001 From: Stephen Sugden Date: Sun, 17 Jun 2012 17:41:59 -0700 Subject: [PATCH 4/4] Add test for replacing objects with strings and vice-versa --- test/mutability.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/mutability.js b/test/mutability.js index 2236f56..dbea80c 100644 --- a/test/mutability.js +++ b/test/mutability.js @@ -250,3 +250,28 @@ exports.deleteMapRedux = function () { res, { a : 1, c : [ 3 ,, 5 ] } )); }; + +exports.objectToString = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).forEach(function (x) { + if (typeof x === 'object' && !this.isRoot) { + this.update(JSON.stringify(x)); + } + }); + assert.deepEqual(obj, res); + assert.deepEqual(obj, { a : 1, b : 2, c : "[3,4]" }); +}; + +exports.stringToObject = function () { + var obj = { a : 1, b : 2, c : "[3,4]" }; + var res = Traverse(obj).forEach(function (x) { + if (typeof x === 'string') { + this.update(JSON.parse(x)); + } + else if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, res); + assert.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] }); +};