const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;
// 将js代码转换成AST
// const { parse } = require("@babel/parser");
// 用来遍历AST中的节点
// const traverse = require("@babel/traverse").default;
// AST转换成js
const generator = require("@babel/generator").default;
// 用来判断节点类型和生成新的节点
const types = require("@babel/types");
const jscode = `
var a = 123;
const b = -5;
let c = window;
function d(){
var f = c.btoa("hello,AST!");
return a + b + f ;
}
`;
let ast = parser.parse(jscode);
const restoreVarDeclarator = {
VariableDeclarator(path)
{
let {id,init} = path.node;
if (!types.isIdentifier(id)) return;
let initPath = path.get("init");
if (initPath.isUnaryExpression({operator:"+"}) ||
initPath.isUnaryExpression({operator:"-"}))
{// -5或者 +"3" 也可以算作是字面量
if (!types.isLiteral(init.argument)) return;
}
//如果初始值非Literal节点或者Identifier节点,不做还原
//有时候为MemberExpression节点时,也可以还原,视情况而论
//请大家自行添加,通用插件不做处理。
else if (!initPath.isLiteral() &&
!initPath.isIdentifier())
{
return;
}
const binding = path.scope.getBinding(id.name);
//判断初始值是否被更改
if (!binding || !binding.constant) return;
//获取所有引用的地方并替换
let referPaths = binding.referencePaths;
for (let referPath of referPaths)
{
referPath.replaceWith(init);
}
//替换完毕,直接删除即可。
path.remove();
},
}
traverse(ast, restoreVarDeclarator);
let { code } = generator(ast);
console.log(code);