js-confuser 1.7.1 → 1.7.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.
Files changed (123) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +12 -27
  3. package/dist/compiler.js +2 -8
  4. package/dist/constants.js +17 -10
  5. package/dist/index.js +7 -30
  6. package/dist/obfuscator.js +15 -62
  7. package/dist/options.js +21 -38
  8. package/dist/order.js +4 -7
  9. package/dist/parser.js +5 -13
  10. package/dist/precedence.js +6 -8
  11. package/dist/presets.js +4 -6
  12. package/dist/probability.js +13 -24
  13. package/dist/templates/bufferToString.js +100 -5
  14. package/dist/templates/crash.js +51 -9
  15. package/dist/templates/es5.js +125 -6
  16. package/dist/templates/functionLength.js +24 -6
  17. package/dist/templates/globals.js +9 -0
  18. package/dist/templates/template.js +71 -30
  19. package/dist/transforms/antiTooling.js +26 -22
  20. package/dist/transforms/calculator.js +18 -54
  21. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +236 -333
  22. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +46 -25
  23. package/dist/transforms/deadCode.js +528 -27
  24. package/dist/transforms/dispatcher.js +106 -110
  25. package/dist/transforms/es5/antiClass.js +70 -44
  26. package/dist/transforms/es5/antiDestructuring.js +14 -38
  27. package/dist/transforms/es5/antiES6Object.js +39 -48
  28. package/dist/transforms/es5/antiSpreadOperator.js +5 -14
  29. package/dist/transforms/es5/antiTemplate.js +10 -19
  30. package/dist/transforms/es5/es5.js +7 -40
  31. package/dist/transforms/extraction/classExtraction.js +83 -0
  32. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +41 -80
  33. package/dist/transforms/extraction/objectExtraction.js +24 -56
  34. package/dist/transforms/finalizer.js +6 -20
  35. package/dist/transforms/flatten.js +51 -99
  36. package/dist/transforms/identifier/globalAnalysis.js +8 -26
  37. package/dist/transforms/identifier/globalConcealing.js +35 -54
  38. package/dist/transforms/identifier/movedDeclarations.js +66 -38
  39. package/dist/transforms/identifier/renameVariables.js +29 -68
  40. package/dist/transforms/identifier/variableAnalysis.js +21 -48
  41. package/dist/transforms/lock/antiDebug.js +20 -25
  42. package/dist/transforms/lock/integrity.js +48 -47
  43. package/dist/transforms/lock/lock.js +62 -113
  44. package/dist/transforms/minify.js +77 -108
  45. package/dist/transforms/opaquePredicates.js +11 -48
  46. package/dist/transforms/preparation.js +17 -50
  47. package/dist/transforms/renameLabels.js +5 -22
  48. package/dist/transforms/rgf.js +93 -69
  49. package/dist/transforms/shuffle.js +41 -46
  50. package/dist/transforms/stack.js +35 -98
  51. package/dist/transforms/string/encoding.js +73 -27
  52. package/dist/transforms/string/stringCompression.js +44 -68
  53. package/dist/transforms/string/stringConcealing.js +125 -134
  54. package/dist/transforms/string/stringEncoding.js +6 -26
  55. package/dist/transforms/string/stringSplitting.js +5 -30
  56. package/dist/transforms/transform.js +50 -100
  57. package/dist/traverse.js +11 -18
  58. package/dist/util/compare.js +27 -29
  59. package/dist/util/gen.js +32 -86
  60. package/dist/util/guard.js +0 -1
  61. package/dist/util/identifiers.js +9 -72
  62. package/dist/util/insert.js +27 -77
  63. package/dist/util/math.js +0 -3
  64. package/dist/util/object.js +3 -7
  65. package/dist/util/random.js +5 -36
  66. package/dist/util/scope.js +6 -3
  67. package/package.json +3 -3
  68. package/src/constants.ts +12 -0
  69. package/src/options.ts +13 -0
  70. package/src/order.ts +2 -2
  71. package/src/templates/bufferToString.ts +49 -11
  72. package/src/templates/functionLength.ts +21 -3
  73. package/src/templates/globals.ts +3 -0
  74. package/src/templates/template.ts +85 -25
  75. package/src/transforms/antiTooling.ts +33 -11
  76. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +2 -2
  77. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +46 -10
  78. package/src/transforms/deadCode.ts +0 -16
  79. package/src/transforms/dispatcher.ts +91 -69
  80. package/src/transforms/es5/antiClass.ts +10 -1
  81. package/src/transforms/extraction/classExtraction.ts +168 -0
  82. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +9 -10
  83. package/src/transforms/extraction/objectExtraction.ts +4 -15
  84. package/src/transforms/flatten.ts +20 -5
  85. package/src/transforms/identifier/globalConcealing.ts +29 -65
  86. package/src/transforms/identifier/movedDeclarations.ts +90 -24
  87. package/src/transforms/minify.ts +27 -12
  88. package/src/transforms/rgf.ts +94 -5
  89. package/src/transforms/stack.ts +12 -3
  90. package/src/transforms/string/encoding.ts +85 -51
  91. package/src/transforms/string/stringCompression.ts +5 -8
  92. package/src/transforms/string/stringConcealing.ts +139 -113
  93. package/src/transforms/string/stringEncoding.ts +1 -2
  94. package/src/transforms/string/stringSplitting.ts +1 -2
  95. package/src/transforms/transform.ts +30 -1
  96. package/src/util/compare.ts +39 -5
  97. package/src/util/gen.ts +10 -3
  98. package/src/util/insert.ts +17 -0
  99. package/src/util/scope.ts +14 -2
  100. package/test/code/Cash.test.ts +10 -4
  101. package/test/code/StrictMode.src.js +65 -0
  102. package/test/code/StrictMode.test.js +37 -0
  103. package/test/compare.test.ts +62 -2
  104. package/test/options.test.ts +111 -55
  105. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +37 -18
  106. package/test/transforms/dispatcher.test.ts +55 -0
  107. package/test/transforms/extraction/classExtraction.test.ts +86 -0
  108. package/test/transforms/extraction/duplicateLiteralsRemoval.test.ts +8 -0
  109. package/test/transforms/extraction/objectExtraction.test.ts +2 -0
  110. package/test/transforms/identifier/globalConcealing.test.ts +19 -0
  111. package/test/transforms/identifier/movedDeclarations.test.ts +61 -0
  112. package/test/transforms/minify.test.ts +37 -0
  113. package/test/transforms/rgf.test.ts +50 -0
  114. package/dist/transforms/controlFlowFlattening/choiceFlowObfuscation.js +0 -62
  115. package/dist/transforms/controlFlowFlattening/controlFlowObfuscation.js +0 -159
  116. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +0 -106
  117. package/dist/transforms/eval.js +0 -84
  118. package/dist/transforms/hexadecimalNumbers.js +0 -63
  119. package/dist/transforms/hideInitializingCode.js +0 -270
  120. package/dist/transforms/identifier/nameRecycling.js +0 -218
  121. package/dist/transforms/label.js +0 -67
  122. package/dist/transforms/preparation/nameConflicts.js +0 -116
  123. package/dist/transforms/preparation/preparation.js +0 -188
@@ -74,19 +74,52 @@ export function isDirective(object: Node, parents: Node[]) {
74
74
  return parents[dIndex].expression == (parents[dIndex - 1] || object);
75
75
  }
76
76
 
77
+ export function isModuleSource(object: Node, parents: Node[]) {
78
+ if (!parents[0]) {
79
+ return false;
80
+ }
81
+
82
+ if (parents[0].type == "ImportDeclaration" && parents[0].source == object) {
83
+ return true;
84
+ }
85
+
86
+ if (parents[0].type == "ImportExpression" && parents[0].source == object) {
87
+ return true;
88
+ }
89
+
90
+ if (
91
+ parents[1] &&
92
+ parents[1].type == "CallExpression" &&
93
+ parents[1].arguments[0] === object &&
94
+ parents[1].callee.type == "Identifier"
95
+ ) {
96
+ if (
97
+ parents[1].callee.name == "require" ||
98
+ parents[1].callee.name == "import"
99
+ ) {
100
+ return true;
101
+ }
102
+ }
103
+
104
+ return false;
105
+ }
106
+
107
+ export function isMoveable(object: Node, parents: Node[]) {
108
+ return !isDirective(object, parents) && !isModuleSource(object, parents);
109
+ }
110
+
77
111
  export function isIndependent(object: Node, parents: Node[]) {
78
112
  if (object.type == "Literal") {
79
113
  return true;
80
114
  }
81
115
 
82
- var parent = parents[0];
83
-
84
116
  if (object.type == "Identifier") {
85
- var set = new Set(["null", "undefined"]);
86
- if (set.has(object.name)) {
117
+ if (primitiveIdentifiers.has(object.name)) {
87
118
  return true;
88
119
  }
89
- if (parent.type == "Property") {
120
+
121
+ var parent = parents[0];
122
+ if (parent && parent.type == "Property") {
90
123
  if (!parent.computed && parent.key == object) {
91
124
  return true;
92
125
  }
@@ -105,6 +138,7 @@ export function isIndependent(object: Node, parents: Node[]) {
105
138
  if (object != $object) {
106
139
  if (!Array.isArray($object) && !isIndependent($object, $parents)) {
107
140
  allowIt = false;
141
+ return "EXIT";
108
142
  }
109
143
  }
110
144
  });
package/src/util/gen.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { ok } from "assert";
2
+ import { predictableFunctionTag } from "../constants";
2
3
  import { isValidIdentifier } from "./compare";
3
4
 
4
5
  export type Type =
@@ -306,6 +307,7 @@ export function FunctionExpression(params: Node[], body: any[]) {
306
307
  generator: false,
307
308
  expression: false,
308
309
  async: false,
310
+ [predictableFunctionTag]: true,
309
311
  };
310
312
  }
311
313
 
@@ -340,6 +342,7 @@ export function FunctionDeclaration(
340
342
  generator: false,
341
343
  expression: false,
342
344
  async: false,
345
+ [predictableFunctionTag]: true,
343
346
  };
344
347
  }
345
348
 
@@ -529,16 +532,20 @@ export function AddComment(node: Node, text: string) {
529
532
  return node;
530
533
  }
531
534
 
535
+ export function Super() {
536
+ return { type: "Super" };
537
+ }
538
+
532
539
  export function MethodDefinition(
533
- identifier: Node,
540
+ key: Node,
534
541
  functionExpression: Node,
535
542
  kind: "method" | "constructor" | "get" | "set",
536
- isStatic = true,
543
+ isStatic = false,
537
544
  computed = false
538
545
  ) {
539
546
  return {
540
547
  type: "MethodDefinition",
541
- key: identifier,
548
+ key: key,
542
549
  computed: computed,
543
550
  value: functionExpression,
544
551
  kind: kind,
@@ -3,6 +3,12 @@ import { getBlock, isBlock } from "../traverse";
3
3
  import { Node } from "./gen";
4
4
  import { getIdentifierInfo, validateChain } from "./identifiers";
5
5
 
6
+ export function isClass(object: Node): boolean {
7
+ return (
8
+ object.type === "ClassDeclaration" || object.type === "ClassExpression"
9
+ );
10
+ }
11
+
6
12
  /**
7
13
  * - `FunctionDeclaration`
8
14
  * - `FunctionExpression`
@@ -18,6 +24,17 @@ export function isFunction(object: Node): boolean {
18
24
  ].includes(object && object.type);
19
25
  }
20
26
 
27
+ export function isStrictModeFunction(object: Node): boolean {
28
+ ok(isFunction(object));
29
+
30
+ return (
31
+ object.body.type === "BlockStatement" &&
32
+ object.body.body[0] &&
33
+ object.body.body[0].type === "ExpressionStatement" &&
34
+ object.body.body[0].directive === "use strict"
35
+ );
36
+ }
37
+
21
38
  /**
22
39
  * The function context where the object is.
23
40
  *
package/src/util/scope.ts CHANGED
@@ -1,9 +1,21 @@
1
+ import { ok } from "assert";
1
2
  import { isBlock } from "../traverse";
3
+ import { Node } from "./gen";
2
4
 
3
- export function isLexicalScope(object) {
5
+ export function isLexicalScope(object: Node) {
4
6
  return isBlock(object) || object.type == "SwitchCase";
5
7
  }
6
8
 
7
- export function getLexicalScope(object, parents) {
9
+ export function getLexicalScope(object: Node, parents: Node[]): Node {
8
10
  return [object, ...parents].find((node) => isLexicalScope(node));
9
11
  }
12
+
13
+ export function getLexicalScopeBody(object: Node): Node[] {
14
+ ok(isLexicalScope(object));
15
+
16
+ return isBlock(object)
17
+ ? object.body
18
+ : object.type === "SwitchCase"
19
+ ? object.consequent
20
+ : ok("Unhandled case");
21
+ }
@@ -32,12 +32,18 @@ test("Variant #1: Cash.js on High Preset (Strict Mode)", async () => {
32
32
  $: false,
33
33
  } as any;
34
34
  window.window = window;
35
+ global.window = window;
35
36
 
36
- // writeFileSync(join(__dirname, "Cash.output.js"), output, {
37
- // encoding: "utf-8",
38
- // });
37
+ try {
38
+ eval(output);
39
+ } catch (e) {
40
+ console.error(e);
41
+ writeFileSync("dev.output.js", output, {
42
+ encoding: "utf-8",
43
+ });
39
44
 
40
- eval(output);
45
+ expect(true).toStrictEqual(false);
46
+ }
41
47
 
42
48
  expect(window).toHaveProperty("cash");
43
49
  });
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+
3
+ function TestStrictMode() {
4
+ "use strict";
5
+
6
+ var isStrictMode = () => {
7
+ try {
8
+ undefined = true;
9
+ } catch (E) {
10
+ return true;
11
+ }
12
+ return false;
13
+ };
14
+
15
+ // filler code to make transformations more likely to affect this function
16
+ var x, y, z;
17
+ var string1 = "Hello World";
18
+ var string2 = "use strict";
19
+
20
+ var chars = string2.split("");
21
+ var count = 0;
22
+ for (var char of chars) {
23
+ count++;
24
+ }
25
+
26
+ expect(count).toStrictEqual(10);
27
+
28
+ // This function should be in strict mode
29
+ expect(isStrictMode()).toStrictEqual(true);
30
+ }
31
+
32
+ var isStrictMode = () => {
33
+ try {
34
+ undefined = true;
35
+ } catch (E) {
36
+ return true;
37
+ }
38
+ return false;
39
+ };
40
+
41
+ // Global level should be in strict mode
42
+ expect(isStrictMode()).toStrictEqual(true);
43
+ TestStrictMode();
44
+
45
+ // Direct vs. Indirect eval usage
46
+ var evalString = `
47
+ var isStrictMode = () => {
48
+ try {
49
+ undefined = true;
50
+ } catch (E) {
51
+ return true;
52
+ }
53
+ return false;
54
+ };
55
+
56
+ isStrictMode();`;
57
+
58
+ // Direct eval -> Preserve global strict-mode
59
+ var directEvalResult = eval(evalString);
60
+ expect(directEvalResult).toStrictEqual(true);
61
+
62
+ // Indirect eval -> Does not inherit context strict-mode
63
+ var _eval_ = eval;
64
+ var indirectEvalResult = _eval_(evalString);
65
+ expect(indirectEvalResult).toStrictEqual(false);
@@ -0,0 +1,37 @@
1
+ import { readFileSync, writeFileSync } from "fs";
2
+ import { join } from "path";
3
+ import JsConfuser from "../../src/index";
4
+
5
+ var StrictMode_JS = readFileSync(
6
+ join(__dirname, "./StrictMode.src.js"),
7
+ "utf-8"
8
+ );
9
+
10
+ test("Variant #1: StrictMode on High Preset", async () => {
11
+ var output = await JsConfuser(StrictMode_JS, {
12
+ target: "node",
13
+ preset: "high",
14
+ });
15
+
16
+ //writeFileSync("./dev.output.js", output);
17
+
18
+ eval(output);
19
+ });
20
+
21
+ test("Variant #2: StrictMode on 2x High Preset", async () => {
22
+ var output = await JsConfuser(StrictMode_JS, {
23
+ target: "node",
24
+ preset: "high",
25
+ });
26
+
27
+ //writeFileSync("./dev.output1.js", output);
28
+
29
+ var output2 = await JsConfuser(output, {
30
+ target: "node",
31
+ preset: "high",
32
+ });
33
+
34
+ //writeFileSync("./dev.output2.js", output2);
35
+
36
+ eval(output2);
37
+ });
@@ -1,3 +1,4 @@
1
+ import Template from "../src/templates/template";
1
2
  import { isIndependent } from "../src/util/compare";
2
3
  import {
3
4
  ArrayExpression,
@@ -17,9 +18,9 @@ describe("isIndependent", () => {
17
18
  ).toStrictEqual(false);
18
19
  });
19
20
 
20
- it("should return true for reserved identifiers (null, undefined, etc)", () => {
21
+ it("should return true for reserved identifiers (undefined, NaN, etc)", () => {
21
22
  expect(
22
- isIndependent(Identifier("null"), [{ type: "Program" }])
23
+ isIndependent(Identifier("undefined"), [{ type: "Program" }])
23
24
  ).toStrictEqual(true);
24
25
  });
25
26
 
@@ -41,4 +42,63 @@ describe("isIndependent", () => {
41
42
  it("should return false for everything else", () => {
42
43
  expect(isIndependent(FunctionExpression([], []), [])).toStrictEqual(false);
43
44
  });
45
+
46
+ it("various cases", () => {
47
+ expect(
48
+ isIndependent(
49
+ Template(`({
50
+ x: 1,
51
+ y: 2,
52
+ z: 3,
53
+ })`).single().expression,
54
+ []
55
+ )
56
+ ).toStrictEqual(true);
57
+
58
+ expect(
59
+ isIndependent(
60
+ Template(`({
61
+ x: 1,
62
+ y: 2,
63
+ z: [3,4,5,6,7,"My String",undefined,null,NaN],
64
+ })`).single().expression,
65
+ []
66
+ )
67
+ ).toStrictEqual(true);
68
+
69
+ expect(
70
+ isIndependent(
71
+ Template(`({
72
+ x: 1,
73
+ y: 2,
74
+ z: 3,
75
+ _: function(){return value}
76
+ })`).single().expression,
77
+ []
78
+ )
79
+ ).toStrictEqual(false);
80
+
81
+ expect(
82
+ isIndependent(
83
+ Template(`({
84
+ x: 1,
85
+ y: 2,
86
+ z: 3,
87
+ _: [value]
88
+ })`).single().expression,
89
+ []
90
+ )
91
+ ).toStrictEqual(false);
92
+
93
+ expect(
94
+ isIndependent(
95
+ Template(`([
96
+ {
97
+ x: value
98
+ }
99
+ ])`).single().expression,
100
+ []
101
+ )
102
+ ).toStrictEqual(false);
103
+ });
44
104
  });
@@ -1,76 +1,132 @@
1
1
  import JsConfuser from "../src/index";
2
2
 
3
- it("should accept percentages", async () => {
4
- var output = await JsConfuser(`var TEST_VARIABLE;`, {
5
- target: "node",
6
- renameGlobals: true,
7
- renameVariables: true,
8
- stringConcealing: 0.5,
3
+ describe("options", () => {
4
+ test("Variant #1: Accept percentages", async () => {
5
+ var output = await JsConfuser(`var TEST_VARIABLE;`, {
6
+ target: "node",
7
+ renameGlobals: true,
8
+ renameVariables: true,
9
+ stringConcealing: 0.5,
10
+ });
11
+
12
+ expect(output).not.toContain("TEST_VARIABLE");
9
13
  });
10
14
 
11
- expect(output).not.toContain("TEST_VARIABLE");
12
- });
15
+ test("Variant #2: Accept probability arrays", async () => {
16
+ var output = await JsConfuser(`var TEST_VARIABLE;`, {
17
+ target: "node",
18
+ renameVariables: true,
19
+ renameGlobals: true,
20
+ identifierGenerator: ["hexadecimal", "mangled"], // half hexadecimal, half randomized
21
+ });
13
22
 
14
- it("should accept probability arrays", async () => {
15
- var output = await JsConfuser(`var TEST_VARIABLE;`, {
16
- target: "node",
17
- renameVariables: true,
18
- renameGlobals: true,
19
- identifierGenerator: ["hexadecimal", "mangled"], // half hexadecimal, half randomized
23
+ expect(output).not.toContain("TEST_VARIABLE");
20
24
  });
21
25
 
22
- expect(output).not.toContain("TEST_VARIABLE");
23
- });
26
+ test("Variant #3: Accept probability maps", async () => {
27
+ var output = await JsConfuser(`var TEST_VARIABLE;`, {
28
+ target: "node",
29
+ renameVariables: true,
30
+ renameGlobals: true,
31
+ identifierGenerator: {
32
+ // 25% each
33
+ hexadecimal: 0.25,
34
+ randomized: 0.25,
35
+ mangled: 0.25,
36
+ number: 0.25,
37
+ },
38
+ });
24
39
 
25
- it("should accept probability maps", async () => {
26
- var output = await JsConfuser(`var TEST_VARIABLE;`, {
27
- target: "node",
28
- renameVariables: true,
29
- renameGlobals: true,
30
- identifierGenerator: {
31
- // 25% each
32
- hexadecimal: 0.25,
33
- randomized: 0.25,
34
- mangled: 0.25,
35
- number: 0.25,
36
- },
40
+ expect(output).not.toContain("TEST_VARIABLE");
37
41
  });
38
42
 
39
- expect(output).not.toContain("TEST_VARIABLE");
40
- });
43
+ test("Variant #4: Work with compact false", async () => {
44
+ var output = await JsConfuser(`var TEST_VARIABLE;`, {
45
+ target: "node",
46
+ renameGlobals: true,
47
+ renameVariables: true,
48
+ compact: false,
49
+ });
41
50
 
42
- it("should work with compact false", async () => {
43
- var output = await JsConfuser(`var TEST_VARIABLE;`, {
44
- target: "node",
45
- renameGlobals: true,
46
- renameVariables: true,
47
- compact: false,
51
+ expect(output).not.toContain("TEST_VARIABLE");
48
52
  });
49
53
 
50
- expect(output).not.toContain("TEST_VARIABLE");
51
- });
54
+ test("Variant #5: Work with indent set to 2 spaces", async () => {
55
+ var output = await JsConfuser(`var TEST_VARIABLE;`, {
56
+ target: "node",
57
+ renameGlobals: true,
58
+ renameVariables: true,
59
+ compact: false,
60
+ indent: 2,
61
+ });
52
62
 
53
- it("should work with indent set to 2 spaces", async () => {
54
- var output = await JsConfuser(`var TEST_VARIABLE;`, {
55
- target: "node",
56
- renameGlobals: true,
57
- renameVariables: true,
58
- compact: false,
59
- indent: 2,
63
+ expect(output).not.toContain("TEST_VARIABLE");
60
64
  });
61
65
 
62
- expect(output).not.toContain("TEST_VARIABLE");
66
+ test("Variant #6: Work with debugComments enabled", async () => {
67
+ var output = await JsConfuser(`var TEST_VARIABLE;`, {
68
+ target: "node",
69
+ renameGlobals: true,
70
+ renameVariables: true,
71
+ compact: false,
72
+ indent: 2,
73
+ debugComments: true,
74
+ });
75
+
76
+ expect(output).not.toContain("TEST_VARIABLE");
77
+ });
63
78
  });
64
79
 
65
- it("should work with debugComments enabled", async () => {
66
- var output = await JsConfuser(`var TEST_VARIABLE;`, {
67
- target: "node",
68
- renameGlobals: true,
69
- renameVariables: true,
70
- compact: false,
71
- indent: 2,
72
- debugComments: true,
80
+ describe("options.preserveFunctionLength", () => {
81
+ test("Variant #1: Enabled by default", async () => {
82
+ var output = await JsConfuser(
83
+ `
84
+ function myFunction(a, b, c, d = "") {
85
+ // Function.length = 3
86
+ }
87
+
88
+ TEST_OUTPUT = myFunction.length; // 3
89
+ `,
90
+ {
91
+ target: "node",
92
+ preset: "high",
93
+ }
94
+ );
95
+
96
+ var TEST_OUTPUT;
97
+ eval(output);
98
+ expect(TEST_OUTPUT).toStrictEqual(3);
73
99
  });
74
100
 
75
- expect(output).not.toContain("TEST_VARIABLE");
101
+ test("Variant #2: Disabled", async () => {
102
+ var output = await JsConfuser(
103
+ `
104
+ function myFunction(a, b, c, d = "") {
105
+ // Function.length = 3
106
+ }
107
+
108
+ TEST_OUTPUT = myFunction.length; // 3
109
+ `,
110
+ {
111
+ target: "node",
112
+ preset: "high",
113
+ preserveFunctionLength: false,
114
+
115
+ stringEncoding: false,
116
+ stringCompression: false,
117
+ stringConcealing: false,
118
+ stringSplitting: false,
119
+ deadCode: false,
120
+ duplicateLiteralsRemoval: false,
121
+
122
+ rgf: true,
123
+ }
124
+ );
125
+
126
+ expect(output).not.toContain("defineProperty");
127
+
128
+ var TEST_OUTPUT;
129
+ eval(output);
130
+ expect(TEST_OUTPUT).not.toStrictEqual(3);
131
+ });
76
132
  });