js-confuser 1.7.1 → 1.7.3

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 (153) hide show
  1. package/.github/workflows/node.js.yml +1 -1
  2. package/CHANGELOG.md +73 -0
  3. package/README.md +32 -31
  4. package/dist/compiler.js +2 -8
  5. package/dist/constants.js +22 -10
  6. package/dist/index.js +15 -30
  7. package/dist/obfuscator.js +15 -62
  8. package/dist/options.js +33 -40
  9. package/dist/order.js +4 -7
  10. package/dist/parser.js +5 -13
  11. package/dist/precedence.js +6 -8
  12. package/dist/presets.js +4 -6
  13. package/dist/probability.js +13 -24
  14. package/dist/templates/bufferToString.js +121 -5
  15. package/dist/templates/core.js +35 -0
  16. package/dist/templates/crash.js +22 -11
  17. package/dist/templates/es5.js +125 -6
  18. package/dist/templates/functionLength.js +24 -6
  19. package/dist/templates/globals.js +9 -0
  20. package/dist/templates/template.js +189 -43
  21. package/dist/transforms/antiTooling.js +26 -22
  22. package/dist/transforms/calculator.js +19 -55
  23. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +242 -333
  24. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +46 -25
  25. package/dist/transforms/deadCode.js +542 -31
  26. package/dist/transforms/dispatcher.js +112 -112
  27. package/dist/transforms/es5/antiClass.js +70 -44
  28. package/dist/transforms/es5/antiDestructuring.js +14 -38
  29. package/dist/transforms/es5/antiES6Object.js +39 -48
  30. package/dist/transforms/es5/antiSpreadOperator.js +5 -14
  31. package/dist/transforms/es5/antiTemplate.js +10 -19
  32. package/dist/transforms/es5/es5.js +7 -40
  33. package/dist/transforms/extraction/classExtraction.js +83 -0
  34. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +41 -80
  35. package/dist/transforms/extraction/objectExtraction.js +24 -56
  36. package/dist/transforms/finalizer.js +6 -20
  37. package/dist/transforms/flatten.js +51 -99
  38. package/dist/transforms/identifier/globalAnalysis.js +21 -26
  39. package/dist/transforms/identifier/globalConcealing.js +72 -56
  40. package/dist/transforms/identifier/movedDeclarations.js +66 -38
  41. package/dist/transforms/identifier/renameVariables.js +36 -68
  42. package/dist/transforms/identifier/variableAnalysis.js +21 -48
  43. package/dist/transforms/lock/antiDebug.js +20 -25
  44. package/dist/transforms/lock/integrity.js +53 -52
  45. package/dist/transforms/lock/lock.js +161 -126
  46. package/dist/transforms/minify.js +77 -108
  47. package/dist/transforms/opaquePredicates.js +12 -49
  48. package/dist/transforms/preparation.js +28 -49
  49. package/dist/transforms/renameLabels.js +5 -22
  50. package/dist/transforms/rgf.js +125 -72
  51. package/dist/transforms/shuffle.js +42 -47
  52. package/dist/transforms/stack.js +41 -98
  53. package/dist/transforms/string/encoding.js +76 -27
  54. package/dist/transforms/string/stringCompression.js +75 -68
  55. package/dist/transforms/string/stringConcealing.js +127 -135
  56. package/dist/transforms/string/stringEncoding.js +6 -26
  57. package/dist/transforms/string/stringSplitting.js +5 -30
  58. package/dist/transforms/transform.js +76 -104
  59. package/dist/traverse.js +11 -18
  60. package/dist/util/compare.js +27 -29
  61. package/dist/util/gen.js +32 -86
  62. package/dist/util/guard.js +5 -1
  63. package/dist/util/identifiers.js +9 -72
  64. package/dist/util/insert.js +27 -77
  65. package/dist/util/math.js +0 -3
  66. package/dist/util/object.js +3 -7
  67. package/dist/util/random.js +31 -36
  68. package/dist/util/scope.js +6 -3
  69. package/docs/Countermeasures.md +13 -6
  70. package/docs/Integrity.md +35 -28
  71. package/docs/RGF.md +6 -1
  72. package/docs/RenameVariables.md +116 -0
  73. package/docs/TamperProtection.md +100 -0
  74. package/docs/Template.md +117 -0
  75. package/package.json +3 -3
  76. package/src/constants.ts +17 -0
  77. package/src/index.ts +7 -5
  78. package/src/options.ts +60 -7
  79. package/src/order.ts +2 -2
  80. package/src/templates/bufferToString.ts +79 -11
  81. package/src/templates/core.ts +29 -0
  82. package/src/templates/crash.ts +6 -38
  83. package/src/templates/es5.ts +1 -1
  84. package/src/templates/functionLength.ts +21 -3
  85. package/src/templates/globals.ts +3 -0
  86. package/src/templates/template.ts +205 -46
  87. package/src/transforms/antiTooling.ts +33 -11
  88. package/src/transforms/calculator.ts +4 -2
  89. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +12 -5
  90. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +46 -10
  91. package/src/transforms/deadCode.ts +74 -42
  92. package/src/transforms/dispatcher.ts +99 -73
  93. package/src/transforms/es5/antiClass.ts +25 -12
  94. package/src/transforms/es5/antiDestructuring.ts +1 -1
  95. package/src/transforms/es5/antiES6Object.ts +2 -2
  96. package/src/transforms/es5/antiTemplate.ts +1 -1
  97. package/src/transforms/extraction/classExtraction.ts +168 -0
  98. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +11 -16
  99. package/src/transforms/extraction/objectExtraction.ts +4 -15
  100. package/src/transforms/flatten.ts +20 -5
  101. package/src/transforms/identifier/globalAnalysis.ts +18 -1
  102. package/src/transforms/identifier/globalConcealing.ts +119 -72
  103. package/src/transforms/identifier/movedDeclarations.ts +90 -24
  104. package/src/transforms/identifier/renameVariables.ts +16 -1
  105. package/src/transforms/lock/antiDebug.ts +2 -2
  106. package/src/transforms/lock/integrity.ts +13 -11
  107. package/src/transforms/lock/lock.ts +122 -30
  108. package/src/transforms/minify.ts +28 -13
  109. package/src/transforms/opaquePredicates.ts +2 -2
  110. package/src/transforms/preparation.ts +16 -0
  111. package/src/transforms/rgf.ts +139 -12
  112. package/src/transforms/shuffle.ts +3 -3
  113. package/src/transforms/stack.ts +19 -4
  114. package/src/transforms/string/encoding.ts +88 -51
  115. package/src/transforms/string/stringCompression.ts +86 -17
  116. package/src/transforms/string/stringConcealing.ts +148 -118
  117. package/src/transforms/string/stringEncoding.ts +1 -2
  118. package/src/transforms/string/stringSplitting.ts +1 -2
  119. package/src/transforms/transform.ts +63 -46
  120. package/src/types.ts +2 -0
  121. package/src/util/compare.ts +39 -5
  122. package/src/util/gen.ts +10 -3
  123. package/src/util/guard.ts +10 -0
  124. package/src/util/insert.ts +17 -0
  125. package/src/util/random.ts +81 -1
  126. package/src/util/scope.ts +14 -2
  127. package/test/code/Cash.test.ts +94 -5
  128. package/test/code/StrictMode.src.js +65 -0
  129. package/test/code/StrictMode.test.js +37 -0
  130. package/test/compare.test.ts +62 -2
  131. package/test/options.test.ts +129 -55
  132. package/test/templates/template.test.ts +211 -1
  133. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +37 -18
  134. package/test/transforms/dispatcher.test.ts +55 -0
  135. package/test/transforms/extraction/classExtraction.test.ts +86 -0
  136. package/test/transforms/extraction/duplicateLiteralsRemoval.test.ts +8 -0
  137. package/test/transforms/extraction/objectExtraction.test.ts +2 -0
  138. package/test/transforms/identifier/globalConcealing.test.ts +89 -0
  139. package/test/transforms/identifier/movedDeclarations.test.ts +61 -0
  140. package/test/transforms/identifier/renameVariables.test.ts +75 -1
  141. package/test/transforms/lock/tamperProtection.test.ts +336 -0
  142. package/test/transforms/minify.test.ts +37 -0
  143. package/test/transforms/rgf.test.ts +50 -0
  144. package/dist/transforms/controlFlowFlattening/choiceFlowObfuscation.js +0 -62
  145. package/dist/transforms/controlFlowFlattening/controlFlowObfuscation.js +0 -159
  146. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +0 -106
  147. package/dist/transforms/eval.js +0 -84
  148. package/dist/transforms/hexadecimalNumbers.js +0 -63
  149. package/dist/transforms/hideInitializingCode.js +0 -270
  150. package/dist/transforms/identifier/nameRecycling.js +0 -218
  151. package/dist/transforms/label.js +0 -67
  152. package/dist/transforms/preparation/nameConflicts.js +0 -116
  153. package/dist/transforms/preparation/preparation.js +0 -188
@@ -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
  *
@@ -63,7 +63,7 @@ export function splitIntoChunks(str: string, size: number) {
63
63
  ok(Math.floor(size) === size, "size must be integer");
64
64
 
65
65
  const numChunks = Math.ceil(str.length / size);
66
- const chunks = new Array(numChunks);
66
+ const chunks: string[] = new Array(numChunks);
67
67
 
68
68
  for (let i = 0, o = 0; i < numChunks; ++i, o += size) {
69
69
  chunks[i] = str.substr(o, size);
@@ -139,3 +139,83 @@ export function alphabeticalGenerator(index: number) {
139
139
  }
140
140
  return name;
141
141
  }
142
+
143
+ export function createZeroWidthGenerator() {
144
+ var keywords = [
145
+ "if",
146
+ "in",
147
+ "for",
148
+ "let",
149
+ "new",
150
+ "try",
151
+ "var",
152
+ "case",
153
+ "else",
154
+ "null",
155
+ "break",
156
+ "catch",
157
+ "class",
158
+ "const",
159
+ "super",
160
+ "throw",
161
+ "while",
162
+ "yield",
163
+ "delete",
164
+ "export",
165
+ "import",
166
+ "public",
167
+ "return",
168
+ "switch",
169
+ "default",
170
+ "finally",
171
+ "private",
172
+ "continue",
173
+ "debugger",
174
+ "function",
175
+ "arguments",
176
+ "protected",
177
+ "instanceof",
178
+ "await",
179
+ "async",
180
+
181
+ // new key words and other fun stuff :P
182
+ "NaN",
183
+ "undefined",
184
+ "true",
185
+ "false",
186
+ "typeof",
187
+ "this",
188
+ "static",
189
+ "void",
190
+ "of",
191
+ ];
192
+
193
+ var maxSize = 0;
194
+ var currentKeyWordsArray: string[] = [];
195
+
196
+ function generateArray() {
197
+ var result = keywords
198
+ .map(
199
+ (keyWord) =>
200
+ keyWord + "\u200C".repeat(Math.max(maxSize - keyWord.length, 1))
201
+ )
202
+ .filter((craftedVariableName) => craftedVariableName.length == maxSize);
203
+
204
+ if (!result.length) {
205
+ ++maxSize;
206
+ return generateArray();
207
+ }
208
+
209
+ return shuffle(result);
210
+ }
211
+
212
+ function getNextVariable(): string {
213
+ if (!currentKeyWordsArray.length) {
214
+ ++maxSize;
215
+ currentKeyWordsArray = generateArray();
216
+ }
217
+ return currentKeyWordsArray.pop();
218
+ }
219
+
220
+ return { generate: getNextVariable };
221
+ }
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
+ }
@@ -6,7 +6,7 @@ var CASH_JS = readFileSync(join(__dirname, "./Cash.src.js"), "utf-8");
6
6
 
7
7
  test("Variant #1: Cash.js on High Preset (Strict Mode)", async () => {
8
8
  var output = await JsConfuser(CASH_JS, {
9
- target: "browser",
9
+ target: "node",
10
10
  preset: "high",
11
11
  });
12
12
 
@@ -32,12 +32,101 @@ 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;
36
+ for (var key in window) {
37
+ global[key] = window[key];
38
+ }
35
39
 
36
- // writeFileSync(join(__dirname, "Cash.output.js"), output, {
37
- // encoding: "utf-8",
38
- // });
40
+ try {
41
+ eval(output);
42
+ } catch (e) {
43
+ console.error(e);
44
+ writeFileSync("dev.output.js", output, {
45
+ encoding: "utf-8",
46
+ });
39
47
 
40
- eval(output);
48
+ expect(true).toStrictEqual(false);
49
+ }
50
+
51
+ expect(window).toHaveProperty("cash");
52
+ });
53
+
54
+ test("Variant #2: Cash.js on High Preset + Integrity + Self Defending + RGF + Tamper Protection", async () => {
55
+ // Make the required document variables for initialization
56
+ var document = {
57
+ documentElement: {},
58
+ createElement: () => {
59
+ return { style: {} };
60
+ },
61
+ } as any as Document;
62
+ var window = {
63
+ document,
64
+ Array,
65
+ Object,
66
+ Symbol,
67
+ Number,
68
+ parseInt,
69
+ JSON,
70
+ setTimeout,
71
+ encodeURIComponent,
72
+ RegExp,
73
+ String,
74
+ $: false,
75
+ } as any;
76
+ window.window = window;
77
+ global.window = window;
78
+ for (var key in window) {
79
+ global[key] = window[key];
80
+ }
81
+
82
+ var output = await JsConfuser(CASH_JS, {
83
+ target: "node",
84
+ preset: "high",
85
+ rgf: true,
86
+ lock: {
87
+ integrity: true,
88
+ selfDefending: true,
89
+ tamperProtection: true,
90
+ },
91
+ });
92
+
93
+ try {
94
+ // new Function() runs in non-strict mode
95
+ new Function(output)();
96
+ } catch (e) {
97
+ var helperCode = `var document = {
98
+ documentElement: {},
99
+ createElement: () => {
100
+ return { style: {} };
101
+ },
102
+ };
103
+ var window = {
104
+ document,
105
+ Array,
106
+ Object,
107
+ Symbol,
108
+ Number,
109
+ parseInt,
110
+ JSON,
111
+ setTimeout,
112
+ encodeURIComponent,
113
+ RegExp,
114
+ String,
115
+ $: false,
116
+ };
117
+ window.window = window;
118
+ global.window = window;
119
+ for (var key in window) {
120
+ global[key] = window[key];
121
+ }`;
122
+
123
+ console.error(e);
124
+ writeFileSync("dev.output.js", helperCode + "\n" + output, {
125
+ encoding: "utf-8",
126
+ });
127
+
128
+ expect(true).toStrictEqual(false);
129
+ }
41
130
 
42
131
  expect(window).toHaveProperty("cash");
43
132
  });
@@ -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
+ new Template(`({
50
+ x: 1,
51
+ y: 2,
52
+ z: 3,
53
+ })`).single().expression,
54
+ []
55
+ )
56
+ ).toStrictEqual(true);
57
+
58
+ expect(
59
+ isIndependent(
60
+ new 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
+ new 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
+ new 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
+ new Template(`([
96
+ {
97
+ x: value
98
+ }
99
+ ])`).single().expression,
100
+ []
101
+ )
102
+ ).toStrictEqual(false);
103
+ });
44
104
  });
@@ -1,76 +1,150 @@
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
+ });
78
+
79
+ test("Variant #7: Error on invalid lock option", async () => {
80
+ expect(
81
+ JsConfuser(`var TEST_VARIABLE;`, {
82
+ target: "node",
83
+ lock: "invalid",
84
+ } as any)
85
+ ).rejects.toThrow();
86
+
87
+ expect(
88
+ JsConfuser(`var TEST_VARIABLE;`, {
89
+ target: "node",
90
+ lock: {
91
+ invalidProperty: true,
92
+ },
93
+ } as any)
94
+ ).rejects.toThrow();
95
+ });
63
96
  });
64
97
 
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,
98
+ describe("options.preserveFunctionLength", () => {
99
+ test("Variant #1: Enabled by default", async () => {
100
+ var output = await JsConfuser(
101
+ `
102
+ function myFunction(a, b, c, d = "") {
103
+ // Function.length = 3
104
+ }
105
+
106
+ TEST_OUTPUT = myFunction.length; // 3
107
+ `,
108
+ {
109
+ target: "node",
110
+ preset: "high",
111
+ }
112
+ );
113
+
114
+ var TEST_OUTPUT;
115
+ eval(output);
116
+ expect(TEST_OUTPUT).toStrictEqual(3);
73
117
  });
74
118
 
75
- expect(output).not.toContain("TEST_VARIABLE");
119
+ test("Variant #2: Disabled", async () => {
120
+ var output = await JsConfuser(
121
+ `
122
+ function myFunction(a, b, c, d = "") {
123
+ // Function.length = 3
124
+ }
125
+
126
+ TEST_OUTPUT = myFunction.length; // 3
127
+ `,
128
+ {
129
+ target: "node",
130
+ preset: "high",
131
+ preserveFunctionLength: false,
132
+
133
+ stringEncoding: false,
134
+ stringCompression: false,
135
+ stringConcealing: false,
136
+ stringSplitting: false,
137
+ deadCode: false,
138
+ duplicateLiteralsRemoval: false,
139
+
140
+ rgf: true,
141
+ }
142
+ );
143
+
144
+ expect(output).not.toContain("defineProperty");
145
+
146
+ var TEST_OUTPUT;
147
+ eval(output);
148
+ expect(TEST_OUTPUT).not.toStrictEqual(3);
149
+ });
76
150
  });