Skip to content

Commit 84e978f

Browse files
committed
visitor: add split-assignment
Signed-off-by: echo094 <20028238+echo094@users.noreply.github.com>
1 parent f1f40bc commit 84e978f

File tree

12 files changed

+134
-13
lines changed

12 files changed

+134
-13
lines changed

src/plugin/obfuscator.js

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import lintIfStatement from '../visitor/lint-if-statement.js'
1818
import mergeObject from '../visitor/merge-object.js'
1919
import parseControlFlowStorage from '../visitor/parse-control-flow-storage.js'
2020
import pruneIfBranch from '../visitor/prune-if-branch.js'
21+
import splitAssignment from '../visitor/split-assignment.js'
2122
import splitSequence from '../visitor/split-sequence.js'
2223
import splitVarDeclaration from '../visitor/split-variable-declaration.js'
2324

@@ -732,18 +733,6 @@ function cleanDeadCode(ast) {
732733
return ast
733734
}
734735

735-
const splitVariableDeclarator = {
736-
VariableDeclarator(path) {
737-
const init = path.get('init')
738-
if (!init.isAssignmentExpression()) {
739-
return
740-
}
741-
path.parentPath.insertBefore(init.node)
742-
init.replaceWith(init.node.left)
743-
path.parentPath.scope.crawl()
744-
},
745-
}
746-
747736
function standardIfStatement(path) {
748737
const consequent = path.get('consequent')
749738
const alternate = path.get('alternate')
@@ -802,8 +791,8 @@ function purifyCode(ast) {
802791
path.remove()
803792
},
804793
})
794+
traverse(ast, splitAssignment)
805795
// 删除未使用的变量
806-
traverse(ast, splitVariableDeclarator)
807796
traverse(ast, deleteUnusedVar)
808797
// 替换索引器
809798
function FormatMember(path) {

src/visitor/split-assignment.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import * as t from '@babel/types'
2+
3+
/**
4+
* Split the AssignmentExpressions. For example:
5+
*
6+
* - In the test of IfStatement
7+
* - In the VariableDeclaration
8+
*/
9+
export default {
10+
IfStatement(path) {
11+
if (!path.parentPath.isBlockStatement() && !path.parentPath.isProgram()) {
12+
return
13+
}
14+
let test = path.get('test')
15+
if (test.isAssignmentExpression()) {
16+
path.insertBefore(t.expressionStatement(test.node))
17+
test.replaceWith(test.node.left)
18+
path.scope.crawl()
19+
return
20+
}
21+
if (test.isMemberExpression()) {
22+
let object = test.get('object')
23+
if (object.isAssignmentExpression()) {
24+
path.insertBefore(t.expressionStatement(object.node))
25+
object.replaceWith(object.node.left)
26+
}
27+
let property = test.get('property')
28+
if (property.isAssignmentExpression()) {
29+
path.insertBefore(t.expressionStatement(property.node))
30+
property.replaceWith(property.node.left)
31+
}
32+
path.scope.crawl()
33+
}
34+
},
35+
VariableDeclaration(path) {
36+
if (!path.parentPath.isBlockStatement() && !path.parentPath.isProgram()) {
37+
return
38+
}
39+
for (let i = 0; i < path.node.declarations.length; ++i) {
40+
const declaration = path.get(`declarations.${i}`)
41+
const init = declaration.node.init
42+
if (!t.isAssignmentExpression(init)) {
43+
continue
44+
}
45+
path.insertBefore(t.ExpressionStatement(init))
46+
declaration.get('init').replaceWith(init.left)
47+
}
48+
path.scope.crawl()
49+
},
50+
}

test/helper.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import fs from 'fs'
2+
import { expect } from 'vitest'
3+
import { parse } from '@babel/parser'
4+
import generate from '@babel/generator'
5+
import traverse from '@babel/traverse'
6+
7+
export default function (visitor, fix, input) {
8+
const sourceCode = fs.readFileSync(input + '.js', { encoding: 'utf-8' })
9+
const ast = parse(sourceCode)
10+
traverse(ast, visitor)
11+
if (fix) {
12+
const cmpCode = fs.readFileSync(input + '.fix.js', { encoding: 'utf-8' })
13+
expect(generate(ast).code).toBe(cmpCode)
14+
} else {
15+
expect(generate(ast).code).toBe(sourceCode)
16+
}
17+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { join } from 'path'
2+
import { test } from 'vitest'
3+
import getResult from '../helper.js'
4+
import splitAssignment from '#visitor/split-assignment'
5+
6+
const root = join(__dirname, 'split-assignment')
7+
8+
test('if-invalid', () => {
9+
const tc = 'if-invalid'
10+
getResult(splitAssignment, false, join(root, tc))
11+
})
12+
13+
test('if-assignment-valid', () => {
14+
const tc = 'if-assignment-valid'
15+
getResult(splitAssignment, true, join(root, tc))
16+
})
17+
18+
test('if-member-valid', () => {
19+
const tc = 'if-member-valid'
20+
getResult(splitAssignment, true, join(root, tc))
21+
})
22+
23+
test('variable-invalid', () => {
24+
const tc = 'variable-invalid'
25+
getResult(splitAssignment, false, join(root, tc))
26+
})
27+
28+
test('variable-valid', () => {
29+
const tc = 'variable-valid'
30+
getResult(splitAssignment, true, join(root, tc))
31+
})
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
let a = 1;
2+
let b;
3+
b = a;
4+
if (b) {}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
let a = 1;
2+
let b;
3+
if (b = a) {}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
let a = 1;
2+
let b;
3+
while (1) if (b = a) {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
let a = {
2+
b: 1
3+
};
4+
let b;
5+
let c;
6+
b = a;
7+
c = 'b';
8+
if (b[c]) {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
let a = {
2+
b: 1
3+
};
4+
let b;
5+
let c;
6+
if ((b = a)[c = 'b']) {}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
let a = 1;
2+
let b;
3+
for (let c = a = b;;) {}

0 commit comments

Comments
 (0)