const parser = require(
'@babel/parser'
);
const traverse = require(
'@babel/traverse'
).
default
;
const generator = require(
'@babel/generator'
).
default
;
const t = require(
'@babel/types'
);
const fs = require(
'fs'
);
const start = Date.now();
const jscode = fs.readFileSync(
"./input.js"
, {
encoding:
"utf-8"
});
let
code;
let
ast = parser.parse(jscode);
`
(
function
() {
var
_$rD = 0
, _$zG = $_ts.scj
, _$cj = [[],[],[],[],[]];
.........
})()
`
traverse(ast,{
Program(path){
if
(!path.get(
'body.0'
)?.get(
'expression'
)?.get(
'callee'
)?.get(
'body'
)?.get(
'body.0'
)?.isVariableDeclaration())
return
;
let
func_statement_path_1 = path.get(
'body'
)[0].get(
'expression.callee.body.body'
)[0];
func_statement_path_1.get(
'declarations'
).forEach(
function
(v) {
if
(v.get(
'init'
).isArrayExpression()){
let
binding = func_statement_path_1.scope.getBinding(v.node.id.name);
let
arr = v.node.init.elements;
binding && binding.constantViolations.length == 0 && binding.referencePaths.forEach(
function
(vv) {
if
(vv.parentPath.isMemberExpression()
&& vv.parent.object.name == v.node.id.name
&& vv.parentPath.get(
'property'
).isNumericLiteral()
){
vv.parentPath.replaceWith(arr[vv.parent.property.value]);
}
})
}
});
}
});
traverse(ast, {
IfStatement(path) {
let
{consequent, alternate} = path.node;
if
(consequent && !t.isBlockStatement(consequent)) {
path.get(
'consequent'
).replaceWith(t.BlockStatement([consequent]));
}
if
(alternate && !t.isBlockStatement(alternate)) {
path.get(
'alternate'
).replaceWith(t.BlockStatement([alternate]));
}
}
});
function
judge_include_identifier(path, idt) {
let
flag =
true
;
path.traverse({
Identifier(path_) {
if
(path_.node.name != idt) {
flag =
false
}
}
})
return
flag
}
function
parseIfStatement(path, test_li, idt, li) {
let
{consequent, alternate, test} = path.node;
if
(consequent && t.isBlockStatement(consequent)
&& t.isIfStatement(consequent.body[0])
&& judge_include_identifier(path.get(
'consequent.body'
)[0].get(
'test'
), idt)
) {
test_li.push(test);
parseIfStatement(path.get(
'consequent.body'
)[0], test_li, idt, li);
test_li.pop();
}
else
{
test_li.push(test);
let
condition = test_li.map(
function
(v) {
return
generator(v).code
}).join(
' && '
);
test_li.pop();
let
case1 = path.node.consequent.body;
li[condition] = case1;
}
if
(alternate && t.isBlockStatement(alternate)
&& t.isIfStatement(alternate.body[0])
&& judge_include_identifier(path.get(
'alternate.body'
)[0].get(
'test'
), idt)
) {
test_li.push(t.UnaryExpression(
'!'
, test));
parseIfStatement(path.get(
'alternate.body'
)[0], test_li, idt, li);
test_li.pop();
}
else
{
test_li.push(t.UnaryExpression(
'!'
, test));
let
condition = test_li.map(
function
(v) {
return
generator(v).code
}).join(
' && '
);
test_li.pop();
let
case1 = path.node.alternate.body;
li[condition] = case1;
}
}
traverse(ast, {
WhileStatement(path) {
let
while_body = path?.get(
'body'
)?.get(
'body'
);
if
(t.isNumericLiteral(path.node.test, {value: 1})
&& while_body && while_body.length == 2
&& while_body[0].isExpressionStatement()
&& while_body[1].isIfStatement()
) {
let
condition_identifier = while_body[0].node.expression.left.name;
let
if_statement = while_body[1];
let
li = {};
parseIfStatement(if_statement, [], condition_identifier, li);
let
cases = [];
let
var_statement_path = path.getSibling(path.key-1);
if
(var_statement_path.isVariableDeclaration()
&& var_statement_path.get(
'declarations'
).at(-1)?.get(
'init'
)?.isArrayExpression()) {
let
index_arr = eval(var_statement_path.get(
'declarations'
).at(-1).get(
'init'
)+
''
);
index_arr = Array.from(
new
Set(index_arr)).sort(
function
(a,b){
return
a-b});
for
(
let
i of index_arr) {
let
flag =
false
;
for
(
var
[test, statement] of Object.entries(li)) {
eval(`
let
${condition_identifier} = i;
if
(${test}) {
res_statement = statement;
flag =
true
;
}
`);
if
(flag)
break
;
}
if
(!flag) {
console.error(
'没有匹配的值:'
, i);
throw
Error(
'没有匹配条件'
);
}
res_statement = Array.from(res_statement);
res_statement.push(t.BreakStatement());
cases.push(t.SwitchCase(t.valueToNode(parseInt(i)), res_statement));
}
}
else
{
console.log(
'没有获取到索引数组,结束!!!!!'
)
}
let
sw = t.SwitchStatement(while_body[0].node.expression.left, cases);
if_statement.replaceWith(sw);
}
}
});
code = generator(ast).code;
fs.writeFileSync(
'./output.js'
, code,{encoding:
'utf-8'
});
console.log(
'耗时=》'
, Date.now() - start);