js-confuser 1.5.9 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/node.js.yml +2 -2
- package/CHANGELOG.md +55 -0
- package/README.md +346 -165
- package/dist/constants.js +6 -2
- package/dist/index.js +9 -21
- package/dist/obfuscator.js +19 -31
- package/dist/options.js +5 -5
- package/dist/order.js +1 -3
- package/dist/presets.js +6 -7
- package/dist/probability.js +2 -4
- package/dist/templates/bufferToString.js +13 -0
- package/dist/templates/crash.js +3 -3
- package/dist/templates/es5.js +18 -0
- package/dist/templates/functionLength.js +16 -0
- package/dist/transforms/calculator.js +77 -21
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -1
- package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
- package/dist/transforms/deadCode.js +33 -25
- package/dist/transforms/dispatcher.js +8 -4
- package/dist/transforms/es5/antiDestructuring.js +2 -0
- package/dist/transforms/es5/es5.js +31 -34
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +92 -58
- package/dist/transforms/finalizer.js +82 -0
- package/dist/transforms/flatten.js +229 -148
- package/dist/transforms/identifier/globalAnalysis.js +88 -0
- package/dist/transforms/identifier/globalConcealing.js +10 -83
- package/dist/transforms/identifier/movedDeclarations.js +35 -88
- package/dist/transforms/identifier/renameVariables.js +124 -59
- package/dist/transforms/identifier/variableAnalysis.js +58 -62
- package/dist/transforms/lock/lock.js +0 -37
- package/dist/transforms/minify.js +60 -57
- package/dist/transforms/opaquePredicates.js +1 -1
- package/dist/transforms/preparation/preparation.js +2 -2
- package/dist/transforms/preparation.js +231 -0
- package/dist/transforms/renameLabels.js +1 -1
- package/dist/transforms/rgf.js +139 -247
- package/dist/transforms/stack.js +128 -26
- package/dist/transforms/string/encoding.js +150 -179
- package/dist/transforms/string/stringCompression.js +14 -15
- package/dist/transforms/string/stringConcealing.js +25 -8
- package/dist/transforms/string/stringEncoding.js +13 -24
- package/dist/transforms/transform.js +12 -19
- package/dist/traverse.js +24 -10
- package/dist/util/gen.js +17 -1
- package/dist/util/identifiers.js +37 -3
- package/dist/util/insert.js +35 -4
- package/dist/util/random.js +15 -0
- package/docs/ControlFlowFlattening.md +595 -0
- package/{Countermeasures.md → docs/Countermeasures.md} +1 -15
- package/{Integrity.md → docs/Integrity.md} +2 -2
- package/docs/RGF.md +419 -0
- package/package.json +5 -5
- package/src/constants.ts +3 -0
- package/src/index.ts +2 -2
- package/src/obfuscator.ts +19 -31
- package/src/options.ts +14 -103
- package/src/order.ts +1 -5
- package/src/presets.ts +6 -7
- package/src/probability.ts +2 -3
- package/src/templates/bufferToString.ts +68 -0
- package/src/templates/crash.ts +15 -19
- package/src/templates/es5.ts +131 -0
- package/src/templates/functionLength.ts +14 -0
- package/src/transforms/calculator.ts +122 -59
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +4 -1
- package/src/transforms/deadCode.ts +383 -26
- package/src/transforms/dispatcher.ts +9 -4
- package/src/transforms/es5/antiDestructuring.ts +2 -0
- package/src/transforms/es5/es5.ts +32 -77
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +133 -129
- package/src/transforms/{hexadecimalNumbers.ts → finalizer.ts} +29 -13
- package/src/transforms/flatten.ts +357 -300
- package/src/transforms/identifier/globalAnalysis.ts +85 -0
- package/src/transforms/identifier/globalConcealing.ts +14 -103
- package/src/transforms/identifier/movedDeclarations.ts +49 -102
- package/src/transforms/identifier/renameVariables.ts +149 -78
- package/src/transforms/identifier/variableAnalysis.ts +66 -73
- package/src/transforms/lock/lock.ts +1 -42
- package/src/transforms/minify.ts +91 -75
- package/src/transforms/opaquePredicates.ts +2 -2
- package/src/transforms/preparation.ts +238 -0
- package/src/transforms/renameLabels.ts +2 -2
- package/src/transforms/rgf.ts +213 -405
- package/src/transforms/stack.ts +156 -36
- package/src/transforms/string/encoding.ts +115 -212
- package/src/transforms/string/stringCompression.ts +27 -18
- package/src/transforms/string/stringConcealing.ts +39 -9
- package/src/transforms/string/stringEncoding.ts +18 -18
- package/src/transforms/transform.ts +21 -23
- package/src/traverse.ts +23 -4
- package/src/types.ts +2 -1
- package/src/util/gen.ts +28 -3
- package/src/util/identifiers.ts +43 -2
- package/src/util/insert.ts +38 -3
- package/src/util/random.ts +13 -0
- package/test/code/Cash.test.ts +1 -1
- package/test/code/Dynamic.test.ts +12 -10
- package/test/code/ES6.src.js +146 -0
- package/test/code/ES6.test.ts +28 -2
- package/test/index.test.ts +2 -1
- package/test/probability.test.ts +44 -0
- package/test/templates/template.test.ts +1 -1
- package/test/transforms/antiTooling.test.ts +22 -0
- package/test/transforms/calculator.test.ts +40 -0
- package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +702 -160
- package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
- package/test/transforms/deadCode.test.ts +66 -15
- package/test/transforms/dispatcher.test.ts +20 -1
- package/test/transforms/es5/antiDestructuring.test.ts +16 -0
- package/test/transforms/flatten.test.ts +399 -86
- package/test/transforms/identifier/movedDeclarations.test.ts +63 -8
- package/test/transforms/identifier/renameVariables.test.ts +119 -0
- package/test/transforms/lock/antiDebug.test.ts +2 -2
- package/test/transforms/lock/lock.test.ts +1 -48
- package/test/transforms/minify.test.ts +104 -0
- package/test/transforms/preparation.test.ts +157 -0
- package/test/transforms/rgf.test.ts +261 -381
- package/test/transforms/stack.test.ts +143 -21
- package/test/transforms/string/stringCompression.test.ts +39 -0
- package/test/transforms/string/stringConcealing.test.ts +82 -0
- package/test/transforms/string/stringEncoding.test.ts +53 -2
- package/test/transforms/transform.test.ts +66 -0
- package/test/traverse.test.ts +139 -0
- package/test/util/identifiers.test.ts +113 -1
- package/test/util/insert.test.ts +57 -3
- package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
- package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
- package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
- package/src/transforms/eval.ts +0 -89
- package/src/transforms/hideInitializingCode.ts +0 -432
- package/src/transforms/identifier/nameRecycling.ts +0 -280
- package/src/transforms/label.ts +0 -64
- package/src/transforms/preparation/nameConflicts.ts +0 -102
- package/src/transforms/preparation/preparation.ts +0 -176
- package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
- package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
- package/test/transforms/eval.test.ts +0 -131
- package/test/transforms/hideInitializingCode.test.ts +0 -336
- package/test/transforms/identifier/nameRecycling.test.ts +0 -205
- package/test/transforms/preparation/nameConflicts.test.ts +0 -52
- package/test/transforms/preparation/preparation.test.ts +0 -62
|
@@ -9,8 +9,6 @@ var _assert = require("assert");
|
|
|
9
9
|
|
|
10
10
|
var _constants = require("../../constants");
|
|
11
11
|
|
|
12
|
-
var _traverse = require("../../traverse");
|
|
13
|
-
|
|
14
12
|
var _compare = require("../../util/compare");
|
|
15
13
|
|
|
16
14
|
var _identifiers = require("../../util/identifiers");
|
|
@@ -37,10 +35,12 @@ class VariableAnalysis extends _transform.default {
|
|
|
37
35
|
|
|
38
36
|
/**
|
|
39
37
|
* Set of global identifiers to never be redefined
|
|
38
|
+
*
|
|
39
|
+
* - Used to not accidentally block access to a global variable
|
|
40
40
|
*/
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
* Set of
|
|
43
|
+
* Set of identifiers that are defined within the program
|
|
44
44
|
*/
|
|
45
45
|
constructor(o) {
|
|
46
46
|
super(o);
|
|
@@ -60,72 +60,68 @@ class VariableAnalysis extends _transform.default {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
match(object, parents) {
|
|
63
|
-
return
|
|
63
|
+
return object.type === "Identifier";
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
transform(object, parents) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
67
|
+
var name = object.name;
|
|
68
|
+
(0, _assert.ok)(typeof name === "string");
|
|
69
|
+
|
|
70
|
+
if (!(0, _compare.isValidIdentifier)(name)) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (_constants.reservedIdentifiers.has(name)) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (this.options.globalVariables.has(name)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
var info = (0, _identifiers.getIdentifierInfo)(object, parents);
|
|
83
|
+
|
|
84
|
+
if (!info.spec.isReferenced) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (info.spec.isExported) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
var isDefined = info.spec.isDefined; // Keep track of defined names within the program
|
|
93
|
+
|
|
94
|
+
if (isDefined) {
|
|
95
|
+
this.notGlobals.add(object.name);
|
|
96
|
+
this.globals.delete(object.name);
|
|
97
|
+
} else if (!this.notGlobals.has(object.name)) {
|
|
98
|
+
this.globals.add(object.name);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
var definingContexts = info.spec.isDefined ? (0, _insert.getAllDefiningContexts)(object, parents) : (0, _insert.getReferencingContexts)(object, parents, info);
|
|
102
|
+
(0, _assert.ok)(definingContexts.length);
|
|
103
|
+
definingContexts.forEach(definingContext => {
|
|
104
|
+
// ok(
|
|
105
|
+
// isContext(definingContext),
|
|
106
|
+
// `${definingContext.type} is not a context`
|
|
107
|
+
// );
|
|
108
|
+
if (isDefined) {
|
|
109
|
+
// Add to defined Map
|
|
110
|
+
if (!this.defined.has(definingContext)) {
|
|
111
|
+
this.defined.set(definingContext, new Set());
|
|
92
112
|
}
|
|
93
113
|
|
|
94
|
-
|
|
114
|
+
this.defined.get(definingContext).add(name);
|
|
115
|
+
this.references.has(definingContext) && this.references.get(definingContext).delete(name);
|
|
116
|
+
} else {
|
|
117
|
+
// Add to references Map
|
|
118
|
+
if (!this.defined.has(definingContext) || !this.defined.get(definingContext).has(name)) {
|
|
119
|
+
if (!this.references.has(definingContext)) {
|
|
120
|
+
this.references.set(definingContext, new Set());
|
|
121
|
+
}
|
|
95
122
|
|
|
96
|
-
|
|
97
|
-
this.notGlobals.add(o.name);
|
|
98
|
-
this.globals.delete(o.name);
|
|
99
|
-
} else if (!this.notGlobals.has(o.name)) {
|
|
100
|
-
this.globals.add(o.name);
|
|
123
|
+
this.references.get(definingContext).add(name);
|
|
101
124
|
}
|
|
102
|
-
|
|
103
|
-
var definingContexts = info.spec.isDefined ? (0, _insert.getAllDefiningContexts)(o, p) : (0, _insert.getReferencingContexts)(o, p, info);
|
|
104
|
-
(0, _assert.ok)(definingContexts.length);
|
|
105
|
-
definingContexts.forEach(definingContext => {
|
|
106
|
-
// ok(
|
|
107
|
-
// isContext(definingContext),
|
|
108
|
-
// `${definingContext.type} is not a context`
|
|
109
|
-
// );
|
|
110
|
-
if (isDefined) {
|
|
111
|
-
// Add to defined Map
|
|
112
|
-
if (!this.defined.has(definingContext)) {
|
|
113
|
-
this.defined.set(definingContext, new Set());
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
this.defined.get(definingContext).add(name);
|
|
117
|
-
this.references.has(definingContext) && this.references.get(definingContext).delete(name);
|
|
118
|
-
} else {
|
|
119
|
-
// Add to references Map
|
|
120
|
-
if (!this.defined.has(definingContext) || !this.defined.get(definingContext).has(name)) {
|
|
121
|
-
if (!this.references.has(definingContext)) {
|
|
122
|
-
this.references.set(definingContext, new Set());
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
this.references.get(definingContext).add(name);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
125
|
}
|
|
130
126
|
});
|
|
131
127
|
}
|
|
@@ -194,10 +194,6 @@ class Lock extends _transform.default {
|
|
|
194
194
|
choices.push("domainLock");
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
if (this.options.lock.nativeFunctions) {
|
|
198
|
-
choices.push("nativeFunction");
|
|
199
|
-
}
|
|
200
|
-
|
|
201
197
|
if (this.options.lock.context && this.options.lock.context.length) {
|
|
202
198
|
choices.push("context");
|
|
203
199
|
}
|
|
@@ -248,39 +244,6 @@ class Lock extends _transform.default {
|
|
|
248
244
|
nodes.push((0, _gen.IfStatement)(callExpression, this.getCounterMeasuresCode(object, parents) || [], null));
|
|
249
245
|
break;
|
|
250
246
|
|
|
251
|
-
case "nativeFunction":
|
|
252
|
-
var set = this.options.lock.nativeFunctions;
|
|
253
|
-
|
|
254
|
-
if (set === true) {
|
|
255
|
-
if (this.options.target == "node") {
|
|
256
|
-
set = new Set(["Function", "String"]);
|
|
257
|
-
} else {
|
|
258
|
-
set = new Set(["Function", "String", "fetch"]);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
if (Array.isArray(set)) {
|
|
263
|
-
set = new Set(set);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
if (!set) {
|
|
267
|
-
set = new Set();
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
var fn = (0, _random.choice)(Array.from(set));
|
|
271
|
-
|
|
272
|
-
if (fn) {
|
|
273
|
-
test = (0, _template.default)("(".concat(fn, "+\"\").indexOf(\"[native code]\") == -1")).single().expression;
|
|
274
|
-
|
|
275
|
-
if (Math.random() > 0.5) {
|
|
276
|
-
test = (0, _template.default)("".concat(fn, ".toString().split(\"{ [native code] }\").length <= 1")).single().expression;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
break;
|
|
283
|
-
|
|
284
247
|
case "startDate":
|
|
285
248
|
test = (0, _gen.BinaryExpression)("<", dateNow, (0, _gen.Literal)(this.getTime(this.options.lock.startDate)));
|
|
286
249
|
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
|
|
@@ -78,7 +78,7 @@ class Minify extends _transform.default {
|
|
|
78
78
|
var startIndex = -1;
|
|
79
79
|
var sequences = [];
|
|
80
80
|
body.forEach((stmt, i) => {
|
|
81
|
-
if (stmt.type == "ExpressionStatement") {
|
|
81
|
+
if (stmt.type == "ExpressionStatement" && !stmt.directive) {
|
|
82
82
|
exprs.push(stmt.expression);
|
|
83
83
|
|
|
84
84
|
if (startIndex == -1) {
|
|
@@ -108,48 +108,44 @@ class Minify extends _transform.default {
|
|
|
108
108
|
(0, _assert.ok)(seq.index != -1);
|
|
109
109
|
body.splice(seq.index, seq.exprs.length, (0, _gen.ExpressionStatement)(seq.exprs.length == 1 ? seq.exprs[0] : (0, _gen.SequenceExpression)(seq.exprs)));
|
|
110
110
|
});
|
|
111
|
-
}
|
|
111
|
+
} // Unnecessary return
|
|
112
112
|
|
|
113
|
-
if (object.type != "SwitchCase") {
|
|
114
|
-
// Unnecessary return
|
|
115
|
-
if (body.length && body[body.length - 1]) {
|
|
116
|
-
var last = body[body.length - 1];
|
|
117
113
|
|
|
118
|
-
|
|
119
|
-
|
|
114
|
+
if (parents[0] && (0, _insert.isVarContext)(parents[0]) && body.length && body[body.length - 1]) {
|
|
115
|
+
var last = body[body.length - 1];
|
|
120
116
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
117
|
+
if (last.type == "ReturnStatement") {
|
|
118
|
+
var isUndefined = last.argument == null;
|
|
119
|
+
|
|
120
|
+
if (isUndefined) {
|
|
121
|
+
body.pop();
|
|
126
122
|
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
lastDec.declarations.push(...(0, _insert.clone)(x.declarations));
|
|
143
|
-
remove.unshift(i);
|
|
144
|
-
}
|
|
123
|
+
}
|
|
124
|
+
} // Variable declaration grouping
|
|
125
|
+
// var a = 1;
|
|
126
|
+
// var b = 1;
|
|
127
|
+
// var c = 1;
|
|
128
|
+
//
|
|
129
|
+
// var a=1,b=1,c=1;
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
var lastDec = null;
|
|
133
|
+
var remove = [];
|
|
134
|
+
body.forEach((x, i) => {
|
|
135
|
+
if (x.type === "VariableDeclaration") {
|
|
136
|
+
if (!lastDec || lastDec.kind !== x.kind || !lastDec.declarations.length) {
|
|
137
|
+
lastDec = x;
|
|
145
138
|
} else {
|
|
146
|
-
lastDec
|
|
139
|
+
lastDec.declarations.push(...(0, _insert.clone)(x.declarations));
|
|
140
|
+
remove.unshift(i);
|
|
147
141
|
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
142
|
+
} else {
|
|
143
|
+
lastDec = null;
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
remove.forEach(x => {
|
|
147
|
+
body.splice(x, 1);
|
|
148
|
+
});
|
|
153
149
|
};
|
|
154
150
|
}
|
|
155
151
|
/**
|
|
@@ -172,29 +168,30 @@ class Minify extends _transform.default {
|
|
|
172
168
|
}
|
|
173
169
|
}
|
|
174
170
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (blockIndex !== -1) {
|
|
178
|
-
var block = parents[blockIndex];
|
|
179
|
-
var body = block.body;
|
|
171
|
+
if (object.type === "FunctionDeclaration") {
|
|
172
|
+
var body = parents[0];
|
|
180
173
|
|
|
181
174
|
if (!Array.isArray(body)) {
|
|
182
175
|
return;
|
|
183
176
|
}
|
|
184
177
|
|
|
185
|
-
var
|
|
186
|
-
var index = body.indexOf(stmt);
|
|
178
|
+
var index = body.indexOf(object);
|
|
187
179
|
|
|
188
180
|
if (index == -1) {
|
|
189
181
|
return;
|
|
190
182
|
}
|
|
191
183
|
|
|
192
184
|
var before = body.slice(0, index);
|
|
193
|
-
(0, _assert.ok)(!before.includes(
|
|
194
|
-
var
|
|
195
|
-
|
|
185
|
+
(0, _assert.ok)(!before.includes(object));
|
|
186
|
+
var beforeTypes = new Set(before.map(x => x.type));
|
|
187
|
+
beforeTypes.delete("FunctionDeclaration");
|
|
188
|
+
|
|
189
|
+
if (beforeTypes.size > 0) {
|
|
190
|
+
return;
|
|
191
|
+
} // Test Variant #25: Don't break redefined function declaration
|
|
192
|
+
|
|
196
193
|
|
|
197
|
-
if (
|
|
194
|
+
if (object.id && body.find(x => x.type === "FunctionDeclaration" && x !== object && x.id && x.id.name === object.id.name)) {
|
|
198
195
|
return;
|
|
199
196
|
}
|
|
200
197
|
}
|
|
@@ -217,11 +214,11 @@ class Minify extends _transform.default {
|
|
|
217
214
|
if (canTransform) {
|
|
218
215
|
if (!this.arrowFunctionName) {
|
|
219
216
|
this.arrowFunctionName = this.getPlaceholder();
|
|
220
|
-
(0, _insert.append)(parents[parents.length - 1] || object, (0, _template.default)("\n function ".concat(this.arrowFunctionName, "(arrowFn){\n
|
|
217
|
+
(0, _insert.append)(parents[parents.length - 1] || object, (0, _template.default)("\n function ".concat(this.arrowFunctionName, "(arrowFn, functionLength){\n var functionObject = function(){ return arrowFn(...arguments) };\n\n Object[\"defineProperty\"](functionObject, \"length\", {\n \"value\": functionLength,\n \"configurable\": true\n });\n\n return functionObject;\n }\n ")).single());
|
|
221
218
|
}
|
|
222
219
|
|
|
223
220
|
const wrap = object => {
|
|
224
|
-
return (0, _gen.CallExpression)((0, _gen.Identifier)(this.arrowFunctionName), [(0, _insert.clone)(object)]);
|
|
221
|
+
return (0, _gen.CallExpression)((0, _gen.Identifier)(this.arrowFunctionName), [(0, _insert.clone)(object), (0, _gen.Literal)((0, _insert.computeFunctionLength)(object.params))]);
|
|
225
222
|
};
|
|
226
223
|
|
|
227
224
|
if (object.type == "FunctionExpression") {
|
|
@@ -253,7 +250,7 @@ class Minify extends _transform.default {
|
|
|
253
250
|
|
|
254
251
|
if (body.length == 1 && stmt1.type == "ReturnStatement") {
|
|
255
252
|
// x=>{a: 1} // Invalid syntax
|
|
256
|
-
if (stmt1.argument.type != "ObjectExpression") {
|
|
253
|
+
if (stmt1.argument && stmt1.argument.type != "ObjectExpression") {
|
|
257
254
|
object.body = stmt1.argument;
|
|
258
255
|
object.expression = true;
|
|
259
256
|
}
|
|
@@ -421,8 +418,16 @@ class Minify extends _transform.default {
|
|
|
421
418
|
if (property.type == "Literal" && (0, _compare.isValidIdentifier)(property.value)) {
|
|
422
419
|
object.computed = false;
|
|
423
420
|
object.property.type = "Identifier";
|
|
424
|
-
object.property.name = (0, _insert.clone)(object.property.value);
|
|
425
|
-
|
|
421
|
+
object.property.name = (0, _insert.clone)(object.property.value); // obj.name &&
|
|
422
|
+
// this.log(
|
|
423
|
+
// obj.name +
|
|
424
|
+
// "['" +
|
|
425
|
+
// object.property.name +
|
|
426
|
+
// "'] -> " +
|
|
427
|
+
// obj.name +
|
|
428
|
+
// "." +
|
|
429
|
+
// object.property.name
|
|
430
|
+
// );
|
|
426
431
|
}
|
|
427
432
|
}
|
|
428
433
|
|
|
@@ -437,18 +442,16 @@ class Minify extends _transform.default {
|
|
|
437
442
|
} // { "x": 1 } -> {x: 1}
|
|
438
443
|
|
|
439
444
|
|
|
440
|
-
if (object.type
|
|
445
|
+
if (object.type === "Property" || object.type === "MethodDefinition") {
|
|
441
446
|
if (object.key.type == "SequenceExpression" && object.key.expressions.length == 1) {
|
|
442
447
|
object.key = object.key.expressions[0];
|
|
443
448
|
object.computed = true;
|
|
444
449
|
}
|
|
445
450
|
|
|
446
|
-
if (object.key.type == "Literal" && (0, _compare.isValidIdentifier)(object.key.value)) {
|
|
451
|
+
if (object.key.type == "Literal" && typeof object.key.value === "string" && (0, _compare.isValidIdentifier)(object.key.value)) {
|
|
447
452
|
object.key.type = "Identifier";
|
|
448
453
|
object.key.name = object.key.value;
|
|
449
454
|
object.computed = false;
|
|
450
|
-
} else if (object.key.type == "Identifier" && !(0, _compare.isValidIdentifier)(object.key.name)) {
|
|
451
|
-
object.key = (0, _gen.Literal)(object.key.name);
|
|
452
455
|
}
|
|
453
456
|
}
|
|
454
457
|
|
|
@@ -66,7 +66,7 @@ class OpaquePredicates extends _transform.default {
|
|
|
66
66
|
_defineProperty(this, "made", void 0);
|
|
67
67
|
|
|
68
68
|
this.predicates = Object.create(null);
|
|
69
|
-
this.gen = this.getGenerator(
|
|
69
|
+
this.gen = this.getGenerator();
|
|
70
70
|
this.made = 0;
|
|
71
71
|
}
|
|
72
72
|
|
|
@@ -103,9 +103,9 @@ class ExplicitIdentifiers extends _transform.default {
|
|
|
103
103
|
if (parents[propIndex].type == "MethodDefinition" && parents[propIndex].kind == "constructor") {
|
|
104
104
|
return;
|
|
105
105
|
}
|
|
106
|
-
}
|
|
106
|
+
} // this.log(object.name, "->", `'${object.name}'`);
|
|
107
|
+
|
|
107
108
|
|
|
108
|
-
this.log(object.name, "->", "'".concat(object.name, "'"));
|
|
109
109
|
this.replace(object, (0, _gen.Literal)(object.name));
|
|
110
110
|
parents[0].computed = true;
|
|
111
111
|
parents[0].shorthand = false;
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _transform = _interopRequireDefault(require("./transform"));
|
|
9
|
+
|
|
10
|
+
var _gen = require("../util/gen");
|
|
11
|
+
|
|
12
|
+
var _order = require("../order");
|
|
13
|
+
|
|
14
|
+
var _insert = require("../util/insert");
|
|
15
|
+
|
|
16
|
+
var _identifiers = require("../util/identifiers");
|
|
17
|
+
|
|
18
|
+
var _compare = require("../util/compare");
|
|
19
|
+
|
|
20
|
+
var _traverse = require("../traverse");
|
|
21
|
+
|
|
22
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Preparation arranges the user's code into an AST the obfuscator can easily transform.
|
|
26
|
+
*
|
|
27
|
+
* ExplicitIdentifiers
|
|
28
|
+
* - `object.IDENTIFIER` -> `object['IDENTIFIER']` // Now String Concealing can apply on it
|
|
29
|
+
* - `{ IDENTIFIER: ... }` -> `{ "IDENTIFIER": ... }`
|
|
30
|
+
*
|
|
31
|
+
* ExplicitDeclarations
|
|
32
|
+
* - `var a,b,c` -> `var a; var b; var c;` // Now Stack can apply on it
|
|
33
|
+
*
|
|
34
|
+
* Block
|
|
35
|
+
* - `x => x * 2` -> `x => { return x * 2 }` // Change into Block Statements
|
|
36
|
+
* - `if(true) return` -> `if (true) { return }`
|
|
37
|
+
* - `while(a) a--;` -> `while(a) { a-- }`
|
|
38
|
+
*
|
|
39
|
+
* Label
|
|
40
|
+
* - `for(...) { break; }` -> `_1: for(...) { break _1; }`
|
|
41
|
+
* - `switch(v) { case 1...break }` -> `_2: switch(v) { case 1...break _2; }`
|
|
42
|
+
* - // Control Flow Flattening can safely apply now
|
|
43
|
+
*/
|
|
44
|
+
class Preparation extends _transform.default {
|
|
45
|
+
constructor(o) {
|
|
46
|
+
super(o, _order.ObfuscateOrder.Preparation);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
match(object, parents) {
|
|
50
|
+
return !!object.type;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
transform(object, parents) {
|
|
54
|
+
// ExplicitIdentifiers
|
|
55
|
+
if (object.type === "Identifier") {
|
|
56
|
+
return this.transformExplicitIdentifiers(object, parents);
|
|
57
|
+
} // ExplicitDeclarations
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
if (object.type === "VariableDeclaration") {
|
|
61
|
+
return this.transformExplicitDeclarations(object, parents);
|
|
62
|
+
} // Block
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
switch (object.type) {
|
|
66
|
+
/**
|
|
67
|
+
* People use shortcuts and its harder to parse.
|
|
68
|
+
*
|
|
69
|
+
* - `if (a) b()` -> `if (a) { b() }`
|
|
70
|
+
* - Ensures all bodies are `BlockStatement`, not individual expression statements
|
|
71
|
+
*/
|
|
72
|
+
case "IfStatement":
|
|
73
|
+
if (object.consequent.type != "BlockStatement") {
|
|
74
|
+
object.consequent = (0, _gen.BlockStatement)([(0, _insert.clone)(object.consequent)]);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (object.alternate && object.alternate.type != "BlockStatement") {
|
|
78
|
+
object.alternate = (0, _gen.BlockStatement)([(0, _insert.clone)(object.alternate)]);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
break;
|
|
82
|
+
|
|
83
|
+
case "WhileStatement":
|
|
84
|
+
case "WithStatement":
|
|
85
|
+
case "ForStatement":
|
|
86
|
+
case "ForOfStatement":
|
|
87
|
+
case "ForInStatement":
|
|
88
|
+
if (object.body.type != "BlockStatement") {
|
|
89
|
+
object.body = (0, _gen.BlockStatement)([(0, _insert.clone)(object.body)]);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
break;
|
|
93
|
+
|
|
94
|
+
case "ArrowFunctionExpression":
|
|
95
|
+
if (object.body.type !== "BlockStatement" && object.expression) {
|
|
96
|
+
object.body = (0, _gen.BlockStatement)([(0, _gen.ReturnStatement)((0, _insert.clone)(object.body))]);
|
|
97
|
+
object.expression = false;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
break;
|
|
101
|
+
} // Label
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
if ((0, _compare.isLoop)(object) || object.type == "BlockStatement" && parents[0] && parents[0].type == "LabeledStatement" && parents[0].body === object) {
|
|
105
|
+
return this.transformLabel(object, parents);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Ensures every break; statement has a label to point to.
|
|
110
|
+
*
|
|
111
|
+
* This is because Control Flow Flattening adds For Loops which label-less break statements point to the nearest,
|
|
112
|
+
* when they actually need to point to the original statement.
|
|
113
|
+
*/
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
transformLabel(object, parents) {
|
|
117
|
+
return () => {
|
|
118
|
+
var currentLabel = parents[0].type == "LabeledStatement" && parents[0].label.name;
|
|
119
|
+
var label = currentLabel || this.getPlaceholder();
|
|
120
|
+
(0, _traverse.walk)(object, parents, (o, p) => {
|
|
121
|
+
if (o.type == "BreakStatement" || o.type == "ContinueStatement") {
|
|
122
|
+
function isContinuableStatement(x) {
|
|
123
|
+
return (0, _compare.isLoop)(x) && x.type !== "SwitchStatement";
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function isBreakableStatement(x) {
|
|
127
|
+
return (0, _compare.isLoop)(x) || o.label && x.type == "BlockStatement";
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
var fn = o.type == "ContinueStatement" ? isContinuableStatement : isBreakableStatement;
|
|
131
|
+
var loop = p.find(fn);
|
|
132
|
+
|
|
133
|
+
if (object == loop) {
|
|
134
|
+
if (!o.label) {
|
|
135
|
+
o.label = (0, _gen.Identifier)(label);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}); // Append label statement as this loop has none
|
|
140
|
+
|
|
141
|
+
if (!currentLabel) {
|
|
142
|
+
this.replace(object, (0, _gen.LabeledStatement)(label, { ...object
|
|
143
|
+
}));
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Transforms Identifiers (a.IDENTIFIER, {IDENTIFIER:...}) into string properties
|
|
149
|
+
*/
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
transformExplicitIdentifiers(object, parents) {
|
|
153
|
+
// Mark functions containing 'eval'
|
|
154
|
+
// Some transformations avoid functions that have 'eval' to not break them
|
|
155
|
+
if (object.name === "eval") {
|
|
156
|
+
var fn = (0, _insert.getFunction)(object, parents);
|
|
157
|
+
|
|
158
|
+
if (fn) {
|
|
159
|
+
fn.$requiresEval = true;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
var info = (0, _identifiers.getIdentifierInfo)(object, parents);
|
|
164
|
+
|
|
165
|
+
if (info.isPropertyKey || info.isAccessor) {
|
|
166
|
+
var propIndex = parents.findIndex(x => x.type == "MethodDefinition" || x.type == "Property"); // Don't change constructor!
|
|
167
|
+
|
|
168
|
+
if (propIndex !== -1) {
|
|
169
|
+
if (parents[propIndex].type == "MethodDefinition" && parents[propIndex].kind == "constructor") {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
this.replace(object, (0, _gen.Literal)(object.name));
|
|
175
|
+
parents[0].computed = true;
|
|
176
|
+
parents[0].shorthand = false;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Transforms VariableDeclaration into single declarations.
|
|
181
|
+
*/
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
transformExplicitDeclarations(object, parents) {
|
|
185
|
+
// for ( var x in ... ) {...}
|
|
186
|
+
var forIndex = parents.findIndex(x => x.type == "ForInStatement" || x.type == "ForOfStatement");
|
|
187
|
+
|
|
188
|
+
if (forIndex != -1 && parents[forIndex].left == (parents[forIndex - 1] || object)) {
|
|
189
|
+
object.declarations.forEach(x => {
|
|
190
|
+
x.init = null;
|
|
191
|
+
});
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
var body = parents[0];
|
|
196
|
+
|
|
197
|
+
if ((0, _compare.isLoop)(body) || body.type == "LabeledStatement") {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (body.type == "ExportNamedDeclaration") {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (!Array.isArray(body)) {
|
|
206
|
+
this.error(new Error("body is " + body.type));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (object.declarations.length > 1) {
|
|
210
|
+
// Make singular
|
|
211
|
+
var index = body.indexOf(object);
|
|
212
|
+
|
|
213
|
+
if (index == -1) {
|
|
214
|
+
this.error(new Error("index is -1"));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
var after = object.declarations.slice(1);
|
|
218
|
+
body.splice(index + 1, 0, ...after.map(x => {
|
|
219
|
+
return {
|
|
220
|
+
type: "VariableDeclaration",
|
|
221
|
+
declarations: [(0, _insert.clone)(x)],
|
|
222
|
+
kind: object.kind
|
|
223
|
+
};
|
|
224
|
+
}));
|
|
225
|
+
object.declarations.length = 1;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
exports.default = Preparation;
|