如何解决Babel的`path.unshiftContainer`不会将新创建的var添加到范围
我正在开发一个Babel插件,该插件通常在plugin-transform-modules-commonjs
之后使用(即源代码是ES模块,但正在被转换为CommonJS)。
我的插件需要确定函数中使用的变量是来自外部作用域还是全局变量。
除了plugin-transform-modules-commonjs
创建的var之外,其他方法都可以正常工作。
示例:
const babel = require('@babel/core');
function myPlugin() {
return {
visitor: {
Program: {
exit(programPath) {
// This logic in Program exit visitor
// to ensure runs after ESM->CJS transform
programPath.traverse({
ReferencedIdentifier(path) {
if (!path.findParent(p => p.isFunction())) return;
const isGlobal = !path.scope.getBinding(path.node.name);
path.addComment('leading',isGlobal ? 'global' : 'scoped');
}
});
}
}
}
};
}
const input = `
import {x} from './foo.js';
var y = true;
function answer() {
return x && y && console;
}
`;
const output = babel.transform(input,{
plugins: [
'@babel/plugin-transform-modules-commonjs',myPlugin
]
}).code;
console.log(output);
这将输出:
"use strict";
var _foo = require("./foo.js");
var y = true;
function answer() {
return (/*global*/_foo.x && /*scoped*/y && /*global*/console);
};
问题是_foo
不是全局变量,它是程序顶级范围内的var,因此输出应包含/*scoped*/_foo.x
。但是出于某些原因,path.scope.getBinding('_foo')
返回undefined
。
似乎未根据plugin-transform-modules-commonjs
执行的转换来更新范围。
我没有做任何事情来确保范围得到更新吗?
修改
实际上,这似乎不是plugin-transform-modules-commonjs
特有的。用path.unshiftContainer()
创建的任何var似乎都会发生这种情况。
例如在前面的示例中,用此插件替换plugin-transform-modules-commonjs
:
function createVarPlugin() {
return {
visitor: {
Program: {
exit(path) {
path.unshiftContainer('body',[
t.variableDeclaration('var',[
t.variableDeclarator(
t.identifier('console'),t.numericLiteral(123)
)
])
]);
}
}
}
};
}
/* ... */
const output = babel.transform(input,{
plugins: [ createVarPlugin,myPlugin ]
}).code;
现在的输出是:
var console = 123;
import { x } from './foo.js';
var y = true;
function answer() {
return (/*scoped*/x && /*scoped*/y && /*global*/console);
}
这次console
被误认为是全局的,实际上它在顶级范围内。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。