js-confuser 1.5.8 → 1.6.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.
Files changed (139) hide show
  1. package/.github/workflows/node.js.yml +2 -2
  2. package/CHANGELOG.md +69 -0
  3. package/README.md +143 -7
  4. package/dist/index.js +33 -4
  5. package/dist/obfuscator.js +30 -31
  6. package/dist/options.js +4 -5
  7. package/dist/order.js +4 -6
  8. package/dist/probability.js +2 -4
  9. package/dist/templates/bufferToString.js +13 -0
  10. package/dist/templates/crash.js +2 -2
  11. package/dist/templates/es5.js +18 -0
  12. package/dist/transforms/antiTooling.js +1 -1
  13. package/dist/transforms/calculator.js +77 -21
  14. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
  15. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +8 -3
  16. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
  17. package/dist/transforms/deadCode.js +33 -25
  18. package/dist/transforms/dispatcher.js +7 -6
  19. package/dist/transforms/es5/antiClass.js +6 -2
  20. package/dist/transforms/es5/antiDestructuring.js +3 -1
  21. package/dist/transforms/es5/es5.js +31 -34
  22. package/dist/transforms/eval.js +11 -0
  23. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +8 -5
  24. package/dist/transforms/extraction/objectExtraction.js +6 -1
  25. package/dist/transforms/finalizer.js +82 -0
  26. package/dist/transforms/flatten.js +82 -55
  27. package/dist/transforms/hexadecimalNumbers.js +34 -9
  28. package/dist/transforms/identifier/globalAnalysis.js +88 -0
  29. package/dist/transforms/identifier/globalConcealing.js +10 -83
  30. package/dist/transforms/identifier/movedDeclarations.js +2 -8
  31. package/dist/transforms/identifier/renameVariables.js +39 -27
  32. package/dist/transforms/identifier/variableAnalysis.js +58 -62
  33. package/dist/transforms/minify.js +80 -61
  34. package/dist/transforms/opaquePredicates.js +1 -1
  35. package/dist/transforms/preparation/preparation.js +2 -2
  36. package/dist/transforms/preparation.js +231 -0
  37. package/dist/transforms/renameLabels.js +1 -1
  38. package/dist/transforms/rgf.js +4 -5
  39. package/dist/transforms/stack.js +87 -26
  40. package/dist/transforms/string/encoding.js +150 -179
  41. package/dist/transforms/string/stringCompression.js +14 -15
  42. package/dist/transforms/string/stringConcealing.js +25 -8
  43. package/dist/transforms/string/stringEncoding.js +13 -24
  44. package/dist/transforms/transform.js +11 -18
  45. package/dist/traverse.js +24 -18
  46. package/dist/util/compare.js +2 -2
  47. package/dist/util/gen.js +15 -0
  48. package/dist/util/insert.js +31 -7
  49. package/dist/util/random.js +15 -0
  50. package/package.json +5 -5
  51. package/src/index.ts +57 -19
  52. package/src/obfuscator.ts +26 -29
  53. package/src/options.ts +17 -21
  54. package/src/order.ts +4 -8
  55. package/src/probability.ts +2 -3
  56. package/src/templates/bufferToString.ts +68 -0
  57. package/src/templates/crash.ts +5 -9
  58. package/src/templates/es5.ts +131 -0
  59. package/src/transforms/antiTooling.ts +1 -1
  60. package/src/transforms/calculator.ts +122 -59
  61. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
  62. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +18 -3
  63. package/src/transforms/deadCode.ts +383 -26
  64. package/src/transforms/dispatcher.ts +8 -6
  65. package/src/transforms/es5/antiClass.ts +10 -1
  66. package/src/transforms/es5/antiDestructuring.ts +3 -1
  67. package/src/transforms/es5/es5.ts +32 -77
  68. package/src/transforms/eval.ts +18 -0
  69. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +9 -6
  70. package/src/transforms/extraction/objectExtraction.ts +12 -5
  71. package/src/transforms/finalizer.ts +75 -0
  72. package/src/transforms/flatten.ts +194 -151
  73. package/src/transforms/identifier/globalAnalysis.ts +85 -0
  74. package/src/transforms/identifier/globalConcealing.ts +14 -103
  75. package/src/transforms/identifier/movedDeclarations.ts +4 -11
  76. package/src/transforms/identifier/renameVariables.ts +37 -30
  77. package/src/transforms/identifier/variableAnalysis.ts +66 -73
  78. package/src/transforms/minify.ts +116 -77
  79. package/src/transforms/opaquePredicates.ts +2 -2
  80. package/src/transforms/preparation.ts +238 -0
  81. package/src/transforms/renameLabels.ts +2 -2
  82. package/src/transforms/rgf.ts +6 -7
  83. package/src/transforms/stack.ts +97 -37
  84. package/src/transforms/string/encoding.ts +115 -212
  85. package/src/transforms/string/stringCompression.ts +27 -18
  86. package/src/transforms/string/stringConcealing.ts +41 -11
  87. package/src/transforms/string/stringEncoding.ts +18 -18
  88. package/src/transforms/transform.ts +15 -21
  89. package/src/traverse.ts +24 -12
  90. package/src/types.ts +11 -2
  91. package/src/util/compare.ts +2 -2
  92. package/src/util/gen.ts +21 -1
  93. package/src/util/insert.ts +49 -9
  94. package/src/util/random.ts +13 -0
  95. package/test/code/Cash.test.ts +1 -1
  96. package/test/code/Dynamic.test.ts +12 -10
  97. package/test/code/ES6.src.js +136 -0
  98. package/test/code/ES6.test.ts +28 -2
  99. package/test/code/NewFeatures.test.ts +19 -0
  100. package/test/index.test.ts +15 -2
  101. package/test/probability.test.ts +44 -0
  102. package/test/templates/template.test.ts +1 -1
  103. package/test/transforms/antiTooling.test.ts +52 -0
  104. package/test/transforms/calculator.test.ts +40 -0
  105. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +713 -149
  106. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
  107. package/test/transforms/deadCode.test.ts +66 -15
  108. package/test/transforms/dispatcher.test.ts +44 -1
  109. package/test/transforms/es5/antiClass.test.ts +33 -0
  110. package/test/transforms/es5/antiDestructuring.test.ts +16 -0
  111. package/test/transforms/eval.test.ts +53 -0
  112. package/test/transforms/extraction/objectExtraction.test.ts +21 -0
  113. package/test/transforms/flatten.test.ts +195 -3
  114. package/test/transforms/identifier/movedDeclarations.test.ts +27 -0
  115. package/test/transforms/identifier/renameVariables.test.ts +108 -0
  116. package/test/transforms/lock/antiDebug.test.ts +2 -2
  117. package/test/transforms/minify.test.ts +151 -0
  118. package/test/transforms/preparation.test.ts +157 -0
  119. package/test/transforms/rgf.test.ts +56 -29
  120. package/test/transforms/stack.test.ts +91 -21
  121. package/test/transforms/string/stringCompression.test.ts +39 -0
  122. package/test/transforms/string/stringConcealing.test.ts +115 -0
  123. package/test/transforms/string/stringEncoding.test.ts +53 -2
  124. package/test/transforms/transform.test.ts +66 -0
  125. package/test/traverse.test.ts +139 -0
  126. package/test/util/compare.test.ts +23 -1
  127. package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
  128. package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
  129. package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
  130. package/src/transforms/hexadecimalNumbers.ts +0 -31
  131. package/src/transforms/hideInitializingCode.ts +0 -432
  132. package/src/transforms/label.ts +0 -64
  133. package/src/transforms/preparation/nameConflicts.ts +0 -102
  134. package/src/transforms/preparation/preparation.ts +0 -176
  135. package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
  136. package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
  137. package/test/transforms/hideInitializingCode.test.ts +0 -336
  138. package/test/transforms/preparation/nameConflicts.test.ts +0 -52
  139. package/test/transforms/preparation/preparation.test.ts +0 -62
@@ -2,7 +2,6 @@ import Transform from "./transform";
2
2
  import { ObfuscateOrder } from "../order";
3
3
  import {
4
4
  Node,
5
- Location,
6
5
  VariableDeclaration,
7
6
  BinaryExpression,
8
7
  ExpressionStatement,
@@ -15,18 +14,20 @@ import {
15
14
  AssignmentExpression,
16
15
  VariableDeclarator,
17
16
  Identifier,
17
+ CallExpression,
18
18
  } from "../util/gen";
19
19
  import {
20
20
  getBlockBody,
21
21
  clone,
22
22
  isForInitialize,
23
- isLexContext,
24
- getFunction,
23
+ append,
24
+ isVarContext,
25
25
  } from "../util/insert";
26
26
  import { isValidIdentifier, isEquivalent } from "../util/compare";
27
27
  import { walk, isBlock } from "../traverse";
28
28
  import { ok } from "assert";
29
29
  import { isLexicalScope } from "../util/scope";
30
+ import Template from "../templates/template";
30
31
 
31
32
  /**
32
33
  * Basic transformations to reduce code size.
@@ -37,12 +38,13 @@ import { isLexicalScope } from "../util/scope";
37
38
  * - `x['y']` **->** `x.y`
38
39
  */
39
40
  export default class Minify extends Transform {
40
- variables: Map<Node, Location[]>;
41
+ /**
42
+ * A helper function that is introduced preserve function semantics
43
+ */
44
+ arrowFunctionName: string;
41
45
 
42
46
  constructor(o) {
43
47
  super(o, ObfuscateOrder.Minify);
44
-
45
- this.variables = new Map();
46
48
  }
47
49
 
48
50
  match(object: Node, parents: Node[]) {
@@ -92,7 +94,7 @@ export default class Minify extends Transform {
92
94
  var sequences: { index: number; exprs: Node[] }[] = [];
93
95
 
94
96
  body.forEach((stmt, i) => {
95
- if (stmt.type == "ExpressionStatement") {
97
+ if (stmt.type == "ExpressionStatement" && !stmt.directive) {
96
98
  exprs.push(stmt.expression);
97
99
  if (startIndex == -1) {
98
100
  startIndex = i;
@@ -124,51 +126,52 @@ export default class Minify extends Transform {
124
126
  });
125
127
  }
126
128
 
127
- if (object.type != "SwitchCase") {
128
- // Unnecessary return
129
- if (body.length && body[body.length - 1]) {
130
- var last = body[body.length - 1];
131
- if (last.type == "ReturnStatement") {
132
- var isUndefined = last.argument == null;
133
-
134
- if (isUndefined) {
135
- if (getFunction(object, parents).body == object) {
136
- body.pop();
137
- }
138
- }
129
+ // Unnecessary return
130
+ if (
131
+ parents[0] &&
132
+ isVarContext(parents[0]) &&
133
+ body.length &&
134
+ body[body.length - 1]
135
+ ) {
136
+ var last = body[body.length - 1];
137
+ if (last.type == "ReturnStatement") {
138
+ var isUndefined = last.argument == null;
139
+
140
+ if (isUndefined) {
141
+ body.pop();
139
142
  }
140
143
  }
144
+ }
141
145
 
142
- // Variable declaration grouping
143
- // var a = 1;
144
- // var b = 1;
145
- // var c = 1;
146
- //
147
- // var a=1,b=1,c=1;
148
- var lastDec = null;
149
-
150
- var remove = [];
151
- body.forEach((x, i) => {
152
- if (x.type === "VariableDeclaration") {
153
- if (
154
- !lastDec ||
155
- lastDec.kind !== x.kind ||
156
- !lastDec.declarations.length
157
- ) {
158
- lastDec = x;
159
- } else {
160
- lastDec.declarations.push(...clone(x.declarations));
161
- remove.unshift(i);
162
- }
146
+ // Variable declaration grouping
147
+ // var a = 1;
148
+ // var b = 1;
149
+ // var c = 1;
150
+ //
151
+ // var a=1,b=1,c=1;
152
+ var lastDec = null;
153
+
154
+ var remove = [];
155
+ body.forEach((x, i) => {
156
+ if (x.type === "VariableDeclaration") {
157
+ if (
158
+ !lastDec ||
159
+ lastDec.kind !== x.kind ||
160
+ !lastDec.declarations.length
161
+ ) {
162
+ lastDec = x;
163
163
  } else {
164
- lastDec = null;
164
+ lastDec.declarations.push(...clone(x.declarations));
165
+ remove.unshift(i);
165
166
  }
166
- });
167
+ } else {
168
+ lastDec = null;
169
+ }
170
+ });
167
171
 
168
- remove.forEach((x) => {
169
- body.splice(x, 1);
170
- });
171
- }
172
+ remove.forEach((x) => {
173
+ body.splice(x, 1);
174
+ });
172
175
  };
173
176
  }
174
177
 
@@ -198,28 +201,38 @@ export default class Minify extends Transform {
198
201
  }
199
202
  }
200
203
 
201
- var blockIndex = parents.findIndex((x) => isLexContext(x));
202
- if (blockIndex !== -1) {
203
- var block = parents[blockIndex];
204
- var body = block.body;
204
+ if (object.type === "FunctionDeclaration") {
205
+ var body = parents[0];
205
206
  if (!Array.isArray(body)) {
206
207
  return;
207
208
  }
208
209
 
209
- var stmt = parents[blockIndex - 2] || object;
210
-
211
- var index = body.indexOf(stmt);
210
+ var index = body.indexOf(object);
212
211
  if (index == -1) {
213
212
  return;
214
213
  }
215
214
 
216
215
  var before = body.slice(0, index);
217
- ok(!before.includes(stmt));
216
+ ok(!before.includes(object));
218
217
 
219
- var set = new Set(before.map((x) => x.type));
220
- set.delete("FunctionDeclaration");
218
+ var beforeTypes = new Set(before.map((x) => x.type));
219
+ beforeTypes.delete("FunctionDeclaration");
221
220
 
222
- if (set.size) {
221
+ if (beforeTypes.size > 0) {
222
+ return;
223
+ }
224
+
225
+ // Test Variant #25: Don't break redefined function declaration
226
+ if (
227
+ object.id &&
228
+ body.find(
229
+ (x) =>
230
+ x.type === "FunctionDeclaration" &&
231
+ x !== object &&
232
+ x.id &&
233
+ x.id.name === object.id.name
234
+ )
235
+ ) {
223
236
  return;
224
237
  }
225
238
  }
@@ -239,17 +252,42 @@ export default class Minify extends Transform {
239
252
  });
240
253
 
241
254
  if (canTransform) {
255
+ if (!this.arrowFunctionName) {
256
+ this.arrowFunctionName = this.getPlaceholder();
257
+
258
+ append(
259
+ parents[parents.length - 1] || object,
260
+ Template(`
261
+ function ${this.arrowFunctionName}(arrowFn){
262
+ return function(){ return arrowFn(...arguments) }
263
+ }
264
+ `).single()
265
+ );
266
+ }
267
+
268
+ const wrap = (object: Node) => {
269
+ return CallExpression(Identifier(this.arrowFunctionName), [
270
+ clone(object),
271
+ ]);
272
+ };
273
+
242
274
  if (object.type == "FunctionExpression") {
243
275
  object.type = "ArrowFunctionExpression";
276
+
277
+ this.replace(object, wrap(clone(object)));
244
278
  } else {
245
279
  var arrow = { ...clone(object), type: "ArrowFunctionExpression" };
246
280
  this.replace(
247
281
  object,
248
- VariableDeclaration(VariableDeclarator(object.id.name, arrow))
282
+ VariableDeclaration(
283
+ VariableDeclarator(object.id.name, wrap(arrow))
284
+ )
249
285
  );
250
286
 
251
287
  var x = this.transform(arrow, []);
252
- x();
288
+ if (typeof x === "function") {
289
+ x();
290
+ }
253
291
  }
254
292
  }
255
293
  };
@@ -268,7 +306,7 @@ export default class Minify extends Transform {
268
306
 
269
307
  if (body.length == 1 && stmt1.type == "ReturnStatement") {
270
308
  // x=>{a: 1} // Invalid syntax
271
- if (stmt1.argument.type != "ObjectExpression") {
309
+ if (stmt1.argument && stmt1.argument.type != "ObjectExpression") {
272
310
  object.body = stmt1.argument;
273
311
  object.expression = true;
274
312
  }
@@ -442,6 +480,8 @@ export default class Minify extends Transform {
442
480
  }
443
481
 
444
482
  if (
483
+ object.consequent &&
484
+ object.consequent.body &&
445
485
  object.consequent.body.length == 1 &&
446
486
  object.alternate &&
447
487
  object.alternate.body.length == 1
@@ -512,16 +552,16 @@ export default class Minify extends Transform {
512
552
  object.property.type = "Identifier";
513
553
  object.property.name = clone(object.property.value);
514
554
 
515
- obj.name &&
516
- this.log(
517
- obj.name +
518
- "['" +
519
- object.property.name +
520
- "'] -> " +
521
- obj.name +
522
- "." +
523
- object.property.name
524
- );
555
+ // obj.name &&
556
+ // this.log(
557
+ // obj.name +
558
+ // "['" +
559
+ // object.property.name +
560
+ // "'] -> " +
561
+ // obj.name +
562
+ // "." +
563
+ // object.property.name
564
+ // );
525
565
  }
526
566
  }
527
567
 
@@ -540,7 +580,7 @@ export default class Minify extends Transform {
540
580
  }
541
581
 
542
582
  // { "x": 1 } -> {x: 1}
543
- if (object.type == "Property") {
583
+ if (object.type === "Property" || object.type === "MethodDefinition") {
544
584
  if (
545
585
  object.key.type == "SequenceExpression" &&
546
586
  object.key.expressions.length == 1
@@ -549,15 +589,14 @@ export default class Minify extends Transform {
549
589
  object.computed = true;
550
590
  }
551
591
 
552
- if (object.key.type == "Literal" && isValidIdentifier(object.key.value)) {
592
+ if (
593
+ object.key.type == "Literal" &&
594
+ typeof object.key.value === "string" &&
595
+ isValidIdentifier(object.key.value)
596
+ ) {
553
597
  object.key.type = "Identifier";
554
598
  object.key.name = object.key.value;
555
599
  object.computed = false;
556
- } else if (
557
- object.key.type == "Identifier" &&
558
- !isValidIdentifier(object.key.name)
559
- ) {
560
- object.key = Literal(object.key.name);
561
600
  }
562
601
  }
563
602
 
@@ -64,14 +64,14 @@ export default class OpaquePredicates extends Transform {
64
64
  predicate: Node;
65
65
  predicates: { [name: string]: Node };
66
66
 
67
- gen: any;
67
+ gen: ReturnType<Transform["getGenerator"]>;
68
68
  made: number;
69
69
 
70
70
  constructor(o) {
71
71
  super(o, ObfuscateOrder.OpaquePredicates);
72
72
 
73
73
  this.predicates = Object.create(null);
74
- this.gen = this.getGenerator(getRandomInteger(0, 20));
74
+ this.gen = this.getGenerator();
75
75
  this.made = 0;
76
76
  }
77
77
 
@@ -0,0 +1,238 @@
1
+ import Transform from "./transform";
2
+
3
+ import {
4
+ BlockStatement,
5
+ Identifier,
6
+ LabeledStatement,
7
+ Literal,
8
+ Node,
9
+ ReturnStatement,
10
+ } from "../util/gen";
11
+ import { ObfuscateOrder } from "../order";
12
+ import { clone, getFunction } from "../util/insert";
13
+ import { getIdentifierInfo } from "../util/identifiers";
14
+ import { isLoop } from "../util/compare";
15
+ import { ExitCallback, walk } from "../traverse";
16
+
17
+ /**
18
+ * Preparation arranges the user's code into an AST the obfuscator can easily transform.
19
+ *
20
+ * ExplicitIdentifiers
21
+ * - `object.IDENTIFIER` -> `object['IDENTIFIER']` // Now String Concealing can apply on it
22
+ * - `{ IDENTIFIER: ... }` -> `{ "IDENTIFIER": ... }`
23
+ *
24
+ * ExplicitDeclarations
25
+ * - `var a,b,c` -> `var a; var b; var c;` // Now Stack can apply on it
26
+ *
27
+ * Block
28
+ * - `x => x * 2` -> `x => { return x * 2 }` // Change into Block Statements
29
+ * - `if(true) return` -> `if (true) { return }`
30
+ * - `while(a) a--;` -> `while(a) { a-- }`
31
+ *
32
+ * Label
33
+ * - `for(...) { break; }` -> `_1: for(...) { break _1; }`
34
+ * - `switch(v) { case 1...break }` -> `_2: switch(v) { case 1...break _2; }`
35
+ * - // Control Flow Flattening can safely apply now
36
+ */
37
+ export default class Preparation extends Transform {
38
+ constructor(o) {
39
+ super(o, ObfuscateOrder.Preparation);
40
+ }
41
+
42
+ match(object: Node, parents: Node[]) {
43
+ return !!object.type;
44
+ }
45
+
46
+ transform(object: Node, parents: Node[]): void | ExitCallback {
47
+ // ExplicitIdentifiers
48
+ if (object.type === "Identifier") {
49
+ return this.transformExplicitIdentifiers(object, parents);
50
+ }
51
+
52
+ // ExplicitDeclarations
53
+ if (object.type === "VariableDeclaration") {
54
+ return this.transformExplicitDeclarations(object, parents);
55
+ }
56
+
57
+ // Block
58
+ switch (object.type) {
59
+ /**
60
+ * People use shortcuts and its harder to parse.
61
+ *
62
+ * - `if (a) b()` -> `if (a) { b() }`
63
+ * - Ensures all bodies are `BlockStatement`, not individual expression statements
64
+ */
65
+ case "IfStatement":
66
+ if (object.consequent.type != "BlockStatement") {
67
+ object.consequent = BlockStatement([clone(object.consequent)]);
68
+ }
69
+ if (object.alternate && object.alternate.type != "BlockStatement") {
70
+ object.alternate = BlockStatement([clone(object.alternate)]);
71
+ }
72
+ break;
73
+
74
+ case "WhileStatement":
75
+ case "WithStatement":
76
+ case "ForStatement":
77
+ case "ForOfStatement":
78
+ case "ForInStatement":
79
+ if (object.body.type != "BlockStatement") {
80
+ object.body = BlockStatement([clone(object.body)]);
81
+ }
82
+ break;
83
+
84
+ case "ArrowFunctionExpression":
85
+ if (object.body.type !== "BlockStatement" && object.expression) {
86
+ object.body = BlockStatement([ReturnStatement(clone(object.body))]);
87
+ object.expression = false;
88
+ }
89
+ break;
90
+ }
91
+
92
+ // Label
93
+ if (
94
+ isLoop(object) ||
95
+ (object.type == "BlockStatement" &&
96
+ parents[0] &&
97
+ parents[0].type == "LabeledStatement" &&
98
+ parents[0].body === object)
99
+ ) {
100
+ return this.transformLabel(object, parents);
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Ensures every break; statement has a label to point to.
106
+ *
107
+ * This is because Control Flow Flattening adds For Loops which label-less break statements point to the nearest,
108
+ * when they actually need to point to the original statement.
109
+ */
110
+ transformLabel(object: Node, parents: Node[]) {
111
+ return () => {
112
+ var currentLabel =
113
+ parents[0].type == "LabeledStatement" && parents[0].label.name;
114
+
115
+ var label = currentLabel || this.getPlaceholder();
116
+
117
+ walk(object, parents, (o, p) => {
118
+ if (o.type == "BreakStatement" || o.type == "ContinueStatement") {
119
+ function isContinuableStatement(x) {
120
+ return isLoop(x) && x.type !== "SwitchStatement";
121
+ }
122
+ function isBreakableStatement(x) {
123
+ return isLoop(x) || (o.label && x.type == "BlockStatement");
124
+ }
125
+
126
+ var fn =
127
+ o.type == "ContinueStatement"
128
+ ? isContinuableStatement
129
+ : isBreakableStatement;
130
+
131
+ var loop = p.find(fn);
132
+ if (object == loop) {
133
+ if (!o.label) {
134
+ o.label = Identifier(label);
135
+ }
136
+ }
137
+ }
138
+ });
139
+
140
+ // Append label statement as this loop has none
141
+ if (!currentLabel) {
142
+ this.replace(object, LabeledStatement(label, { ...object }));
143
+ }
144
+ };
145
+ }
146
+
147
+ /**
148
+ * Transforms Identifiers (a.IDENTIFIER, {IDENTIFIER:...}) into string properties
149
+ */
150
+ transformExplicitIdentifiers(object: Node, parents: Node[]) {
151
+ // Mark functions containing 'eval'
152
+ // Some transformations avoid functions that have 'eval' to not break them
153
+ if (object.name === "eval") {
154
+ var fn = getFunction(object, parents);
155
+ if (fn) {
156
+ fn.$requiresEval = true;
157
+ }
158
+ }
159
+
160
+ var info = getIdentifierInfo(object, parents);
161
+ if (info.isPropertyKey || info.isAccessor) {
162
+ var propIndex = parents.findIndex(
163
+ (x) => x.type == "MethodDefinition" || x.type == "Property"
164
+ );
165
+
166
+ // Don't change constructor!
167
+ if (propIndex !== -1) {
168
+ if (
169
+ parents[propIndex].type == "MethodDefinition" &&
170
+ parents[propIndex].kind == "constructor"
171
+ ) {
172
+ return;
173
+ }
174
+ }
175
+
176
+ this.replace(object, Literal(object.name));
177
+ parents[0].computed = true;
178
+ parents[0].shorthand = false;
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Transforms VariableDeclaration into single declarations.
184
+ */
185
+ transformExplicitDeclarations(object: Node, parents: Node[]) {
186
+ // for ( var x in ... ) {...}
187
+ var forIndex = parents.findIndex(
188
+ (x) => x.type == "ForInStatement" || x.type == "ForOfStatement"
189
+ );
190
+ if (
191
+ forIndex != -1 &&
192
+ parents[forIndex].left == (parents[forIndex - 1] || object)
193
+ ) {
194
+ object.declarations.forEach((x) => {
195
+ x.init = null;
196
+ });
197
+ return;
198
+ }
199
+
200
+ var body = parents[0];
201
+ if (isLoop(body) || body.type == "LabeledStatement") {
202
+ return;
203
+ }
204
+
205
+ if (body.type == "ExportNamedDeclaration") {
206
+ return;
207
+ }
208
+
209
+ if (!Array.isArray(body)) {
210
+ this.error(new Error("body is " + body.type));
211
+ }
212
+
213
+ if (object.declarations.length > 1) {
214
+ // Make singular
215
+
216
+ var index = body.indexOf(object);
217
+ if (index == -1) {
218
+ this.error(new Error("index is -1"));
219
+ }
220
+
221
+ var after = object.declarations.slice(1);
222
+
223
+ body.splice(
224
+ index + 1,
225
+ 0,
226
+ ...after.map((x) => {
227
+ return {
228
+ type: "VariableDeclaration",
229
+ declarations: [clone(x)],
230
+ kind: object.kind,
231
+ };
232
+ })
233
+ );
234
+
235
+ object.declarations.length = 1;
236
+ }
237
+ }
238
+ }
@@ -9,12 +9,12 @@ import Transform from "./transform";
9
9
  * Renames the labels to shorter names.
10
10
  */
11
11
  export default class RenameLabels extends Transform {
12
- gen: any;
12
+ gen: ReturnType<Transform["getGenerator"]>;
13
13
 
14
14
  constructor(o) {
15
15
  super(o, ObfuscateOrder.RenameLabels);
16
16
 
17
- this.gen = this.getGenerator();
17
+ this.gen = this.getGenerator("randomized");
18
18
  }
19
19
 
20
20
  match(object, parents) {
@@ -20,7 +20,6 @@ import {
20
20
  Node,
21
21
  ReturnStatement,
22
22
  SpreadElement,
23
- ThisExpression,
24
23
  VariableDeclaration,
25
24
  VariableDeclarator,
26
25
  } from "../util/gen";
@@ -31,6 +30,7 @@ import {
31
30
  isFunction,
32
31
  prepend,
33
32
  getDefiningContext,
33
+ clone,
34
34
  } from "../util/insert";
35
35
  import { getRandomString } from "../util/random";
36
36
  import Transform from "./transform";
@@ -300,14 +300,15 @@ export default class RGF extends Transform {
300
300
  [],
301
301
  [
302
302
  ReturnStatement(
303
- CallExpression(memberExpression, [
303
+ // clone() is required!
304
+ CallExpression(clone(memberExpression), [
304
305
  Identifier(referenceArray),
305
306
  SpreadElement(Identifier("arguments")),
306
307
  ])
307
308
  ),
308
309
  ]
309
310
  ),
310
- memberExpression
311
+ clone(memberExpression)
311
312
  );
312
313
 
313
314
  this.replace(o, conditionalExpression);
@@ -328,8 +329,6 @@ export default class RGF extends Transform {
328
329
 
329
330
  queue.forEach(([object, parents]) => {
330
331
  var name = object?.id?.name;
331
- var hasName = !!name;
332
- var params = object.params.map((x) => x.name) || [];
333
332
  var signature = referenceSignatures[names.get(name)];
334
333
 
335
334
  var embeddedName = name || this.getPlaceholder();
@@ -348,9 +347,9 @@ export default class RGF extends Transform {
348
347
  integrity: false,
349
348
  },
350
349
  eval: false,
351
- hideInitializingCode: false,
350
+ stringEncoding: false,
352
351
  });
353
- var transforms = Object.values(obfuscator.transforms).filter(
352
+ var transforms = obfuscator.array.filter(
354
353
  (x) => x.priority > this.priority
355
354
  );
356
355