js-confuser 1.5.0 → 1.5.2

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/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ # `1.5.2`
2
+ Mini fixes
3
+
4
+ - Fixed [#41](https://github.com/MichaelXF/js-confuser/issues/41)
5
+ - - Obfuscator mishandled switch statements with a `default` case
6
+
7
+ - Fixed [#43](https://github.com/MichaelXF/js-confuser/issues/43)
8
+ - - Obfuscator mishandled variable destructuring in for-loops
9
+
10
+ # `1.5.1`
11
+ Object Extraction Fix
12
+
13
+ - Fixed [#37](https://github.com/MichaelXF/js-confuser/issues/37)
14
+ - - Object Extraction was applying to objects with get/set methods, fixed in this version.
15
+
16
+ - Slight improvement to `Flatten`
17
+
1
18
  # `1.5.0`
2
19
  Hexadecimal Numbers
3
20
 
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  JS-Confuser is a JavaScript obfuscation tool to make your programs _impossible_ to read. [Try the web version](https://jsconfuser.com).
4
4
 
5
+ [![NPM](https://img.shields.io/badge/NPM-%23000000.svg?style=for-the-badge&logo=npm&logoColor=white)](https://npmjs.com/package/js-confuser) [![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/MichaelXF/js-confuser) [![Netlify](https://img.shields.io/badge/netlify-%23000000.svg?style=for-the-badge&logo=netlify&logoColor=#00C7B7)](https://jsconfuser.com)
6
+
5
7
  ## Key features
6
8
 
7
9
  - Variable renaming
@@ -28,7 +28,7 @@ class SwitchCaseObfuscation extends _transform.default {
28
28
  }
29
29
 
30
30
  match(object, parents) {
31
- return object.type == "SwitchStatement" && !object.cases.find(x => !(x.test.type == "Literal" && typeof x.test.value === "number" && Math.abs(x.test.value) < 100000));
31
+ return object.type == "SwitchStatement" && !object.cases.find(x => !(x.test && typeof x.test === "object" && x.test.type == "Literal" && typeof x.test.value === "number" && Math.abs(x.test.value) < 100000));
32
32
  }
33
33
 
34
34
  transform(object, parents) {
@@ -23,6 +23,8 @@ var _probability = require("../../probability");
23
23
 
24
24
  var _assert = require("assert");
25
25
 
26
+ var _guard = require("../../util/guard");
27
+
26
28
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
27
29
 
28
30
  /**
@@ -84,17 +86,18 @@ class ObjectExtraction extends _transform.default {
84
86
  illegal.add(name);
85
87
  return;
86
88
  } // check for computed properties
89
+ // Change String literals to non-computed
87
90
 
88
91
 
89
92
  object.properties.forEach(prop => {
90
- if (prop.computed && prop.key.type == "Literal") {
93
+ if (prop.computed && (0, _guard.isStringLiteral)(prop.key)) {
91
94
  prop.computed = false;
92
95
  }
93
96
  });
94
- var computed = object.properties.find(x => x.computed);
97
+ var nonInitOrComputed = object.properties.find(x => x.kind !== "init" || x.computed);
95
98
 
96
- if (computed) {
97
- this.log(name + " has computed property: " + computed.key.name || computed.key.value);
99
+ if (nonInitOrComputed) {
100
+ this.log(name + " has non-init/computed property: " + nonInitOrComputed.key.name || nonInitOrComputed.key.value);
98
101
  illegal.add(name);
99
102
  return;
100
103
  } else {
@@ -17,6 +17,8 @@ var _identifiers = require("../util/identifiers");
17
17
 
18
18
  var _insert = require("../util/insert");
19
19
 
20
+ var _random = require("../util/random");
21
+
20
22
  var _transform = _interopRequireDefault(require("./transform"));
21
23
 
22
24
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -44,7 +46,16 @@ class Flatten extends _transform.default {
44
46
 
45
47
  _defineProperty(this, "definedNames", void 0);
46
48
 
49
+ _defineProperty(this, "flatMapName", void 0);
50
+
51
+ _defineProperty(this, "flatNode", void 0);
52
+
53
+ _defineProperty(this, "gen", void 0);
54
+
47
55
  this.definedNames = new Map();
56
+ this.flatMapName = null;
57
+ this.flatNode = null;
58
+ this.gen = this.getGenerator();
48
59
  }
49
60
 
50
61
  apply(tree) {
@@ -175,7 +186,10 @@ class Flatten extends _transform.default {
175
186
  }
176
187
 
177
188
  var output = Array.from(modified);
178
- var newName = "flatten" + this.getPlaceholder() + "_" + (object.id && object.id.name || "fn");
189
+ var newName = this.gen.generate();
190
+ var valName = this.getPlaceholder();
191
+ var resultName = this.getPlaceholder();
192
+ var propName = this.gen.generate();
179
193
  (0, _insert.getBlockBody)(object.body).push((0, _gen.ReturnStatement)());
180
194
  (0, _traverse.walk)(object.body, [object, ...parents], (o, p) => {
181
195
  return () => {
@@ -187,33 +201,51 @@ class Flatten extends _transform.default {
187
201
  }
188
202
 
189
203
  o.argument = (0, _gen.ArrayExpression)(elements);
204
+ o.argument = (0, _gen.AssignmentExpression)("=", (0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(propName), false), o.argument);
190
205
  }
191
206
  };
192
207
  });
193
208
  var newBody = (0, _insert.getBlockBody)(object.body);
209
+ newBody.unshift((0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)((0, _gen.ArrayPattern)([(0, _gen.ArrayPattern)(input.map(_gen.Identifier)), (0, _gen.ArrayPattern)((0, _insert.clone)(object.params)), (0, _gen.Identifier)(resultName)]), (0, _gen.Identifier)(valName))));
194
210
 
195
- if (input.length) {
196
- newBody.unshift((0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)((0, _gen.ArrayPattern)(input.map(_gen.Identifier)), (0, _gen.ThisExpression)())));
211
+ if (!this.flatMapName) {
212
+ this.flatMapName = this.getPlaceholder();
213
+ (0, _insert.prepend)(parents[parents.length - 1], (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(this.flatMapName, this.flatNode = (0, _gen.ObjectExpression)([]))));
197
214
  }
198
215
 
199
- var newFunctionDeclaration = (0, _gen.FunctionDeclaration)(newName, (0, _insert.clone)(object.params), newBody);
200
- newFunctionDeclaration.async = !!object.async;
201
- newFunctionDeclaration.generator = !!object.generator;
202
- (0, _insert.prepend)(parents[parents.length - 1], newFunctionDeclaration);
216
+ var newFunctionExpression = (0, _gen.FunctionExpression)([(0, _gen.Identifier)(valName)], newBody);
217
+ newFunctionExpression.async = !!object.async;
218
+ newFunctionExpression.generator = !!object.generator;
219
+ var property = (0, _gen.Property)((0, _gen.Identifier)(newName), newFunctionExpression, false);
220
+ property.kind = "set";
221
+ this.flatNode.properties.push(property);
222
+ var identifier = (0, _gen.MemberExpression)((0, _gen.Identifier)(this.flatMapName), (0, _gen.Identifier)(newName), false);
203
223
  var newParamNodes = object.params.map(() => (0, _gen.Identifier)(this.getPlaceholder())); // var result = newFn.call([...refs], ...arguments)
204
224
 
205
- var call = (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)("result", (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(newName), (0, _gen.Identifier)("call"), false), [(0, _gen.ArrayExpression)(input.map(_gen.Identifier)), ...newParamNodes]))); // result.pop()
225
+ var call = (0, _gen.VariableDeclaration)([(0, _gen.VariableDeclarator)(resultName, (0, _gen.ArrayExpression)([])), (0, _gen.VariableDeclarator)("_", (0, _gen.AssignmentExpression)("=", identifier, (0, _gen.ArrayExpression)([(0, _gen.ArrayExpression)(input.map(_gen.Identifier)), (0, _gen.ArrayExpression)([...newParamNodes]), (0, _gen.Identifier)(resultName)])))]); // result.pop()
206
226
 
207
- var pop = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)("result"), (0, _gen.Identifier)("pop"), false), []); // var result = newFn.call([...refs], ...arguments)
227
+ var pop = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(propName), false), (0, _gen.Identifier)("pop"), false), []); // var result = newFn.call([...refs], ...arguments)
208
228
  // modified1 = result.pop();
209
229
  // modified2 = result.pop();
210
230
  // ...modifiedN = result.pop();...
211
231
  //
212
232
  // return result.pop()
213
233
 
214
- object.body = (0, _gen.BlockStatement)([call, ...[...output].reverse().map(name => {
234
+ var newObjectBody = [call];
235
+ var outputReversed = [...output].reverse(); // DECOY STATEMENTS
236
+
237
+ var decoyKey = this.gen.generate();
238
+ var decoyNodes = [(0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(this.gen.generate()), false), [(0, _gen.ThrowStatement)((0, _gen.NewExpression)((0, _gen.Identifier)("Error"), [(0, _gen.Literal)(this.getPlaceholder())]))]), (0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(this.gen.generate()), false), [(0, _gen.ReturnStatement)((0, _gen.Identifier)(resultName))]), (0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(this.gen.generate()), false), [(0, _gen.ReturnStatement)((0, _gen.Identifier)(resultName))]), (0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(decoyKey), false), [(0, _gen.ReturnStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(decoyKey), false))]), (0, _gen.IfStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(this.gen.generate()), false), [(0, _gen.ReturnStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(resultName), (0, _gen.Identifier)(this.gen.generate()), false))])];
239
+ (0, _random.shuffle)(decoyNodes);
240
+ decoyNodes.forEach(decoyNode => {
241
+ if (Math.random() < 0.5) {
242
+ newObjectBody.push(decoyNode);
243
+ }
244
+ });
245
+ newObjectBody.push(...outputReversed.map(name => {
215
246
  return (0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(name), (0, _insert.clone)(pop)));
216
- }), (0, _gen.ReturnStatement)((0, _insert.clone)(pop))]);
247
+ }), (0, _gen.ReturnStatement)((0, _insert.clone)(pop)));
248
+ object.body = (0, _gen.BlockStatement)(newObjectBody);
217
249
  object.params = newParamNodes;
218
250
  };
219
251
  }
@@ -457,7 +457,7 @@ class Minify extends _transform.default {
457
457
  } // check for redundant patterns
458
458
 
459
459
 
460
- if (object.id.type == "ArrayPattern" && object.init.type == "ArrayExpression") {
460
+ if (object.id.type == "ArrayPattern" && object.init && typeof object.init === "object" && object.init.type == "ArrayExpression") {
461
461
  if (object.id.elements.length == 1 && object.init.elements.length == 1) {
462
462
  object.id = object.id.elements[0];
463
463
  object.init = object.init.elements[0];
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isStringLiteral = isStringLiteral;
7
+
8
+ function isStringLiteral(node) {
9
+ return node.type === "Literal" && typeof node.value === "string" && !node.regex;
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-confuser",
3
- "version": "1.5.0",
3
+ "version": "1.5.2",
4
4
  "description": "JavaScript Obfuscation Tool.",
5
5
  "main": "dist/index.js",
6
6
  "types": "index.d.ts",
@@ -27,6 +27,8 @@ export default class SwitchCaseObfuscation extends Transform {
27
27
  !object.cases.find(
28
28
  (x) =>
29
29
  !(
30
+ x.test &&
31
+ typeof x.test === "object" &&
30
32
  x.test.type == "Literal" &&
31
33
  typeof x.test.value === "number" &&
32
34
  Math.abs(x.test.value) < 100_000
@@ -19,6 +19,7 @@ import { getIdentifierInfo } from "../../util/identifiers";
19
19
  import { isValidIdentifier } from "../../util/compare";
20
20
  import { ComputeProbabilityMap } from "../../probability";
21
21
  import { ok } from "assert";
22
+ import { isStringLiteral } from "../../util/guard";
22
23
 
23
24
  /**
24
25
  * Extracts keys out of an object if possible.
@@ -87,17 +88,22 @@ export default class ObjectExtraction extends Transform {
87
88
  }
88
89
 
89
90
  // check for computed properties
91
+ // Change String literals to non-computed
90
92
  object.properties.forEach((prop) => {
91
- if (prop.computed && prop.key.type == "Literal") {
93
+ if (prop.computed && isStringLiteral(prop.key)) {
92
94
  prop.computed = false;
93
95
  }
94
96
  });
95
97
 
96
- var computed = object.properties.find((x) => x.computed);
97
- if (computed) {
98
+ var nonInitOrComputed = object.properties.find(
99
+ (x) => x.kind !== "init" || x.computed
100
+ );
101
+
102
+ if (nonInitOrComputed) {
98
103
  this.log(
99
- name + " has computed property: " + computed.key.name ||
100
- computed.key.value
104
+ name +
105
+ " has non-init/computed property: " +
106
+ nonInitOrComputed.key.name || nonInitOrComputed.key.value
101
107
  );
102
108
  illegal.add(name);
103
109
  return;
@@ -16,6 +16,14 @@ import {
16
16
  Node,
17
17
  BlockStatement,
18
18
  ArrayPattern,
19
+ FunctionExpression,
20
+ ObjectExpression,
21
+ Property,
22
+ SpreadElement,
23
+ Literal,
24
+ IfStatement,
25
+ ThrowStatement,
26
+ NewExpression,
19
27
  } from "../util/gen";
20
28
  import { getIdentifierInfo } from "../util/identifiers";
21
29
  import {
@@ -25,6 +33,7 @@ import {
25
33
  prepend,
26
34
  clone,
27
35
  } from "../util/insert";
36
+ import { shuffle } from "../util/random";
28
37
  import Transform from "./transform";
29
38
 
30
39
  /**
@@ -41,10 +50,17 @@ import Transform from "./transform";
41
50
  export default class Flatten extends Transform {
42
51
  definedNames: Map<Node, Set<string>>;
43
52
 
53
+ flatMapName: string;
54
+ flatNode: Node;
55
+ gen: any;
56
+
44
57
  constructor(o) {
45
58
  super(o, ObfuscateOrder.Flatten);
46
59
 
47
60
  this.definedNames = new Map();
61
+ this.flatMapName = null;
62
+ this.flatNode = null;
63
+ this.gen = this.getGenerator();
48
64
  }
49
65
 
50
66
  apply(tree) {
@@ -200,11 +216,10 @@ export default class Flatten extends Transform {
200
216
 
201
217
  var output = Array.from(modified);
202
218
 
203
- var newName =
204
- "flatten" +
205
- this.getPlaceholder() +
206
- "_" +
207
- ((object.id && object.id.name) || "fn");
219
+ var newName = this.gen.generate();
220
+ var valName = this.getPlaceholder();
221
+ var resultName = this.getPlaceholder();
222
+ var propName = this.gen.generate();
208
223
 
209
224
  getBlockBody(object.body).push(ReturnStatement());
210
225
  walk(object.body, [object, ...parents], (o, p) => {
@@ -222,51 +237,100 @@ export default class Flatten extends Transform {
222
237
  }
223
238
 
224
239
  o.argument = ArrayExpression(elements);
240
+
241
+ o.argument = AssignmentExpression(
242
+ "=",
243
+ MemberExpression(
244
+ Identifier(resultName),
245
+ Identifier(propName),
246
+ false
247
+ ),
248
+ o.argument
249
+ );
225
250
  }
226
251
  };
227
252
  });
228
253
 
229
254
  var newBody = getBlockBody(object.body);
230
255
 
231
- if (input.length) {
232
- newBody.unshift(
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],
233
274
  VariableDeclaration(
234
275
  VariableDeclarator(
235
- ArrayPattern(input.map(Identifier)),
236
- ThisExpression()
276
+ this.flatMapName,
277
+ (this.flatNode = ObjectExpression([]))
237
278
  )
238
279
  )
239
280
  );
240
281
  }
241
282
 
242
- var newFunctionDeclaration = FunctionDeclaration(
243
- newName,
244
- clone(object.params),
283
+ var newFunctionExpression = FunctionExpression(
284
+ [Identifier(valName)],
245
285
  newBody
246
286
  );
247
- newFunctionDeclaration.async = !!object.async;
248
- newFunctionDeclaration.generator = !!object.generator;
249
287
 
250
- prepend(parents[parents.length - 1], newFunctionDeclaration);
288
+ newFunctionExpression.async = !!object.async;
289
+ newFunctionExpression.generator = !!object.generator;
290
+
291
+ var property = Property(
292
+ Identifier(newName),
293
+ newFunctionExpression,
294
+ false
295
+ );
296
+ property.kind = "set";
297
+
298
+ this.flatNode.properties.push(property);
299
+
300
+ var identifier = MemberExpression(
301
+ Identifier(this.flatMapName),
302
+ Identifier(newName),
303
+ false
304
+ );
251
305
 
252
306
  var newParamNodes = object.params.map(() =>
253
307
  Identifier(this.getPlaceholder())
254
308
  );
255
309
 
256
310
  // var result = newFn.call([...refs], ...arguments)
257
- var call = VariableDeclaration(
311
+ var call = VariableDeclaration([
312
+ VariableDeclarator(resultName, ArrayExpression([])),
258
313
  VariableDeclarator(
259
- "result",
260
- CallExpression(
261
- MemberExpression(Identifier(newName), Identifier("call"), false),
262
- [ArrayExpression(input.map(Identifier)), ...newParamNodes]
314
+ "_",
315
+ AssignmentExpression(
316
+ "=",
317
+ identifier,
318
+ ArrayExpression([
319
+ ArrayExpression(input.map(Identifier)),
320
+ ArrayExpression([...newParamNodes]),
321
+ Identifier(resultName),
322
+ ])
263
323
  )
264
- )
265
- );
324
+ ),
325
+ ]);
266
326
 
267
327
  // result.pop()
268
328
  var pop = CallExpression(
269
- MemberExpression(Identifier("result"), Identifier("pop"), false),
329
+ MemberExpression(
330
+ MemberExpression(Identifier(resultName), Identifier(propName), false),
331
+ Identifier("pop"),
332
+ false
333
+ ),
270
334
  []
271
335
  );
272
336
 
@@ -277,16 +341,90 @@ export default class Flatten extends Transform {
277
341
  //
278
342
  // return result.pop()
279
343
 
280
- object.body = BlockStatement([
281
- call,
282
- ...[...output].reverse().map((name) => {
344
+ var newObjectBody: Node[] = [call];
345
+ var outputReversed = [...output].reverse();
346
+
347
+ // DECOY STATEMENTS
348
+ var decoyKey = this.gen.generate();
349
+ var decoyNodes = [
350
+ IfStatement(
351
+ MemberExpression(
352
+ Identifier(resultName),
353
+ Identifier(this.gen.generate()),
354
+ false
355
+ ),
356
+ [
357
+ ThrowStatement(
358
+ NewExpression(Identifier("Error"), [
359
+ Literal(this.getPlaceholder()),
360
+ ])
361
+ ),
362
+ ]
363
+ ),
364
+ IfStatement(
365
+ MemberExpression(
366
+ Identifier(resultName),
367
+ Identifier(this.gen.generate()),
368
+ false
369
+ ),
370
+ [ReturnStatement(Identifier(resultName))]
371
+ ),
372
+ IfStatement(
373
+ MemberExpression(
374
+ Identifier(resultName),
375
+ Identifier(this.gen.generate()),
376
+ false
377
+ ),
378
+ [ReturnStatement(Identifier(resultName))]
379
+ ),
380
+ IfStatement(
381
+ MemberExpression(Identifier(resultName), Identifier(decoyKey), false),
382
+ [
383
+ ReturnStatement(
384
+ MemberExpression(
385
+ Identifier(resultName),
386
+ Identifier(decoyKey),
387
+ false
388
+ )
389
+ ),
390
+ ]
391
+ ),
392
+ IfStatement(
393
+ MemberExpression(
394
+ Identifier(resultName),
395
+ Identifier(this.gen.generate()),
396
+ false
397
+ ),
398
+ [
399
+ ReturnStatement(
400
+ MemberExpression(
401
+ Identifier(resultName),
402
+ Identifier(this.gen.generate()),
403
+ false
404
+ )
405
+ ),
406
+ ]
407
+ ),
408
+ ];
409
+
410
+ shuffle(decoyNodes);
411
+ decoyNodes.forEach((decoyNode) => {
412
+ if (Math.random() < 0.5) {
413
+ newObjectBody.push(decoyNode);
414
+ }
415
+ });
416
+
417
+ newObjectBody.push(
418
+ ...outputReversed.map((name) => {
283
419
  return ExpressionStatement(
284
420
  AssignmentExpression("=", Identifier(name), clone(pop))
285
421
  );
286
422
  }),
287
423
 
288
- ReturnStatement(clone(pop)),
289
- ]);
424
+ ReturnStatement(clone(pop))
425
+ );
426
+
427
+ object.body = BlockStatement(newObjectBody);
290
428
 
291
429
  object.params = newParamNodes;
292
430
  };
@@ -595,6 +595,8 @@ export default class Minify extends Transform {
595
595
  // check for redundant patterns
596
596
  if (
597
597
  object.id.type == "ArrayPattern" &&
598
+ object.init &&
599
+ typeof object.init === "object" &&
598
600
  object.init.type == "ArrayExpression"
599
601
  ) {
600
602
  if (
package/src/util/gen.ts CHANGED
@@ -58,7 +58,7 @@ export type EvalCallback = {
58
58
  */
59
59
  export type Chain = Node[];
60
60
 
61
- export function Literal(value: string | number | boolean) {
61
+ export function Literal(value: string | number | boolean): Node {
62
62
  if (typeof value === "undefined") {
63
63
  throw new Error("value is undefined");
64
64
  }
@@ -0,0 +1,7 @@
1
+ import { Node } from "./gen";
2
+
3
+ export function isStringLiteral(node: Node) {
4
+ return (
5
+ node.type === "Literal" && typeof node.value === "string" && !node.regex
6
+ );
7
+ }
@@ -74,3 +74,47 @@ it("should not obfuscate switch statements with complex discriminants (SwitchCas
74
74
 
75
75
  eval(output);
76
76
  });
77
+
78
+ // https://github.com/MichaelXF/js-confuser/issues/41
79
+ it("Not apply to switch statements with default cases", async ()=>{
80
+
81
+ var code = `
82
+ var array = [];
83
+
84
+ function runOnce(stateParam){
85
+ switch(stateParam){
86
+ case 1: array.push(1, 2, 3); break;
87
+ case 2: array.push(4, 5, 6); break;
88
+ case 3: array.push(7, 8, 9); break;
89
+ default: array.push(10); break;
90
+ }
91
+ }
92
+
93
+ runOnce(1);
94
+ runOnce(2);
95
+ runOnce(3);
96
+ runOnce(-1); // default case
97
+
98
+ input(array);
99
+ `;
100
+
101
+ var output = await JsConfuser(code, {
102
+ target: "browser",
103
+ controlFlowFlattening: true,
104
+ });
105
+
106
+ expect(
107
+ output.includes("case 1:") &&
108
+ output.includes("case 2:") &&
109
+ output.includes("case 3:")
110
+ ).toStrictEqual(true);
111
+
112
+ function input(array) {
113
+ expect(array).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
114
+ }
115
+
116
+ eval(output);
117
+
118
+
119
+
120
+ });
@@ -423,3 +423,26 @@ it("should properly use custom callback to exclude certain names from being chan
423
423
 
424
424
  eval(output);
425
425
  });
426
+
427
+ it("should not apply to objects with non-init properties (method, set, get)", async () => {
428
+ var code = `
429
+
430
+ var realValue = 0;
431
+ var TEST_OBJECT = {
432
+ set key(newValue){
433
+ realValue = newValue;
434
+ },
435
+ get key(){
436
+ return realValue;
437
+ }
438
+ };
439
+ `;
440
+
441
+ var output = await JsConfuser(code, {
442
+ target: "node",
443
+ objectExtraction: true,
444
+ });
445
+
446
+ expect(output).toContain("TEST_OBJECT");
447
+ expect(output).toContain("set ");
448
+ });
@@ -17,7 +17,7 @@ it("should bring independent to the global level", async () => {
17
17
  }
18
18
  );
19
19
 
20
- expect(output.startsWith("function flatten_")).toStrictEqual(true);
20
+ expect(output).toContain("set");
21
21
  });
22
22
 
23
23
  it("should have correct return values", async () => {
@@ -227,7 +227,7 @@ it("should not change functions with const", async () => {
227
227
  }
228
228
  );
229
229
 
230
- expect(output).not.toContain("this");
230
+ expect(output).not.toContain("set");
231
231
 
232
232
  var value = "never_called",
233
233
  input = (x) => (value = x);
@@ -255,7 +255,7 @@ it("should work when pattern-based assignment expressions are involved", async (
255
255
  }
256
256
  );
257
257
 
258
- expect(output).toContain("this");
258
+ expect(output).toContain("set");
259
259
 
260
260
  var value = "never_called",
261
261
  input = (x) => (value = x);
@@ -299,3 +299,25 @@ test("Variant #15: Removing implied 'return'", async () => {
299
299
 
300
300
  expect(output2).toContain("return");
301
301
  });
302
+
303
+ // https://github.com/MichaelXF/js-confuser/issues/43
304
+ test("Variant #16: Handle deconstructuring in for loop", async ()=>{
305
+ // Valid
306
+ var output = await JsConfuser(
307
+ `
308
+ for(const [a] of [[1]]) {
309
+ input(a);
310
+ }
311
+ `,
312
+ { target: "node", minify: true }
313
+ );
314
+
315
+ var value;
316
+ function input(valueIn){
317
+ value = valueIn;
318
+ }
319
+
320
+ eval(output);
321
+
322
+ expect(value).toStrictEqual(1);
323
+ })