Skip to content

Commit

Permalink
[Fix] continue iterating properly when items are removed
Browse files Browse the repository at this point in the history
Fixes #18
  • Loading branch information
ljharb committed Sep 12, 2024
1 parent 368e82c commit ca14874
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 2 deletions.
13 changes: 11 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ function walk(root, cb) {
parent: parents[parents.length - 1],
parents: parents,
key: path[path.length - 1],
removedKeys: { __proto__: null },
isRoot: path.length === 0,
level: path.length,
circular: null,
Expand All @@ -144,15 +145,17 @@ function walk(root, cb) {
},
delete: function (stopHere) {
delete state.parent.node[state.key];
state.parent.removedKeys[state.key] = true;
if (stopHere) { keepGoing = false; }
},
remove: function (stopHere) {
if (isArray(state.parent.node)) {
state.parent.node.splice(state.key, 1);
state.parent.removedKeys[state.key] = true;
if (stopHere) { keepGoing = false; }
} else {
delete state.parent.node[state.key];
state.delete(stopHere);
}
if (stopHere) { keepGoing = false; }
},
keys: null,
before: function (f) { modifiers.before = f; },
Expand Down Expand Up @@ -208,6 +211,11 @@ function walk(root, cb) {
updateState();

forEach(state.keys, function (key, i) {
var prevIsRemoved = (i - 1) in state.removedKeys;
if (prevIsRemoved) {
key = state.keys[i - 1]; // eslint-disable-line no-param-reassign
}

path[path.length] = (key);

if (modifiers.pre) { modifiers.pre.call(state, state.node[key], key); }
Expand All @@ -217,6 +225,7 @@ function walk(root, cb) {
immutable
&& hasOwnProperty.call(state.node, key)
&& !isWritable(state.node, key)
&& !prevIsRemoved
) {
state.node[key] = child.node;
}
Expand Down
27 changes: 27 additions & 0 deletions test/mutability.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,3 +290,30 @@ test('stringToObject', function (t) {
t.deepEqual(obj, { a: 1, b: 20, c: [3, 40] });
t.end();
});

test('array item removal', function (t) {
var obj = [
function a() {},
function b() {},
'a',
];

function cb(x) {
if (x !== obj) {
// console.log("**", x, typeof x)
if (typeof x === 'function') { this.remove(); }
}
}

var result = traverse(obj, { immutable: true }).forEach(cb);

t.equal(obj.length, 3, 'immutable: makes no changes');

t.deepEqual(result, ['a'], 'immutable result: removes all functions');

traverse(obj).forEach(cb);

t.deepEqual(obj, ['a'], 'removes all functions');

t.end();
});

0 comments on commit ca14874

Please sign in to comment.