const fs = require('fs');
const types = require("@babel/types");
const parser = require("@babel/parser");
const template = require("@babel/template").default;
const traverse = require("@babel/traverse").default;
const generator = require("@babel/generator").default;


//js混淆代码读取
process.argv.length > 2 ? encodeFile = process.argv[2] : encodeFile = "./captcha.js";  //默认的js文件
process.argv.length > 3 ? decodeFile = process.argv[3] : decodeFile = encodeFile.slice(0, encodeFile.length - 3) + "_ok.js";

//将源代码解析为AST
let sourceCode = fs.readFileSync(encodeFile, {encoding: "utf-8"});
let ast = parser.parse(sourceCode);
console.time("处理完毕，耗时");

//还原object
traverse(ast, {
    VariableDeclaration(path) {
        let {node} = path;
        let declarations = node.declarations;
        let res = [];
        if (declarations.length <=1)return;
        for (const declaration of declarations) {
            res.push(types.variableDeclaration('var', [declaration]))
        }
        path.replaceWithMultiple(res);
    }
})
//还原object
traverse(ast, {
    VariableDeclaration(path) {
        let {scope, node} = path;
        let {declarations} = node;
        if (!declarations) return

        if (declarations.length !== 1) return;

        let {id, init} = declarations[0]
        if (!types.isObjectExpression(init)) return
        let {properties} = init;

        if (properties.length === 0) return;
        for (let i = 0; i < properties.length; i++) {
            let {key, value} = properties[i];
            if (!types.isNumericLiteral(value)) return
        }


        let binding = scope.getBinding(id.name);
        if (!binding) return
        let {constant, referencePaths, constantViolations} = binding;
        if (!constant) {//新版本的babel库，在循环里面的变量定义，默认非常量
            if (constantViolations.length != 1 || constantViolations[0] != path) //旧版本屏蔽该行即可
            {
                return;
            }
        }

        let newMap = new Map();
        for (const property of properties) {
            let {key, value} = property;
            newMap.set(key.name, value);
        }

        let canBeRemoved = true;
        for (const referPath of referencePaths) {
            let {parentPath} = referPath;
            if (!parentPath.isMemberExpression()) {
                canBeRemoved = false;
                return;
            }

            let AncestorPath = parentPath.parentPath;

            if (AncestorPath.isAssignmentExpression({"left": parentPath.node})) {
                canBeRemoved = false;
                return;
            }
            if (AncestorPath.isUpdateExpression() && ['++', '--'].includes(AncestorPath.node.operator)) {
                canBeRemoved = false;
                return;
            }

            let curKey = parentPath.node.property.name;
            if (!newMap.has(curKey)) {
                canBeRemoved = false;
                break;
            }
            parentPath.replaceWith(newMap.get(curKey));
        }
        canBeRemoved && path.remove();
        newMap.clear();
    }
})
// 还原未被修改的常量



console.timeEnd("处理完毕，耗时");
let {code} = generator(ast, opts = {
    "compact": false,  // 是否压缩代码
    "comments": false,  // 是否保留注释
    "jsescOption": {"minimal": true},  //Unicode转义
});

fs.writeFile(decodeFile, code, (err) => {
});