javascriptbabeljsbabel-plugin

Replacing different kinds of function nodes on babel


I already asked this on babel slack channel a couple of days ago, but I never got an answer. I've created a plugin to transform functions to curried functions (npm). Despite my success building the plugins, I have a couple of issues that I found a workaround for, but I would prefer to simplify my logic and hence make it more robust and reliable.

My first approach was to build a visitor for FunctionDeclaration. This one was very straightforward: expand each argument into an ArrowFunctionExpression and then replace the current node with a new FunctionDeclaration that returns those functions.

The problem comes when you want to deal with FunctionExpressions. As you probably know, a FunctionExpression can appear at several places an an AST:

All of those are valid FunctionExpressions, which introduce a problem: I was replacing the current node with a functionDeclaration, but seems that babel refuses to replace any of those with a functionDeclaration. This has forced me to replace the entire parent node by re-creating it. This has worked so far for assignment expressions and variable declarations which contains a functionExpression, but I have to re-create them exactly to don't break any code. This gets harder as you want to support more scenarios.

For me the ideal situation would be to just replace the current node and don't worry at all about where it is, but as I said, babel refuses to replace the current node when it is inside a variable declaration.

Code can be seen here. Note: I'm not sure if I should also post the code here, seems to be not neccessary

Regards


Solution

  • Finally I come to a solution. My first attempt was failing because I was trying to replace a FunctionExpression with a FunctionDeclaration, which babel rejects because it seems to be incompatible, even if the output code is exactly the same. Building the new body function with a function expression constructor when replacing a function expression allowed me to just make node.replaceWith instead of replacing the entire parent with a new node.

    This seems to be because both AssignmentExpression and VariableDeclarator expect an Expression as parameter. FunctionDeclaration is not part of that group (as you can see on its aliases list), but FunctionExpression is. So even when the output code it's the same, in AST term they are not.