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
@@ -21,6 +21,8 @@ var _assert = require("assert");
21
21
 
22
22
  var _scope = require("../util/scope");
23
23
 
24
+ var _template = _interopRequireDefault(require("../templates/template"));
25
+
24
26
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
27
 
26
28
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
@@ -34,12 +36,13 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
34
36
  * - `x['y']` **->** `x.y`
35
37
  */
36
38
  class Minify extends _transform.default {
39
+ /**
40
+ * A helper function that is introduced preserve function semantics
41
+ */
37
42
  constructor(o) {
38
43
  super(o, _order.ObfuscateOrder.Minify);
39
44
 
40
- _defineProperty(this, "variables", void 0);
41
-
42
- this.variables = new Map();
45
+ _defineProperty(this, "arrowFunctionName", void 0);
43
46
  }
44
47
 
45
48
  match(object, parents) {
@@ -212,15 +215,28 @@ class Minify extends _transform.default {
212
215
  });
213
216
 
214
217
  if (canTransform) {
218
+ if (!this.arrowFunctionName) {
219
+ this.arrowFunctionName = this.getPlaceholder();
220
+ (0, _insert.append)(parents[parents.length - 1] || object, (0, _template.default)("\n function ".concat(this.arrowFunctionName, "(arrowFn){\n return function(){ return arrowFn(...arguments) }\n }\n ")).single());
221
+ }
222
+
223
+ const wrap = object => {
224
+ return (0, _gen.CallExpression)((0, _gen.Identifier)(this.arrowFunctionName), [(0, _insert.clone)(object)]);
225
+ };
226
+
215
227
  if (object.type == "FunctionExpression") {
216
228
  object.type = "ArrowFunctionExpression";
229
+ this.replace(object, wrap((0, _insert.clone)(object)));
217
230
  } else {
218
231
  var arrow = { ...(0, _insert.clone)(object),
219
232
  type: "ArrowFunctionExpression"
220
233
  };
221
- this.replace(object, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(object.id.name, arrow)));
234
+ this.replace(object, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(object.id.name, wrap(arrow))));
222
235
  var x = this.transform(arrow, []);
223
- x();
236
+
237
+ if (typeof x === "function") {
238
+ x();
239
+ }
224
240
  }
225
241
  }
226
242
  };
@@ -372,7 +388,7 @@ class Minify extends _transform.default {
372
388
  object.alternate = null;
373
389
  }
374
390
 
375
- if (object.consequent.body.length == 1 && object.alternate && object.alternate.body.length == 1) {
391
+ if (object.consequent && object.consequent.body && object.consequent.body.length == 1 && object.alternate && object.alternate.body.length == 1) {
376
392
  var stmt1 = (0, _insert.clone)(object.consequent.body[0]);
377
393
  var stmt2 = (0, _insert.clone)(object.alternate.body[0]); // if (a) {return b;} else {return c;} -> return a ? b : c;
378
394
 
@@ -241,7 +241,8 @@ class RGF extends _transform.default {
241
241
  // fn
242
242
  // In most cases the identifier is being used like this (call expression, or referenced to be called later)
243
243
  // Replace it with a simple wrapper function that will pass on the reference array
244
- var conditionalExpression = (0, _gen.ConditionalExpression)((0, _template.default)("typeof ".concat(referenceArray, "[").concat(index, "] === \"function\" && ").concat(referenceArray, "[").concat(index, "][\"").concat(referenceSignatures[index] || "_", "\"]")).single().expression, (0, _gen.FunctionExpression)([], [(0, _gen.ReturnStatement)((0, _gen.CallExpression)(memberExpression, [(0, _gen.Identifier)(referenceArray), (0, _gen.SpreadElement)((0, _gen.Identifier)("arguments"))]))]), memberExpression);
244
+ var conditionalExpression = (0, _gen.ConditionalExpression)((0, _template.default)("typeof ".concat(referenceArray, "[").concat(index, "] === \"function\" && ").concat(referenceArray, "[").concat(index, "][\"").concat(referenceSignatures[index] || "_", "\"]")).single().expression, (0, _gen.FunctionExpression)([], [(0, _gen.ReturnStatement)( // clone() is required!
245
+ (0, _gen.CallExpression)((0, _insert.clone)(memberExpression), [(0, _gen.Identifier)(referenceArray), (0, _gen.SpreadElement)((0, _gen.Identifier)("arguments"))]))]), memberExpression);
245
246
  this.replace(o, conditionalExpression);
246
247
  }
247
248
  }
@@ -258,8 +259,6 @@ class RGF extends _transform.default {
258
259
 
259
260
  let [object, parents] = _ref2;
260
261
  var name = object === null || object === void 0 ? void 0 : (_object$id2 = object.id) === null || _object$id2 === void 0 ? void 0 : _object$id2.name;
261
- var hasName = !!name;
262
- var params = object.params.map(x => x.name) || [];
263
262
  var signature = referenceSignatures[names.get(name)];
264
263
  var embeddedName = name || this.getPlaceholder(); // Since `new Function` is completely isolated, create an entire new obfuscator and run remaining transformations.
265
264
  // RGF runs early and needs completed code before converting to a string.
@@ -272,7 +271,8 @@ class RGF extends _transform.default {
272
271
  integrity: false
273
272
  },
274
273
  eval: false,
275
- hideInitializingCode: false
274
+ hideInitializingCode: false,
275
+ stringEncoding: false
276
276
  });
277
277
  var transforms = Object.values(obfuscator.transforms).filter(x => x.priority > this.priority);
278
278
  var embeddedFunction = { ...object,
@@ -44,7 +44,7 @@ class Stack extends _transform.default {
44
44
  return () => {
45
45
  // Uncaught SyntaxError: Getter must not have any formal parameters.
46
46
  // Uncaught SyntaxError: Setter must have exactly one formal parameter
47
- var propIndex = parents.findIndex(x => x.type == "Property");
47
+ var propIndex = parents.findIndex(x => x.type === "Property" || x.type === "MethodDefinition");
48
48
 
49
49
  if (propIndex !== -1) {
50
50
  if (parents[propIndex].value === (parents[propIndex - 1] || object)) {
@@ -166,10 +166,10 @@ class StringConcealing extends _transform.default {
166
166
  var callExpr = (0, _gen.CallExpression)((0, _gen.Identifier)(fnName), [(0, _gen.Literal)(index)]); // use `.apply` to fool automated de-obfuscators
167
167
 
168
168
  if (Math.random() > 0.5) {
169
- callExpr = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(fnName), (0, _gen.Identifier)("apply"), false), [(0, _gen.ThisExpression)(), (0, _gen.ArrayExpression)([(0, _gen.Literal)(index)])]);
169
+ callExpr = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(fnName), (0, _gen.Identifier)("apply"), false), [(0, _gen.Identifier)("undefined"), (0, _gen.ArrayExpression)([(0, _gen.Literal)(index)])]);
170
170
  } // use `.call`
171
171
  else if (Math.random() > 0.5) {
172
- callExpr = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(fnName), (0, _gen.Identifier)("call"), false), [(0, _gen.ThisExpression)(), (0, _gen.Literal)(index)]);
172
+ callExpr = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(fnName), (0, _gen.Identifier)("call"), false), [(0, _gen.Identifier)("undefined"), (0, _gen.Literal)(index)]);
173
173
  }
174
174
 
175
175
  var referenceType = "call";
package/dist/traverse.js CHANGED
@@ -40,15 +40,7 @@ function isBlock(object) {
40
40
  }
41
41
 
42
42
  function walk(object, parents, onEnter) {
43
- let seen = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : new Set();
44
-
45
43
  if (typeof object === "object" && object) {
46
- if (seen.has(object)) {
47
- console.log(object);
48
- throw new Error("Already seen: " + object.type);
49
- }
50
-
51
- seen.add(object);
52
44
  var newParents = [object, ...parents];
53
45
 
54
46
  if (!Array.isArray(object)) {
@@ -59,8 +59,8 @@ function isValidIdentifier(name) {
59
59
  return false;
60
60
  }
61
61
 
62
- var x = name.match(/^[A-z$_][A-z0-9$_]*/);
63
- return x && x[0] == name;
62
+ var x = name.match(/^[A-Za-z$_][A-Za-z0-9$_]*/);
63
+ return !!(x && x[0] == name);
64
64
  }
65
65
 
66
66
  function isInsideType(type, object, parents) {
@@ -139,8 +139,12 @@ function getDefiningContext(o, p) {
139
139
  var variableDeclaration = p.find(x => x.type == "VariableDeclaration");
140
140
  (0, _assert.ok)(variableDeclaration);
141
141
 
142
- if (variableDeclaration.kind === "let") {
143
- return getLexContext(o, p);
142
+ if (variableDeclaration.kind === "let" || variableDeclaration.kind === "const") {
143
+ var context = getVarContext(o, p);
144
+
145
+ if (context && context.type === "Program") {
146
+ return getLexContext(o, p);
147
+ }
144
148
  }
145
149
  }
146
150
 
@@ -287,15 +291,21 @@ function prepend(block) {
287
291
  }
288
292
 
289
293
  if (block.type == "Program") {
290
- var decs = 0;
294
+ var moveBy = 0;
291
295
  block.body.forEach((stmt, i) => {
292
296
  if (stmt.type == "ImportDeclaration") {
293
- if (decs == i) {
294
- decs++;
297
+ if (moveBy == i) {
298
+ moveBy++;
299
+ }
300
+ }
301
+
302
+ if (stmt.type === "ExpressionStatement" && typeof stmt.directive === "string") {
303
+ if (moveBy == i) {
304
+ moveBy++;
295
305
  }
296
306
  }
297
307
  });
298
- block.body.splice(decs, 0, ...nodes);
308
+ block.body.splice(moveBy, 0, ...nodes);
299
309
  } else {
300
310
  getBlockBody(block).unshift(...nodes);
301
311
  }
@@ -351,6 +361,10 @@ function isForInitialize(o, p) {
351
361
  (0, _identifiers.validateChain)(o, p);
352
362
  var forIndex = p.findIndex(x => x.type == "ForStatement" || x.type == "ForInStatement" || x.type == "ForOfStatement");
353
363
 
364
+ if (p.slice(0, forIndex).find(x => ["ArrowFunctionExpression", "BlockStatement"].includes(x.type))) {
365
+ return false;
366
+ }
367
+
354
368
  if (forIndex !== -1) {
355
369
  if (p[forIndex].type == "ForStatement") {
356
370
  if (p[forIndex].init == (p[forIndex - 1] || o)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-confuser",
3
- "version": "1.5.8",
3
+ "version": "1.5.9",
4
4
  "description": "JavaScript Obfuscation Tool.",
5
5
  "main": "dist/index.js",
6
6
  "types": "index.d.ts",
package/src/index.ts CHANGED
@@ -4,6 +4,7 @@ import Obfuscator from "./obfuscator";
4
4
  import Transform from "./transforms/transform";
5
5
  import { remove$Properties } from "./util/object";
6
6
  import presets from "./presets";
7
+ import { performance } from "perf_hooks";
7
8
 
8
9
  import * as assert from "assert";
9
10
  import { correctOptions, ObfuscateOptions, validateOptions } from "./options";
@@ -85,8 +86,8 @@ var JsConfuser: IJsConfuser = async function (
85
86
  return result;
86
87
  } as any;
87
88
 
88
- export var debugTransformations: IJsConfuserDebugTransformations =
89
- async function debugTransformations(
89
+ export const debugTransformations: IJsConfuserDebugTransformations =
90
+ async function (
90
91
  code: string,
91
92
  options: ObfuscateOptions
92
93
  ): Promise<{ name: string; code: string; ms: number }[]> {
@@ -115,28 +116,65 @@ export var debugTransformations: IJsConfuserDebugTransformations =
115
116
  return frames;
116
117
  };
117
118
 
118
- export var debugObfuscation: IJsConfuserDebugObfuscation =
119
- async function debugTransformations(
120
- code: string,
121
- options: ObfuscateOptions,
122
- callback: (name: string, complete: number, totalTransforms: number) => void
123
- ): Promise<string> {
124
- validateOptions(options);
125
- options = await correctOptions(options);
119
+ /**
120
+ * This method is used by the obfuscator website to display a progress bar and additional information
121
+ * about the obfuscation.
122
+ *
123
+ * @param code - Source code to obfuscate
124
+ * @param options - Options
125
+ * @param callback - Progress callback, called after each transformation
126
+ * @returns
127
+ */
128
+ export const debugObfuscation: IJsConfuserDebugObfuscation = async function (
129
+ code: string,
130
+ options: ObfuscateOptions,
131
+ callback: (name: string, complete: number, totalTransforms: number) => void
132
+ ) {
133
+ const startTime = performance.now();
126
134
 
127
- var tree = parseSync(code);
128
- var obfuscator = new Obfuscator(options);
129
- var totalTransforms = obfuscator.array.length;
135
+ validateOptions(options);
136
+ options = await correctOptions(options);
130
137
 
131
- obfuscator.on("debug", (name: string, tree: Node, i: number) => {
132
- callback(name, i, totalTransforms);
133
- });
138
+ const beforeParseTime = performance.now();
134
139
 
135
- await obfuscator.apply(tree, true);
140
+ var tree = parseSync(code);
141
+
142
+ const parseTime = performance.now() - beforeParseTime;
143
+
144
+ var obfuscator = new Obfuscator(options);
145
+ var totalTransforms = obfuscator.array.length;
146
+
147
+ var transformationTimes = Object.create(null);
148
+ var currentTransformTime = performance.now();
149
+
150
+ obfuscator.on("debug", (name: string, tree: Node, i: number) => {
151
+ var nowTime = performance.now();
152
+ transformationTimes[name] = nowTime - currentTransformTime;
153
+ currentTransformTime = nowTime;
154
+
155
+ callback(name, i, totalTransforms);
156
+ });
157
+
158
+ await obfuscator.apply(tree, true);
159
+
160
+ const beforeCompileTime = performance.now();
161
+
162
+ var output = await compileJs(tree, options);
163
+
164
+ const compileTime = performance.now() - beforeCompileTime;
165
+
166
+ const endTime = performance.now();
136
167
 
137
- var output = compileJs(tree, options);
138
- return output;
168
+ return {
169
+ obfuscated: output,
170
+ transformationTimes: transformationTimes,
171
+ obfuscationTime: endTime - startTime,
172
+ parseTime: parseTime,
173
+ compileTime: compileTime,
174
+ totalTransforms: totalTransforms,
175
+ totalPossibleTransforms: obfuscator.totalPossibleTransforms,
139
176
  };
177
+ };
140
178
 
141
179
  JsConfuser.obfuscate = obfuscate;
142
180
  JsConfuser.obfuscateAST = obfuscateAST;
package/src/obfuscator.ts CHANGED
@@ -47,17 +47,22 @@ export default class Obfuscator extends EventEmitter {
47
47
  state: "transform" | "eval" = "transform";
48
48
  generated: Set<string>;
49
49
 
50
+ totalPossibleTransforms: number;
51
+
50
52
  constructor(public options: ObfuscateOptions) {
51
53
  super();
52
54
 
53
55
  this.varCount = 0;
54
56
  this.transforms = Object.create(null);
55
57
  this.generated = new Set();
58
+ this.totalPossibleTransforms = 0;
56
59
 
57
60
  this.push(new Preparation(this));
58
61
  this.push(new RenameLabels(this));
59
62
 
60
63
  const test = <T>(map: ProbabilityMap<T>, ...transformers: any[]) => {
64
+ this.totalPossibleTransforms += transformers.length;
65
+
61
66
  if (isProbabilityMapProbable(map)) {
62
67
  // options.verbose && console.log("+ Added " + transformer.name);
63
68
 
@@ -97,7 +102,7 @@ export default class Obfuscator extends EventEmitter {
97
102
  test(options.stack, Stack);
98
103
  test(true, AntiTooling);
99
104
  test(options.hideInitializingCode, HideInitializingCode);
100
- test(options.hexadecimalNumbers, HexadecimalNumbers);
105
+ test(true, HexadecimalNumbers); // BigInt support is included
101
106
 
102
107
  if (
103
108
  options.lock &&
package/src/options.ts CHANGED
@@ -867,8 +867,7 @@ export async function correctOptions(
867
867
  options.compact = true; // self defending forcibly enables this
868
868
  }
869
869
 
870
- // options.globalVariables was never used.
871
- // GlobalConcealing implicitly determines a global to be a variable referenced but never defined or modified.
870
+ // options.globalVariables outlines generic globals that should be present in the execution context
872
871
  if (!options.hasOwnProperty("globalVariables")) {
873
872
  options.globalVariables = new Set([]);
874
873
 
@@ -908,6 +907,10 @@ export async function correctOptions(
908
907
  "Array",
909
908
  "Proxy",
910
909
  "Error",
910
+ "TypeError",
911
+ "ReferenceError",
912
+ "RangeError",
913
+ "EvalError",
911
914
  "setTimeout",
912
915
  "clearTimeout",
913
916
  "setInterval",
@@ -919,6 +922,11 @@ export async function correctOptions(
919
922
  "module",
920
923
  "isNaN",
921
924
  "isFinite",
925
+ "Set",
926
+ "Map",
927
+ "WeakSet",
928
+ "WeakMap",
929
+ "Symbol",
922
930
  ].forEach((x) => options.globalVariables.add(x));
923
931
  }
924
932
 
package/src/order.ts CHANGED
@@ -44,11 +44,11 @@ export enum ObfuscateOrder {
44
44
 
45
45
  MovedDeclarations = 26,
46
46
 
47
- RenameVariables = 27,
47
+ RenameLabels = 27,
48
48
 
49
- RenameLabels = 28,
49
+ Minify = 28,
50
50
 
51
- Minify = 30,
51
+ RenameVariables = 30,
52
52
 
53
53
  ES5 = 31,
54
54
 
@@ -45,7 +45,7 @@ export default class AntiTooling extends Transform {
45
45
  exprs[0],
46
46
  ExpressionStatement(
47
47
  UnaryExpression(
48
- choice(["typeof", "void", "~", "!", "+"]),
48
+ choice(["typeof", "void", "!"]),
49
49
  SequenceExpression(flattened)
50
50
  )
51
51
  )
@@ -20,7 +20,13 @@ export default class ExpressionObfuscation extends Transform {
20
20
  if (stmt.type == "ExpressionStatement") {
21
21
  var expr = stmt.expression;
22
22
 
23
- if (expr.type == "UnaryExpression" && exprs.length) {
23
+ if (
24
+ expr.type == "UnaryExpression" &&
25
+ !(
26
+ expr.operator === "typeof" && expr.argument.type === "Identifier"
27
+ ) &&
28
+ exprs.length // typeof is special
29
+ ) {
24
30
  expr.argument = SequenceExpression([
25
31
  ...exprs,
26
32
  { ...expr.argument },
@@ -38,7 +44,13 @@ export default class ExpressionObfuscation extends Transform {
38
44
  stmt.test.type == "BinaryExpression" &&
39
45
  stmt.test.operator !== "**"
40
46
  ) {
41
- if (stmt.test.left.type == "UnaryExpression") {
47
+ if (
48
+ stmt.test.left.type == "UnaryExpression" &&
49
+ !(
50
+ stmt.test.left.operator === "typeof" &&
51
+ stmt.test.left.argument.type === "Identifier"
52
+ ) // typeof is special
53
+ ) {
42
54
  stmt.test.left.argument = SequenceExpression([
43
55
  ...exprs,
44
56
  { ...stmt.test.left.argument },
@@ -97,14 +97,15 @@ export default class Dispatcher extends Transform {
97
97
  }
98
98
 
99
99
  // Map of FunctionDeclarations
100
- var functionDeclarations: { [name: string]: Location } = {};
100
+ var functionDeclarations: { [name: string]: Location } =
101
+ Object.create(null);
101
102
 
102
103
  // Array of Identifier nodes
103
104
  var identifiers: Location[] = [];
104
105
  var illegalFnNames: Set<string> = new Set();
105
106
 
106
107
  // New Names for Functions
107
- var newFnNames: { [name: string]: string } = {}; // [old name]: randomized name
108
+ var newFnNames: { [name: string]: string } = Object.create(null); // [old name]: randomized name
108
109
 
109
110
  var context = isVarContext(object)
110
111
  ? object
@@ -469,7 +470,7 @@ export default class Dispatcher extends Transform {
469
470
  }
470
471
 
471
472
  var newName = newFnNames[o.name];
472
- if (!newName) {
473
+ if (!newName || typeof newName !== "string") {
473
474
  return;
474
475
  }
475
476
 
@@ -110,7 +110,16 @@ export default class AntiClass extends Transform {
110
110
  );
111
111
  }
112
112
 
113
- if (
113
+ // Support class fields
114
+ if (methodDefinition.type === "PropertyDefinition") {
115
+ var assignmentExpression = AssignmentExpression(
116
+ "=",
117
+ key,
118
+ value || Identifier("undefined")
119
+ );
120
+
121
+ pushingTo.push(ExpressionStatement(assignmentExpression));
122
+ } else if (
114
123
  methodDefinition.kind == "constructor" ||
115
124
  methodDefinition.kind == "method"
116
125
  ) {
@@ -266,7 +266,7 @@ export default class AntiDestructuring extends Transform {
266
266
  ]);
267
267
 
268
268
  if (object.type == "VariableDeclarator") {
269
- var i = getIndexDirect(object, parents);
269
+ var i = getIndexDirect(object, parents[0]);
270
270
 
271
271
  var extra = Array.from(names).map((x) => {
272
272
  return {
@@ -28,6 +28,24 @@ export default class Eval extends Transform {
28
28
  }
29
29
 
30
30
  transform(object, parents) {
31
+ // Don't apply to getter/setters or class methods
32
+ if (parents[0]) {
33
+ if (
34
+ parents[0].type === "MethodDefinition" &&
35
+ parents[0].value === object
36
+ ) {
37
+ return;
38
+ }
39
+
40
+ if (
41
+ parents[0].type === "Property" &&
42
+ parents[0].value === object &&
43
+ (parents[0].kind !== "init" || parents[0].method)
44
+ ) {
45
+ return;
46
+ }
47
+ }
48
+
31
49
  if (
32
50
  !ComputeProbabilityMap(
33
51
  this.options.eval,
@@ -159,7 +159,7 @@ export default class DuplicateLiteralsRemoval extends Transform {
159
159
  var body = [];
160
160
  var thisShift = getRandomInteger(-250, 250);
161
161
  // the name of the getter
162
- getterName = this.getPlaceholder();
162
+ getterName = this.getPlaceholder() + "_dLR_" + this.fnGetters.size;
163
163
 
164
164
  if (basedOn) {
165
165
  var shift = this.fnShifts.get(basedOn);
@@ -268,20 +268,20 @@ export default class DuplicateLiteralsRemoval extends Transform {
268
268
  this.arrayExpression = ArrayExpression([]);
269
269
  }
270
270
 
271
- var first = this.first.get(value);
272
- if (first) {
271
+ var firstLocation = this.first.get(value);
272
+ if (firstLocation) {
273
273
  this.first.set(value, null);
274
274
  var index = this.map.size;
275
275
 
276
276
  ok(!this.map.has(value));
277
277
  this.map.set(value, index);
278
278
 
279
- this.toCaller(first[0], first[1], index);
280
-
281
279
  var pushing = clone(object);
282
280
  this.arrayExpression.elements.push(pushing);
283
281
 
284
282
  ok(this.arrayExpression.elements[index] === pushing);
283
+
284
+ this.toCaller(firstLocation[0], firstLocation[1], index);
285
285
  }
286
286
 
287
287
  var index = this.map.get(value);
@@ -100,11 +100,18 @@ export default class ObjectExtraction extends Transform {
100
100
  );
101
101
 
102
102
  if (nonInitOrComputed) {
103
- this.log(
104
- name +
105
- " has non-init/computed property: " +
106
- nonInitOrComputed.key.name || nonInitOrComputed.key.value
107
- );
103
+ if (nonInitOrComputed.key) {
104
+ this.log(
105
+ name +
106
+ " has non-init/computed property: " +
107
+ nonInitOrComputed.key.name || nonInitOrComputed.key.value
108
+ );
109
+ } else {
110
+ this.log(
111
+ name + " has spread-element or other type of property"
112
+ );
113
+ }
114
+
108
115
  illegal.add(name);
109
116
  return;
110
117
  } else {