还原未修改的常量

 

 

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

 

posted @ 2022-01-02 17:36  AngDH  阅读(59)  评论(0编辑  收藏  举报