Babel unshiftcontainer 不创建元素

ta-*_*run 4 javascript abstract-syntax-tree babeljs

尝试使用 babel 变换,我编写了这段代码以VariableDeclaration在我的之后插入一个path

export default function (babel) {
  const { types: t } = babel;

  return {
    name: "ast-transform", // not required
    visitor: {
      VariableDeclaration (path) {
        if (path.node.kind !== 'var') {
          return;
        }

        const _id = t.Identifier('qwe');
        const _init = t.numericLiteral(42);

        console.log(_id, _init);

        const _node = t.variableDeclaration('var', [
          t.variableDeclarator(
            t.identifier("uid"),
            t.numericLiteral(42)
          )
        ]);

        path
          .unshiftContainer(
            'body',
            _node
          )

      }
    }
  };
}
Run Code Online (Sandbox Code Playgroud)

得到以下错误,

未知:无法读取未定义的属性“body”

编辑:

如果我执行以下操作而不是unshiftContainer有效,

const _program = path.findParent(p => p.isProgram());
_program.node.body.unshift(_node);
Run Code Online (Sandbox Code Playgroud)

为什么不起作用unshiftContainer

链接到ast-explorer上的要点

Max*_*rok 6

为了使用unshiftContainer("body")你必须有一个带有“body”的节点。例如,ProgramFunctionDeclaration( 1,2,3 )

但你试图做到这一点,VariableDeclaration正如body你在ast-explorer中看到的那样。

当您调用 时path.get("body"),它会返回{..., node: undefined, ...},然后,当您调用 时unshiftContainer("body"),它会尝试获取"body"of node,即undefined: container: this.node[listKey],

您的解决方案之所以有效,是因为您正在寻找Program具有主体的对象。因此,如果您想使用,这也可以工作unshiftContainer

const _program = path.findParent(p => p.isProgram());
_program.unshiftContainer("body", _node);
Run Code Online (Sandbox Code Playgroud)

另外,你可以这样做:

const parentWithBody = path.findParent(
  (p) => p.node !== undefined && p.node.body !== undefined
);
parentWithBody.unshiftContainer("body", _node);
Run Code Online (Sandbox Code Playgroud)

它不仅会检测Program,还会检测FunctionDeclaration

来源:

var x = 10;
var y = 5;

function test() {
  var z = 1;
}
Run Code Online (Sandbox Code Playgroud)

输出:

var uid = 42;
var uid = 42;
var x = 10;
var y = 5;

function test() {
  var uid = 42;
  var z = 1;
}
Run Code Online (Sandbox Code Playgroud)

关于无限循环的更新

事实上,当您取消移动容器时,您正在添加 new VariableDeclaration,因此它将进入无限循环:

  1. 参见var x = 10->添加var uid = 42
  2. 参见var uid = 42->添加var uid = 42
  3. 等等...

为了打破这个循环,添加这个条件,检查是否node.kindvar

if (path.node.declarations[0].init.value === 42 && path.node.declarations[0].id.name === "uid") {
  return;
}
Run Code Online (Sandbox Code Playgroud)

要点