I'm building a plugin that inserts enterFunction()
in front of every existing function call by calling path.insertBefore
. So my code is transformed from:
myFunction();
To:
enterFunction(); myFunction();
The problem is that when I insert the node Babel once again traverses the inserted node. Here's the logging output:
'CallExpression', 'myFunction'
'CallExpression', 'enterFunction'
How can I prevent Babel from entering the enterFunction
call expression and its children?
This is the code I'm currently using for my Babel plugin:
function(babel) { return { visitor: { CallExpression: function(path) { console.log("CallExpression", path.node.callee.name) if (path.node.ignore) { return; } path.node.ignore = true var enterCall = babel.types.callExpression( babel.types.identifier("enterFunction"), [] ) enterCall.ignore = true; path.insertBefore(enterCall) } } } }
Babel is a tool that lets you write your Javascript code using all the latest syntax and features, and run it in browsers that may not support those features. Babel is a transpiler that will translate your modern JS code into an older version of Javscript that more browsers are able to understand.
The Babel Handbook mentions the following section:
If your plugin needs to not run in a certain situation, the simpliest thing to do is to write an early return.
BinaryExpression(path) { if (path.node.operator !== '**') return; }
If you are doing a sub-traversal in a top level path, you can use 2 provided API methods:
path.skip() skips traversing the children of the current path. path.stop() stops traversal entirely.
outerPath.traverse({ Function(innerPath) { innerPath.skip(); // if checking the children is irrelevant }, ReferencedIdentifier(innerPath, state) { state.iife = true; innerPath.stop(); // if you want to save some state and then stop traversal, or deopt } });
In short, use path.skip()
to skip traversing the children of the current path. One application of this method is illustrated in this snippet using Visitors, CallExpression and skip():
export default function (babel) { const { types: t } = babel; return { name: "ast-transform", // not required visitor: { CallExpression(path) { path.replaceWith(t.blockStatement([ t.expressionStatement(t.yieldExpression(path.node)) ])); path.skip(); } } }; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With