js-confuser 1.5.8 → 1.5.9

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 (62) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/index.js +45 -4
  3. package/dist/obfuscator.js +10 -5
  4. package/dist/options.js +2 -3
  5. package/dist/order.js +3 -3
  6. package/dist/transforms/antiTooling.js +1 -1
  7. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -2
  8. package/dist/transforms/dispatcher.js +3 -3
  9. package/dist/transforms/es5/antiClass.js +6 -2
  10. package/dist/transforms/es5/antiDestructuring.js +1 -1
  11. package/dist/transforms/eval.js +11 -0
  12. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +4 -4
  13. package/dist/transforms/extraction/objectExtraction.js +6 -1
  14. package/dist/transforms/flatten.js +73 -50
  15. package/dist/transforms/hexadecimalNumbers.js +34 -9
  16. package/dist/transforms/identifier/movedDeclarations.js +1 -1
  17. package/dist/transforms/minify.js +22 -6
  18. package/dist/transforms/rgf.js +4 -4
  19. package/dist/transforms/stack.js +1 -1
  20. package/dist/transforms/string/stringConcealing.js +2 -2
  21. package/dist/traverse.js +0 -8
  22. package/dist/util/compare.js +2 -2
  23. package/dist/util/insert.js +20 -6
  24. package/package.json +1 -1
  25. package/src/index.ts +57 -19
  26. package/src/obfuscator.ts +6 -1
  27. package/src/options.ts +10 -2
  28. package/src/order.ts +3 -3
  29. package/src/transforms/antiTooling.ts +1 -1
  30. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +14 -2
  31. package/src/transforms/dispatcher.ts +4 -3
  32. package/src/transforms/es5/antiClass.ts +10 -1
  33. package/src/transforms/es5/antiDestructuring.ts +1 -1
  34. package/src/transforms/eval.ts +18 -0
  35. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +5 -5
  36. package/src/transforms/extraction/objectExtraction.ts +12 -5
  37. package/src/transforms/flatten.ts +181 -128
  38. package/src/transforms/hexadecimalNumbers.ts +37 -9
  39. package/src/transforms/identifier/movedDeclarations.ts +1 -1
  40. package/src/transforms/minify.ts +37 -5
  41. package/src/transforms/rgf.ts +4 -3
  42. package/src/transforms/stack.ts +3 -1
  43. package/src/transforms/string/stringConcealing.ts +2 -2
  44. package/src/traverse.ts +1 -8
  45. package/src/types.ts +9 -1
  46. package/src/util/compare.ts +2 -2
  47. package/src/util/insert.ts +37 -8
  48. package/test/code/ES6.src.js +14 -0
  49. package/test/code/NewFeatures.test.ts +19 -0
  50. package/test/index.test.ts +13 -1
  51. package/test/transforms/antiTooling.test.ts +30 -0
  52. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +22 -0
  53. package/test/transforms/dispatcher.test.ts +24 -0
  54. package/test/transforms/es5/antiClass.test.ts +33 -0
  55. package/test/transforms/eval.test.ts +53 -0
  56. package/test/transforms/extraction/objectExtraction.test.ts +21 -0
  57. package/test/transforms/flatten.test.ts +146 -3
  58. package/test/transforms/identifier/renameVariables.test.ts +26 -0
  59. package/test/transforms/minify.test.ts +66 -0
  60. package/test/transforms/rgf.test.ts +56 -0
  61. package/test/transforms/string/stringConcealing.test.ts +33 -0
  62. package/test/util/compare.test.ts +23 -1
@@ -1,3 +1,4 @@
1
+ import { ok } from "assert";
1
2
  import { reservedIdentifiers } from "../constants";
2
3
  import { ObfuscateOrder } from "../order";
3
4
  import traverse, { walk } from "../traverse";
@@ -24,6 +25,8 @@ import {
24
25
  IfStatement,
25
26
  ThrowStatement,
26
27
  NewExpression,
28
+ AwaitExpression,
29
+ UnaryExpression,
27
30
  } from "../util/gen";
28
31
  import { getIdentifierInfo } from "../util/identifiers";
29
32
  import {
@@ -46,20 +49,19 @@ import Transform from "./transform";
46
49
  * return [ref1, ref2, refN, returnValue];
47
50
  * }
48
51
  * ```
52
+ *
53
+ * Flatten is used to make functions eligible for the RGF transformation.
49
54
  */
50
55
  export default class Flatten extends Transform {
51
56
  definedNames: Map<Node, Set<string>>;
52
-
53
- flatMapName: string;
54
- flatNode: Node;
55
- gen: any;
57
+ flattenedFns: Node[];
58
+ gen: ReturnType<Transform["getGenerator"]>;
56
59
 
57
60
  constructor(o) {
58
61
  super(o, ObfuscateOrder.Flatten);
59
62
 
60
63
  this.definedNames = new Map();
61
- this.flatMapName = null;
62
- this.flatNode = null;
64
+ this.flattenedFns = [];
63
65
  this.gen = this.getGenerator();
64
66
  }
65
67
 
@@ -87,33 +89,64 @@ export default class Flatten extends Transform {
87
89
  });
88
90
 
89
91
  super.apply(tree);
92
+
93
+ if (this.flattenedFns.length) {
94
+ prepend(tree, VariableDeclaration(this.flattenedFns));
95
+ }
90
96
  }
91
97
 
92
98
  match(object: Node, parents: Node[]) {
93
99
  return (
94
- object.type == "FunctionDeclaration" &&
100
+ (object.type == "FunctionDeclaration" ||
101
+ object.type === "FunctionExpression") &&
95
102
  object.body.type == "BlockStatement" &&
96
103
  !object.generator &&
97
- !object.async &&
98
104
  !object.params.find((x) => x.type !== "Identifier")
99
105
  );
100
106
  }
101
107
 
102
108
  transform(object: Node, parents: Node[]) {
103
109
  return () => {
104
- //
110
+ if (parents[0]) {
111
+ // Don't change class methods
112
+ if (
113
+ parents[0].type === "MethodDefinition" &&
114
+ parents[0].value === object
115
+ ) {
116
+ return;
117
+ }
105
118
 
106
- if (
107
- parents.find(
108
- (x) =>
109
- x.type == "ClassExpression" ||
110
- x.type == "ClassDeclaration" ||
111
- x.type == "MethodDefinition"
112
- )
113
- ) {
114
- return;
119
+ // Don't change getter/setter methods
120
+ if (
121
+ parents[0].type === "Property" &&
122
+ parents[0].value === object &&
123
+ parents[0].kind !== "init"
124
+ ) {
125
+ return;
126
+ }
115
127
  }
116
128
 
129
+ ok(
130
+ object.type === "FunctionDeclaration" ||
131
+ object.type === "FunctionExpression"
132
+ );
133
+
134
+ // The name is purely for debugging purposes
135
+ var currentFnName =
136
+ object.type === "FunctionDeclaration"
137
+ ? object.id?.name
138
+ : parents[0]?.type === "VariableDeclarator" &&
139
+ parents[0].id?.type === "Identifier" &&
140
+ parents[0].id?.name;
141
+
142
+ if (parents[0]?.type === "Property" && parents[0]?.key) {
143
+ currentFnName =
144
+ currentFnName ||
145
+ String(parents[0]?.key?.name || parents[0]?.key?.value);
146
+ }
147
+
148
+ if (!currentFnName) currentFnName = "unnamed";
149
+
117
150
  var defined = new Set<string>();
118
151
  var references = new Set<string>();
119
152
  var modified = new Set<string>();
@@ -147,9 +180,7 @@ export default class Flatten extends Transform {
147
180
 
148
181
  if (o.hidden) {
149
182
  illegal.add(o.name);
150
- }
151
-
152
- if (info.spec.isDefined) {
183
+ } else if (info.spec.isDefined) {
153
184
  defined.add(o.name);
154
185
  } else if (info.spec.isModified) {
155
186
  modified.add(o.name);
@@ -198,9 +229,6 @@ export default class Flatten extends Transform {
198
229
  return;
199
230
  }
200
231
 
201
- illegal.forEach((name) => {
202
- defined.delete(name);
203
- });
204
232
  defined.forEach((name) => {
205
233
  references.delete(name);
206
234
  modified.delete(name);
@@ -216,16 +244,35 @@ export default class Flatten extends Transform {
216
244
 
217
245
  var output = Array.from(modified);
218
246
 
219
- var newName = this.gen.generate();
220
- var valName = this.getPlaceholder();
247
+ var newName = this.getPlaceholder() + "_flat_" + currentFnName;
221
248
  var resultName = this.getPlaceholder();
222
249
  var propName = this.gen.generate();
223
250
 
251
+ var newOutputNames: { [originalName: string]: string } =
252
+ Object.create(null);
253
+ output.forEach((name) => {
254
+ newOutputNames[name] = this.gen.generate();
255
+ });
256
+ var returnOutputName = this.gen.generate();
257
+
224
258
  getBlockBody(object.body).push(ReturnStatement());
225
259
  walk(object.body, [object, ...parents], (o, p) => {
226
260
  return () => {
261
+ // Change return statements from
262
+ // return (argument)
263
+ // to
264
+ // return [ [modifiedRefs], ]
227
265
  if (o.type == "ReturnStatement" && getVarContext(o, p) === object) {
228
- var elements = output.map(Identifier);
266
+ var returnObject = ObjectExpression(
267
+ output.map((outputName) =>
268
+ Property(
269
+ Literal(newOutputNames[outputName]),
270
+ Identifier(outputName),
271
+ true
272
+ )
273
+ )
274
+ );
275
+
229
276
  if (
230
277
  o.argument &&
231
278
  !(
@@ -233,11 +280,11 @@ export default class Flatten extends Transform {
233
280
  o.argument.name == "undefined"
234
281
  )
235
282
  ) {
236
- elements.unshift(clone(o.argument));
283
+ returnObject.properties.push(
284
+ Property(Literal(returnOutputName), clone(o.argument), true)
285
+ );
237
286
  }
238
287
 
239
- o.argument = ArrayExpression(elements);
240
-
241
288
  o.argument = AssignmentExpression(
242
289
  "=",
243
290
  MemberExpression(
@@ -245,7 +292,7 @@ export default class Flatten extends Transform {
245
292
  Identifier(propName),
246
293
  false
247
294
  ),
248
- o.argument
295
+ returnObject
249
296
  );
250
297
  }
251
298
  };
@@ -253,35 +300,12 @@ export default class Flatten extends Transform {
253
300
 
254
301
  var newBody = getBlockBody(object.body);
255
302
 
256
- newBody.unshift(
257
- VariableDeclaration(
258
- VariableDeclarator(
259
- ArrayPattern([
260
- ArrayPattern(input.map(Identifier)),
261
- ArrayPattern(clone(object.params)),
262
- Identifier(resultName),
263
- ]),
264
-
265
- Identifier(valName)
266
- )
267
- )
268
- );
269
-
270
- if (!this.flatMapName) {
271
- this.flatMapName = this.getPlaceholder();
272
- prepend(
273
- parents[parents.length - 1],
274
- VariableDeclaration(
275
- VariableDeclarator(
276
- this.flatMapName,
277
- (this.flatNode = ObjectExpression([]))
278
- )
279
- )
280
- );
281
- }
282
-
283
303
  var newFunctionExpression = FunctionExpression(
284
- [Identifier(valName)],
304
+ [
305
+ ArrayPattern(input.map(Identifier)),
306
+ ArrayPattern(clone(object.params)),
307
+ Identifier(resultName),
308
+ ],
285
309
  newBody
286
310
  );
287
311
 
@@ -295,134 +319,163 @@ export default class Flatten extends Transform {
295
319
  );
296
320
  property.kind = "set";
297
321
 
298
- this.flatNode.properties.push(property);
299
-
300
- var identifier = MemberExpression(
301
- Identifier(this.flatMapName),
302
- Identifier(newName),
303
- false
322
+ this.flattenedFns.push(
323
+ VariableDeclarator(newName, newFunctionExpression)
304
324
  );
305
325
 
306
326
  var newParamNodes = object.params.map(() =>
307
327
  Identifier(this.getPlaceholder())
308
328
  );
309
329
 
310
- // var result = newFn.call([...refs], ...arguments)
311
- var call = VariableDeclaration([
312
- VariableDeclarator(resultName, ArrayExpression([])),
313
- VariableDeclarator(
314
- "_",
315
- AssignmentExpression(
316
- "=",
317
- identifier,
318
- ArrayExpression([
319
- ArrayExpression(input.map(Identifier)),
320
- ArrayExpression([...newParamNodes]),
321
- Identifier(resultName),
322
- ])
323
- )
324
- ),
325
- ]);
326
-
327
330
  // result.pop()
328
- var pop = CallExpression(
331
+ var getOutputMemberExpression = (outputName) =>
329
332
  MemberExpression(
330
- MemberExpression(Identifier(resultName), Identifier(propName), false),
331
- Literal("pop"),
333
+ MemberExpression(Identifier(resultName), Literal(propName), true),
334
+ Literal(outputName),
332
335
  true
333
- ),
334
- []
335
- );
336
+ );
336
337
 
337
- // var result = newFn.call([...refs], ...arguments)
338
- // modified1 = result.pop();
339
- // modified2 = result.pop();
340
- // ...modifiedN = result.pop();...
341
- //
342
- // return result.pop()
338
+ // newFn.call([...refs], ...arguments, resultObject)
339
+ var callExpression = CallExpression(Identifier(newName), [
340
+ ArrayExpression(input.map(Identifier)),
341
+ ArrayExpression([...newParamNodes]),
342
+ Identifier(resultName),
343
+ ]);
344
+
345
+ var newObjectBody: Node[] = [
346
+ // var resultObject = {};
347
+ VariableDeclaration([
348
+ VariableDeclarator(resultName, ObjectExpression([])),
349
+ ]),
350
+
351
+ ExpressionStatement(
352
+ newFunctionExpression.async
353
+ ? AwaitExpression(callExpression)
354
+ : callExpression
355
+ ),
356
+ ];
343
357
 
344
- var newObjectBody: Node[] = [call];
345
358
  var outputReversed = [...output].reverse();
346
359
 
360
+ // realVar
361
+ outputReversed.forEach((outputName) => {
362
+ newObjectBody.push(
363
+ ExpressionStatement(
364
+ AssignmentExpression(
365
+ "=",
366
+ Identifier(outputName),
367
+ getOutputMemberExpression(newOutputNames[outputName])
368
+ )
369
+ )
370
+ );
371
+ });
372
+
347
373
  // DECOY STATEMENTS
348
374
  var decoyKey = this.gen.generate();
349
375
  var decoyNodes = [
376
+ // if (result.random) throw result.prop.random
350
377
  IfStatement(
351
378
  MemberExpression(
352
379
  Identifier(resultName),
353
- Identifier(this.gen.generate()),
354
- false
380
+ Literal(this.gen.generate()),
381
+ true
355
382
  ),
356
383
  [
357
384
  ThrowStatement(
358
385
  NewExpression(Identifier("Error"), [
359
- Literal(this.getPlaceholder()),
386
+ getOutputMemberExpression(this.gen.generate()),
360
387
  ])
361
388
  ),
362
389
  ]
363
390
  ),
391
+ // if (result.random) return true;
364
392
  IfStatement(
365
393
  MemberExpression(
366
394
  Identifier(resultName),
367
- Identifier(this.gen.generate()),
368
- false
395
+ Literal(this.gen.generate()),
396
+ true
369
397
  ),
370
- [ReturnStatement(Identifier(resultName))]
398
+ [ReturnStatement(Literal(true))]
371
399
  ),
400
+ // if (result.random) return result;
372
401
  IfStatement(
373
402
  MemberExpression(
374
403
  Identifier(resultName),
375
- Identifier(this.gen.generate()),
376
- false
404
+ Literal(this.gen.generate()),
405
+ true
377
406
  ),
378
407
  [ReturnStatement(Identifier(resultName))]
379
408
  ),
409
+ // if (result.random) return result.random;
380
410
  IfStatement(
381
- MemberExpression(Identifier(resultName), Identifier(decoyKey), false),
411
+ MemberExpression(Identifier(resultName), Literal(decoyKey), true),
382
412
  [
383
413
  ReturnStatement(
384
- MemberExpression(
385
- Identifier(resultName),
386
- Identifier(decoyKey),
387
- false
388
- )
414
+ MemberExpression(Identifier(resultName), Literal(decoyKey), true)
389
415
  ),
390
416
  ]
391
417
  ),
418
+ // if(result.random1) return result.random2;
392
419
  IfStatement(
393
420
  MemberExpression(
394
421
  Identifier(resultName),
395
- Identifier(this.gen.generate()),
396
- false
422
+ Literal(this.gen.generate()),
423
+ true
397
424
  ),
398
425
  [
399
426
  ReturnStatement(
400
427
  MemberExpression(
401
428
  Identifier(resultName),
402
- Identifier(this.gen.generate()),
403
- false
429
+ Literal(this.gen.generate()),
430
+ true
404
431
  )
405
432
  ),
406
433
  ]
407
434
  ),
408
- ];
435
+ // if(result.random) return flatFn;
436
+ IfStatement(
437
+ MemberExpression(
438
+ Identifier(resultName),
439
+ Literal(this.gen.generate()),
440
+ true
441
+ ),
442
+ [ReturnStatement(Identifier(newName))]
443
+ ),
444
+ // if(result.random) flatFn = undefined;
445
+ IfStatement(
446
+ MemberExpression(
447
+ Identifier(resultName),
448
+ Literal(this.gen.generate()),
449
+ true
450
+ ),
451
+ [
452
+ ExpressionStatement(
453
+ AssignmentExpression(
454
+ "=",
455
+ Identifier(newName),
456
+ Identifier("undefined")
457
+ )
458
+ ),
459
+ ]
460
+ ),
461
+ // if(!result) return;
462
+ IfStatement(UnaryExpression("!", Identifier(resultName)), [
463
+ ReturnStatement(),
464
+ ]),
465
+ ].filter(() => Math.random() > 0.25);
466
+
467
+ // if (result.output) return result.output.returnValue;
468
+ // this is the real return statement, it is always added
469
+ decoyNodes.push(
470
+ IfStatement(
471
+ MemberExpression(Identifier(resultName), Literal(propName), true),
472
+ [ReturnStatement(getOutputMemberExpression(returnOutputName))]
473
+ )
474
+ );
409
475
 
410
476
  shuffle(decoyNodes);
411
- decoyNodes.forEach((decoyNode) => {
412
- if (Math.random() < 0.5) {
413
- newObjectBody.push(decoyNode);
414
- }
415
- });
416
477
 
417
- newObjectBody.push(
418
- ...outputReversed.map((name) => {
419
- return ExpressionStatement(
420
- AssignmentExpression("=", Identifier(name), clone(pop))
421
- );
422
- }),
423
-
424
- ReturnStatement(clone(pop))
425
- );
478
+ newObjectBody.push(...decoyNodes);
426
479
 
427
480
  object.body = BlockStatement(newObjectBody);
428
481
 
@@ -3,12 +3,19 @@ import { ObfuscateOrder } from "../order";
3
3
  import { ExitCallback } from "../traverse";
4
4
  import { Identifier, Node } from "../util/gen";
5
5
 
6
+ /**
7
+ * The HexadecimalNumbers transformation converts number literals into the hexadecimal form.
8
+ *
9
+ * This is done by replacing the number literal with an Identifier to ensure escodegen properly outputs it as such
10
+ *
11
+ * This transformation also handles BigInt support, so its always enabled for this reason.
12
+ */
6
13
  export default class HexadecimalNumbers extends Transform {
7
14
  constructor(o) {
8
15
  super(o, ObfuscateOrder.HexadecimalNumbers);
9
16
  }
10
17
 
11
- match(object: Node, parents: Node[]): boolean {
18
+ isNumberLiteral(object: Node) {
12
19
  return (
13
20
  object.type === "Literal" &&
14
21
  typeof object.value === "number" &&
@@ -16,16 +23,37 @@ export default class HexadecimalNumbers extends Transform {
16
23
  );
17
24
  }
18
25
 
26
+ isBigIntLiteral(object: Node) {
27
+ return object.type === "Literal" && typeof object.value === "bigint";
28
+ }
29
+
30
+ match(object: Node, parents: Node[]): boolean {
31
+ return (
32
+ (this.options.hexadecimalNumbers && this.isNumberLiteral(object)) ||
33
+ this.isBigIntLiteral(object)
34
+ );
35
+ }
36
+
19
37
  transform(object: Node, parents: Node[]): void | ExitCallback {
20
- return () => {
21
- // Technically, a Literal will never be negative because it's supposed to be inside a UnaryExpression with a "-" operator.
22
- // This code handles it regardless
23
- var isNegative = object.value < 0;
24
- var hex = Math.abs(object.value).toString(16);
38
+ if (this.isNumberLiteral(object)) {
39
+ return () => {
40
+ // Technically, a Literal will never be negative because it's supposed to be inside a UnaryExpression with a "-" operator.
41
+ // This code handles it regardless
42
+ var isNegative = object.value < 0;
43
+ var hex = Math.abs(object.value).toString(16);
44
+
45
+ var newStr = (isNegative ? "-" : "") + "0x" + hex;
25
46
 
26
- var newStr = (isNegative ? "-" : "") + "0x" + hex;
47
+ this.replace(object, Identifier(newStr));
48
+ };
49
+ }
27
50
 
28
- this.replace(object, Identifier(newStr));
29
- };
51
+ // https://github.com/MichaelXF/js-confuser/issues/79
52
+ if (this.isBigIntLiteral(object)) {
53
+ return () => {
54
+ // Use an Identifier with the raw string
55
+ this.replace(object, Identifier(object.raw));
56
+ };
57
+ }
30
58
  }
31
59
  }
@@ -46,7 +46,7 @@ export default class MovedDeclarations extends Transform {
46
46
 
47
47
  walk(object, parents, (o, p) => {
48
48
  if (o.type == "Identifier") {
49
- if (getLexicalScope(o, p) !== object) {
49
+ if (o.hidden || getLexicalScope(o, p) !== object) {
50
50
  illegal.add(o.name);
51
51
  } else {
52
52
  var info = getIdentifierInfo(o, p);
@@ -15,6 +15,7 @@ import {
15
15
  AssignmentExpression,
16
16
  VariableDeclarator,
17
17
  Identifier,
18
+ CallExpression,
18
19
  } from "../util/gen";
19
20
  import {
20
21
  getBlockBody,
@@ -22,11 +23,14 @@ import {
22
23
  isForInitialize,
23
24
  isLexContext,
24
25
  getFunction,
26
+ prepend,
27
+ append,
25
28
  } from "../util/insert";
26
29
  import { isValidIdentifier, isEquivalent } from "../util/compare";
27
30
  import { walk, isBlock } from "../traverse";
28
31
  import { ok } from "assert";
29
32
  import { isLexicalScope } from "../util/scope";
33
+ import Template from "../templates/template";
30
34
 
31
35
  /**
32
36
  * Basic transformations to reduce code size.
@@ -37,12 +41,13 @@ import { isLexicalScope } from "../util/scope";
37
41
  * - `x['y']` **->** `x.y`
38
42
  */
39
43
  export default class Minify extends Transform {
40
- variables: Map<Node, Location[]>;
44
+ /**
45
+ * A helper function that is introduced preserve function semantics
46
+ */
47
+ arrowFunctionName: string;
41
48
 
42
49
  constructor(o) {
43
50
  super(o, ObfuscateOrder.Minify);
44
-
45
- this.variables = new Map();
46
51
  }
47
52
 
48
53
  match(object: Node, parents: Node[]) {
@@ -239,17 +244,42 @@ export default class Minify extends Transform {
239
244
  });
240
245
 
241
246
  if (canTransform) {
247
+ if (!this.arrowFunctionName) {
248
+ this.arrowFunctionName = this.getPlaceholder();
249
+
250
+ append(
251
+ parents[parents.length - 1] || object,
252
+ Template(`
253
+ function ${this.arrowFunctionName}(arrowFn){
254
+ return function(){ return arrowFn(...arguments) }
255
+ }
256
+ `).single()
257
+ );
258
+ }
259
+
260
+ const wrap = (object: Node) => {
261
+ return CallExpression(Identifier(this.arrowFunctionName), [
262
+ clone(object),
263
+ ]);
264
+ };
265
+
242
266
  if (object.type == "FunctionExpression") {
243
267
  object.type = "ArrowFunctionExpression";
268
+
269
+ this.replace(object, wrap(clone(object)));
244
270
  } else {
245
271
  var arrow = { ...clone(object), type: "ArrowFunctionExpression" };
246
272
  this.replace(
247
273
  object,
248
- VariableDeclaration(VariableDeclarator(object.id.name, arrow))
274
+ VariableDeclaration(
275
+ VariableDeclarator(object.id.name, wrap(arrow))
276
+ )
249
277
  );
250
278
 
251
279
  var x = this.transform(arrow, []);
252
- x();
280
+ if (typeof x === "function") {
281
+ x();
282
+ }
253
283
  }
254
284
  }
255
285
  };
@@ -442,6 +472,8 @@ export default class Minify extends Transform {
442
472
  }
443
473
 
444
474
  if (
475
+ object.consequent &&
476
+ object.consequent.body &&
445
477
  object.consequent.body.length == 1 &&
446
478
  object.alternate &&
447
479
  object.alternate.body.length == 1
@@ -31,6 +31,7 @@ import {
31
31
  isFunction,
32
32
  prepend,
33
33
  getDefiningContext,
34
+ clone,
34
35
  } from "../util/insert";
35
36
  import { getRandomString } from "../util/random";
36
37
  import Transform from "./transform";
@@ -300,7 +301,8 @@ export default class RGF extends Transform {
300
301
  [],
301
302
  [
302
303
  ReturnStatement(
303
- CallExpression(memberExpression, [
304
+ // clone() is required!
305
+ CallExpression(clone(memberExpression), [
304
306
  Identifier(referenceArray),
305
307
  SpreadElement(Identifier("arguments")),
306
308
  ])
@@ -328,8 +330,6 @@ export default class RGF extends Transform {
328
330
 
329
331
  queue.forEach(([object, parents]) => {
330
332
  var name = object?.id?.name;
331
- var hasName = !!name;
332
- var params = object.params.map((x) => x.name) || [];
333
333
  var signature = referenceSignatures[names.get(name)];
334
334
 
335
335
  var embeddedName = name || this.getPlaceholder();
@@ -349,6 +349,7 @@ export default class RGF extends Transform {
349
349
  },
350
350
  eval: false,
351
351
  hideInitializingCode: false,
352
+ stringEncoding: false,
352
353
  });
353
354
  var transforms = Object.values(obfuscator.transforms).filter(
354
355
  (x) => x.priority > this.priority
@@ -55,7 +55,9 @@ export default class Stack extends Transform {
55
55
  return () => {
56
56
  // Uncaught SyntaxError: Getter must not have any formal parameters.
57
57
  // Uncaught SyntaxError: Setter must have exactly one formal parameter
58
- var propIndex = parents.findIndex((x) => x.type == "Property");
58
+ var propIndex = parents.findIndex(
59
+ (x) => x.type === "Property" || x.type === "MethodDefinition"
60
+ );
59
61
  if (propIndex !== -1) {
60
62
  if (parents[propIndex].value === (parents[propIndex - 1] || object)) {
61
63
  if (parents[propIndex].kind !== "init" || parents[propIndex].method) {