diff --git a/src/arborist.js b/src/arborist.js index dee7165..0fa7b92 100644 --- a/src/arborist.js +++ b/src/arborist.js @@ -55,7 +55,13 @@ class Arborist { * @param {object|ASTNode} [replacementNode] If exists, replace the target node with this node. */ markNode(targetNode, replacementNode) { - if (!targetNode.isMarked) { + let alreadyMarked = false; + let currentNode = targetNode; + while (currentNode) { + if (currentNode.isMarked) {alreadyMarked = true;} + currentNode = currentNode.parentNode; + } + if (alreadyMarked) {return;} if (replacementNode) { // Mark for replacement this.replacements.push([targetNode, replacementNode]); targetNode.isMarked = true; @@ -65,7 +71,6 @@ class Arborist { else if (!targetNode.isMarked) { this.markedForDeletion.push(targetNode.nodeId); targetNode.isMarked = true; - } } } } diff --git a/tests/arborist.test.js b/tests/arborist.test.js index 849878f..29c6000 100644 --- a/tests/arborist.test.js +++ b/tests/arborist.test.js @@ -239,4 +239,15 @@ describe('Arborist edge case tests', () => { arb.applyChanges(); assert.equal(arb.script, 'let y = 20;'); }); + + it('A node will not marked if any of their ancestors is', () => { + const code = 'const arr = [1, 2, 3];'; + const arb = new Arborist(code); + const arrayNode = arb.ast.find((n) => n.type === 'ArrayExpression'); + const literals = arb.ast.filter((n) => n.type === 'Literal'); + arb.markNode(arrayNode); + for (const lit of literals) {arb.markNode(lit);} + assert.ok(arrayNode.isMarked); + for (const lit of literals) {assert.ok(!lit.isMarked);} + }); }); \ No newline at end of file