我可以阻止Babel遍历插件插入的代码吗?

时间:2016-10-10 15:42:00

标签: babeljs

我正在构建一个插件,通过调用enterFunction()在每个现有函数调用之前插入path.insertBefore。所以我的代码转自:

myFunction();

要:

enterFunction();
myFunction();

问题是,当我插入节点时,Babel再次遍历插入的节点。这是日志记录输出:

  

'CallExpression','myFunction'
  'CallExpression','enterFunction'

如何阻止Babel进入enterFunction来电表达及其子女?

这是我目前用于Babel插件的代码:

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)
            }
        }
    }
}

1 个答案:

答案 0 :(得分:3)

Babel Handbook提及以下部分:

  

如果您的插件不需要在某种情况下运行,最简单的方法就是尽早写回。

BinaryExpression(path) {
  if (path.node.operator !== '**') return;
}
     

如果您在顶级路径中进行子遍历,则可以使用2种提供的API方法:

     

path.skip()跳过遍历当前路径的子节点。 path.stop()完全停止遍历。

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
  }
});

简而言之,使用path.skip()跳过遍历当前路径的子项。 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();
      }
    }
  };
}