| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- const fs = require('fs')
- const parser = require('@babel/parser') // 解析 JavaScript 代码
- const traverse = require('@babel/traverse').default // 遍历 AST
- const generator = require('@babel/generator').default // 生成代码
- const t = require('@babel/types')
- // 定义文件路径
- const input_js = './encode.js'
- const output_js = './decode.js'
- // 读取文件内容并解析成 AST
- const js_code = fs.readFileSync(input_js, {encoding: 'utf-8'})
- const ast = parser.parse(js_code) // 解析代码为 AST
- // 字面量访问器 -------------------------------
- const varPool = new Map(); // 存储(第一个函数)计算出的变量值
- const varPool2 = new Map(); // 存储(第二个函数)计算出的变量值
- const visitor_literal = {
- // 第一阶段:处理 QxN 函数
- FunctionDeclaration(path) {
- let {id} = path.node
- let bodyPath = path.get('body')
- if (!t.isIdentifier(id, {name: 'QxN'})) return;
- bodyPath.traverse({
- AssignmentExpression(path) {
- const rightPath = path.get('right'); // 获取右侧表达式的路径(左边是变量名)
- const var_name = path.node.left.name // 获取左侧的变量名
- // evaluate() 方法是路径对象(Path)提供的方法,而非节点(Node)本身的方法。你需要通过路径来调用该方法
- const evaluated = rightPath.evaluate(); // 调用evaluate()
- if (evaluated.confident) {
- let value = evaluated.value
- varPool.set(var_name, value); // 存储变量值
- console.log(rightPath.toString(), '=>', value); // 输出确定的值
- rightPath.replaceWith(t.valueToNode(value)) // 替换为字面量
- } else {
- console.log('无法静态求值');
- }
- }
- })
- },
- Program: {
- exit(path) {
- // 第二阶段:在所有节点处理完成后处理 ShN 函数
- path.traverse({
- FunctionDeclaration(path) {
- let {id} = path.node
- let bodyPath = path.get('body')
- if (!t.isIdentifier(id, {name: 'ShN'})) return;
- bodyPath.traverse({
- AssignmentExpression(path) {
- const rightPath = path.get('right');
- const var_name = path.node.left.name // 获取左侧的变量名
- // evaluate() 方法是路径对象(Path)提供的方法,而非节点(Node)本身的方法。你需要通过路径来调用该方法
- // 继续遍历rightPath下的节点,替换已知变量引用为字面量
- rightPath.traverse({
- // subPath表示子路径,定位子路径下的标识符
- Identifier(subPath) {
- if (varPool.has(subPath.node.name)) {
- subPath.replaceWith(
- t.valueToNode(varPool.get(subPath.node.name))
- )
- }
- }
- });
- // 再次尝试计算表达式
- const evaluated = rightPath.evaluate();
- if (evaluated.confident) {
- let value = evaluated.value
- varPool2.set(var_name, value)
- console.log(rightPath.toString(), '=>', evaluated.value); // 输出确定的值
- rightPath.replaceWith(t.valueToNode(evaluated.value));
- }
- }
- })
- }
- });
- }
- }
- };
- // 定位 return j2.call(this, xL);
- const visitor_ = {
- CallExpression(path) {
- let {callee} = path.node
- if (!t.isFunctionExpression(callee)) return;
- path.traverse({
- ReturnStatement(path) {
- let {argument} = path.node
- if (!t.isCallExpression(argument)) return;
- let {callee: {property,}, arguments: args} = argument
- if (args.length !== 2 || !t.isIdentifier(property, {name: 'call'})) return;
- console.log(path.toString())
- }
- })
- },
- }
- // 控制流平坦化访问器 -------------------------------
- function return_num(varStr) {
- // 根据变量字符串,返回对应变量值
- if (varPool.has(varStr) || varPool2.has(varStr)) {
- return varPool[varStr] || varPool2[varStr]
- }
- console.warn(`${varStr}未找到`)
- }
- const visitor_for = {
- ForStatement(path) {
- const {test, body} = path.node; // 解构循环条件和循环体
- // let {} = test // 从循环条件取出具体值,在变量值map中查找,方便下面循环处理
- // 初始状态变量值
- let init_name = 'HO'; // 状态变量名
- let init_value = 3; // 初始状态值
- const switch_body = body.body[0]; // 提取循环体内的switch语句
- // 验证是否为 Switch 语句,否则终止处理
- if (!t.isSwitchStatement(switch_body)) return;
- const {discriminant, cases} = switch_body; // 解构 Switch 的条件和分支列表
- // 验证 Switch 条件是否为指定状态变量
- if (!t.isIdentifier(discriminant, {name: init_name})) return;
- const ret_body = []; // 存储最终生成的代码块集合
- let end_flag = false; // 终止循环处理标志
- while (init_value !== 662) { // 循环处理所有状态分支
- if (end_flag) break; // 检测终止条件
- for (const each_case of cases) { // 遍历 Switch 的所有 case 分支
- const {test, consequent} = each_case; // 从case分支中取出条件和对应代码块
- if (init_value !== test.name) continue; // 跳过非当前状态的 case 分支
- }
- }
- }
- }
- const visitor_while = {
- VariableDeclarator(path) {
- let {id, init} = path.node
- if (!t.isIdentifier(id, {name: 'j2'})) return
- path.traverse(visitor_for)
- // console.log(id.name)
- }
- }
- traverse(ast, visitor_literal); // 还原初始化2个变量赋值函数
- // traverse(ast, visitor_);
- // traverse(ast, visitor_while);
- console.log(varPool2)
- // 使用 Babel 生成新的代码
- let {code} = generator(ast)
- // 将生成的代码写入指定的文件
- // fs.writeFile(output_js, code, (err) => {
- // })
|