js-confuser 1.5.9 → 1.7.0

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 (143) hide show
  1. package/.github/workflows/node.js.yml +2 -2
  2. package/CHANGELOG.md +55 -0
  3. package/README.md +346 -165
  4. package/dist/constants.js +6 -2
  5. package/dist/index.js +9 -21
  6. package/dist/obfuscator.js +19 -31
  7. package/dist/options.js +5 -5
  8. package/dist/order.js +1 -3
  9. package/dist/presets.js +6 -7
  10. package/dist/probability.js +2 -4
  11. package/dist/templates/bufferToString.js +13 -0
  12. package/dist/templates/crash.js +3 -3
  13. package/dist/templates/es5.js +18 -0
  14. package/dist/templates/functionLength.js +16 -0
  15. package/dist/transforms/calculator.js +77 -21
  16. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
  17. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -1
  18. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
  19. package/dist/transforms/deadCode.js +33 -25
  20. package/dist/transforms/dispatcher.js +8 -4
  21. package/dist/transforms/es5/antiDestructuring.js +2 -0
  22. package/dist/transforms/es5/es5.js +31 -34
  23. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +92 -58
  24. package/dist/transforms/finalizer.js +82 -0
  25. package/dist/transforms/flatten.js +229 -148
  26. package/dist/transforms/identifier/globalAnalysis.js +88 -0
  27. package/dist/transforms/identifier/globalConcealing.js +10 -83
  28. package/dist/transforms/identifier/movedDeclarations.js +35 -88
  29. package/dist/transforms/identifier/renameVariables.js +124 -59
  30. package/dist/transforms/identifier/variableAnalysis.js +58 -62
  31. package/dist/transforms/lock/lock.js +0 -37
  32. package/dist/transforms/minify.js +60 -57
  33. package/dist/transforms/opaquePredicates.js +1 -1
  34. package/dist/transforms/preparation/preparation.js +2 -2
  35. package/dist/transforms/preparation.js +231 -0
  36. package/dist/transforms/renameLabels.js +1 -1
  37. package/dist/transforms/rgf.js +139 -247
  38. package/dist/transforms/stack.js +128 -26
  39. package/dist/transforms/string/encoding.js +150 -179
  40. package/dist/transforms/string/stringCompression.js +14 -15
  41. package/dist/transforms/string/stringConcealing.js +25 -8
  42. package/dist/transforms/string/stringEncoding.js +13 -24
  43. package/dist/transforms/transform.js +12 -19
  44. package/dist/traverse.js +24 -10
  45. package/dist/util/gen.js +17 -1
  46. package/dist/util/identifiers.js +37 -3
  47. package/dist/util/insert.js +35 -4
  48. package/dist/util/random.js +15 -0
  49. package/docs/ControlFlowFlattening.md +595 -0
  50. package/{Countermeasures.md → docs/Countermeasures.md} +1 -15
  51. package/{Integrity.md → docs/Integrity.md} +2 -2
  52. package/docs/RGF.md +419 -0
  53. package/package.json +5 -5
  54. package/src/constants.ts +3 -0
  55. package/src/index.ts +2 -2
  56. package/src/obfuscator.ts +19 -31
  57. package/src/options.ts +14 -103
  58. package/src/order.ts +1 -5
  59. package/src/presets.ts +6 -7
  60. package/src/probability.ts +2 -3
  61. package/src/templates/bufferToString.ts +68 -0
  62. package/src/templates/crash.ts +15 -19
  63. package/src/templates/es5.ts +131 -0
  64. package/src/templates/functionLength.ts +14 -0
  65. package/src/transforms/calculator.ts +122 -59
  66. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
  67. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +4 -1
  68. package/src/transforms/deadCode.ts +383 -26
  69. package/src/transforms/dispatcher.ts +9 -4
  70. package/src/transforms/es5/antiDestructuring.ts +2 -0
  71. package/src/transforms/es5/es5.ts +32 -77
  72. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +133 -129
  73. package/src/transforms/{hexadecimalNumbers.ts → finalizer.ts} +29 -13
  74. package/src/transforms/flatten.ts +357 -300
  75. package/src/transforms/identifier/globalAnalysis.ts +85 -0
  76. package/src/transforms/identifier/globalConcealing.ts +14 -103
  77. package/src/transforms/identifier/movedDeclarations.ts +49 -102
  78. package/src/transforms/identifier/renameVariables.ts +149 -78
  79. package/src/transforms/identifier/variableAnalysis.ts +66 -73
  80. package/src/transforms/lock/lock.ts +1 -42
  81. package/src/transforms/minify.ts +91 -75
  82. package/src/transforms/opaquePredicates.ts +2 -2
  83. package/src/transforms/preparation.ts +238 -0
  84. package/src/transforms/renameLabels.ts +2 -2
  85. package/src/transforms/rgf.ts +213 -405
  86. package/src/transforms/stack.ts +156 -36
  87. package/src/transforms/string/encoding.ts +115 -212
  88. package/src/transforms/string/stringCompression.ts +27 -18
  89. package/src/transforms/string/stringConcealing.ts +39 -9
  90. package/src/transforms/string/stringEncoding.ts +18 -18
  91. package/src/transforms/transform.ts +21 -23
  92. package/src/traverse.ts +23 -4
  93. package/src/types.ts +2 -1
  94. package/src/util/gen.ts +28 -3
  95. package/src/util/identifiers.ts +43 -2
  96. package/src/util/insert.ts +38 -3
  97. package/src/util/random.ts +13 -0
  98. package/test/code/Cash.test.ts +1 -1
  99. package/test/code/Dynamic.test.ts +12 -10
  100. package/test/code/ES6.src.js +146 -0
  101. package/test/code/ES6.test.ts +28 -2
  102. package/test/index.test.ts +2 -1
  103. package/test/probability.test.ts +44 -0
  104. package/test/templates/template.test.ts +1 -1
  105. package/test/transforms/antiTooling.test.ts +22 -0
  106. package/test/transforms/calculator.test.ts +40 -0
  107. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +702 -160
  108. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
  109. package/test/transforms/deadCode.test.ts +66 -15
  110. package/test/transforms/dispatcher.test.ts +20 -1
  111. package/test/transforms/es5/antiDestructuring.test.ts +16 -0
  112. package/test/transforms/flatten.test.ts +399 -86
  113. package/test/transforms/identifier/movedDeclarations.test.ts +63 -8
  114. package/test/transforms/identifier/renameVariables.test.ts +119 -0
  115. package/test/transforms/lock/antiDebug.test.ts +2 -2
  116. package/test/transforms/lock/lock.test.ts +1 -48
  117. package/test/transforms/minify.test.ts +104 -0
  118. package/test/transforms/preparation.test.ts +157 -0
  119. package/test/transforms/rgf.test.ts +261 -381
  120. package/test/transforms/stack.test.ts +143 -21
  121. package/test/transforms/string/stringCompression.test.ts +39 -0
  122. package/test/transforms/string/stringConcealing.test.ts +82 -0
  123. package/test/transforms/string/stringEncoding.test.ts +53 -2
  124. package/test/transforms/transform.test.ts +66 -0
  125. package/test/traverse.test.ts +139 -0
  126. package/test/util/identifiers.test.ts +113 -1
  127. package/test/util/insert.test.ts +57 -3
  128. package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
  129. package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
  130. package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
  131. package/src/transforms/eval.ts +0 -89
  132. package/src/transforms/hideInitializingCode.ts +0 -432
  133. package/src/transforms/identifier/nameRecycling.ts +0 -280
  134. package/src/transforms/label.ts +0 -64
  135. package/src/transforms/preparation/nameConflicts.ts +0 -102
  136. package/src/transforms/preparation/preparation.ts +0 -176
  137. package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
  138. package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
  139. package/test/transforms/eval.test.ts +0 -131
  140. package/test/transforms/hideInitializingCode.test.ts +0 -336
  141. package/test/transforms/identifier/nameRecycling.test.ts +0 -205
  142. package/test/transforms/preparation/nameConflicts.test.ts +0 -52
  143. package/test/transforms/preparation/preparation.test.ts +0 -62
@@ -15,92 +15,30 @@ var _gen = require("../../util/gen");
15
15
 
16
16
  var _insert = require("../../util/insert");
17
17
 
18
- var _identifiers = require("../../util/identifiers");
19
-
20
18
  var _random = require("../../util/random");
21
19
 
22
20
  var _constants = require("../../constants");
23
21
 
24
22
  var _probability = require("../../probability");
25
23
 
24
+ var _globalAnalysis = _interopRequireDefault(require("./globalAnalysis"));
25
+
26
26
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
27
27
 
28
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; }
29
29
 
30
- class GlobalAnalysis extends _transform.default {
31
- constructor(o) {
32
- super(o);
33
-
34
- _defineProperty(this, "notGlobals", void 0);
35
-
36
- _defineProperty(this, "globals", void 0);
37
-
38
- this.globals = Object.create(null);
39
- this.notGlobals = new Set();
40
- }
41
-
42
- match(object, parents) {
43
- return object.type == "Identifier" && !_constants.reservedKeywords.has(object.name);
44
- }
45
-
46
- transform(object, parents) {
47
- // no touching `import()` or `import x from ...`
48
- var importIndex = parents.findIndex(x => x.type == "ImportExpression" || x.type == "ImportDeclaration");
49
-
50
- if (importIndex !== -1) {
51
- if (parents[importIndex].source === (parents[importIndex - 1] || object)) {
52
- return;
53
- }
54
- }
55
-
56
- var info = (0, _identifiers.getIdentifierInfo)(object, parents);
57
-
58
- if (!info.spec.isReferenced) {
59
- return;
60
- } // Add to globals
61
-
62
-
63
- if (!this.notGlobals.has(object.name)) {
64
- if (!this.globals[object.name]) {
65
- this.globals[object.name] = [];
66
- }
67
-
68
- this.globals[object.name].push([object, parents]);
69
- }
70
-
71
- if (info.spec.isDefined || info.spec.isModified) {
72
- delete this.globals[object.name];
73
- this.notGlobals.add(object.name);
74
- }
75
-
76
- var assignmentIndex = parents.findIndex(x => x.type == "AssignmentExpression");
77
- var updateIndex = parents.findIndex(x => x.type == "UpdateExpression");
78
-
79
- if (assignmentIndex != -1 && parents[assignmentIndex].left === (parents[assignmentIndex - 1] || object) || updateIndex != -1) {
80
- var memberIndex = parents.findIndex(x => x.type == "MemberExpression");
81
-
82
- if (memberIndex == -1 || memberIndex > (assignmentIndex == -1 ? assignmentIndex : updateIndex)) {
83
- delete this.globals[object.name];
84
- this.notGlobals.add(object.name);
85
- }
86
- }
87
- }
88
-
89
- }
90
30
  /**
91
31
  * Global Concealing hides global variables being accessed.
92
32
  *
93
33
  * - Any variable that is not defined is considered "global"
94
34
  */
95
-
96
-
97
35
  class GlobalConcealing extends _transform.default {
98
36
  constructor(o) {
99
37
  super(o, _order.ObfuscateOrder.GlobalConcealing);
100
38
 
101
39
  _defineProperty(this, "globalAnalysis", void 0);
102
40
 
103
- this.globalAnalysis = new GlobalAnalysis(o);
41
+ this.globalAnalysis = new _globalAnalysis.default(o);
104
42
  this.before.push(this.globalAnalysis);
105
43
  }
106
44
 
@@ -126,10 +64,10 @@ class GlobalConcealing extends _transform.default {
126
64
  } else if (!(0, _probability.ComputeProbabilityMap)(this.options.globalConcealing, x => x, x)) {
127
65
  delete globals[x];
128
66
  }
129
- }); // this.log(Object.keys(globals).join(', '))
67
+ });
130
68
 
131
69
  if (Object.keys(globals).length > 0) {
132
- var used = new Set(); // 1. Make getter function
70
+ var used = new Set(); // Make getter function
133
71
  // holds "window" or "global"
134
72
 
135
73
  var globalVar = this.getPlaceholder(); // holds outermost "this"
@@ -137,10 +75,11 @@ class GlobalConcealing extends _transform.default {
137
75
  var thisVar = this.getPlaceholder(); // "window" or "global" in node
138
76
 
139
77
  var global = this.options.globalVariables.values().next().value || "window";
78
+ var alternateGlobal = global === "window" ? "global" : "window";
140
79
  var getGlobalVariableFnName = this.getPlaceholder();
141
80
  var getThisVariableFnName = this.getPlaceholder(); // Returns global variable or fall backs to `this`
142
81
 
143
- var getGlobalVariableFn = (0, _template.default)("\n var ".concat(getGlobalVariableFnName, " = function(){\n try {\n return ").concat(global, ";\n } catch (e){\n return ").concat(getThisVariableFnName, "[\"call\"](this);\n }\n }")).single();
82
+ var getGlobalVariableFn = (0, _template.default)("\n var ".concat(getGlobalVariableFnName, " = function(){\n try {\n return ").concat(global, " || ").concat(alternateGlobal, " || (new Function(\"return this\"))();\n } catch (e){\n return ").concat(getThisVariableFnName, "[\"call\"](this);\n }\n }")).single();
144
83
  var getThisVariableFn = (0, _template.default)("\n var ".concat(getThisVariableFnName, " = function(){\n try {\n return this;\n } catch (e){\n return null;\n }\n }")).single(); // 2. Replace old accessors
145
84
 
146
85
  var globalFn = this.getPlaceholder();
@@ -157,19 +96,7 @@ class GlobalConcealing extends _transform.default {
157
96
  newNames[name] = state;
158
97
  locations.forEach(_ref => {
159
98
  let [node, parents] = _ref;
160
-
161
- if (!parents.find(x => x.$dispatcherSkip)) {
162
- // Do not replace
163
- if (parents[0]) {
164
- if (parents[0].type == "ClassDeclaration" || parents[0].type == "ClassExpression" || parents[0].type == "FunctionExpression" || parents[0].type == "FunctionDeclaration") {
165
- if (parents[0].id === node) {
166
- return;
167
- }
168
- }
169
- }
170
-
171
- this.replace(node, (0, _gen.CallExpression)((0, _gen.Identifier)(globalFn), [(0, _gen.Literal)(state)]));
172
- }
99
+ this.replace(node, (0, _gen.CallExpression)((0, _gen.Identifier)(globalFn), [(0, _gen.Literal)(state)]));
173
100
  });
174
101
  }); // Adds all global variables to the switch statement
175
102
 
@@ -178,7 +105,7 @@ class GlobalConcealing extends _transform.default {
178
105
  var state;
179
106
 
180
107
  do {
181
- state = (0, _random.getRandomInteger)(-1000, 1000 + used.size + this.options.globalVariables.size * 100);
108
+ state = (0, _random.getRandomInteger)(0, 1000 + used.size + this.options.globalVariables.size * 100);
182
109
  } while (used.has(state));
183
110
 
184
111
  used.add(state);
@@ -191,7 +118,7 @@ class GlobalConcealing extends _transform.default {
191
118
  var code = newNames[name];
192
119
  var body = [(0, _gen.ReturnStatement)((0, _gen.LogicalExpression)("||", (0, _gen.MemberExpression)((0, _gen.Identifier)(globalVar), (0, _gen.Literal)(name), true), (0, _gen.MemberExpression)((0, _gen.Identifier)(thisVar), (0, _gen.Literal)(name), true)))];
193
120
 
194
- if (Math.random() > 0.5 && name) {
121
+ if ((0, _random.chance)(50)) {
195
122
  body = [(0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(returnName), (0, _gen.LogicalExpression)("||", (0, _gen.Literal)(name), (0, _gen.MemberExpression)((0, _gen.Identifier)(thisVar), (0, _gen.Literal)(name), true)))), (0, _gen.BreakStatement)()];
196
123
  }
197
124
 
@@ -17,10 +17,6 @@ var _assert = require("assert");
17
17
 
18
18
  var _order = require("../../order");
19
19
 
20
- var _identifiers = require("../../util/identifiers");
21
-
22
- var _scope = require("../../util/scope");
23
-
24
20
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
21
 
26
22
  /**
@@ -32,100 +28,51 @@ class MovedDeclarations extends _transform.default {
32
28
  }
33
29
 
34
30
  match(object, parents) {
35
- return (0, _scope.isLexicalScope)(object);
31
+ return object.type === "VariableDeclaration" && object.kind === "var" && object.declarations.length === 1 && object.declarations[0].id.type === "Identifier";
36
32
  }
37
33
 
38
34
  transform(object, parents) {
39
35
  return () => {
40
- var body = (0, _traverse.isBlock)(object) ? object.body : object.consequent;
41
- (0, _assert.ok)(Array.isArray(body));
42
- var illegal = new Set();
43
- var defined = new Set();
44
- var variableDeclarations = Object.create(null);
45
- (0, _traverse.walk)(object, parents, (o, p) => {
46
- if (o.type == "Identifier") {
47
- if (o.hidden || (0, _scope.getLexicalScope)(o, p) !== object) {
48
- illegal.add(o.name);
49
- } else {
50
- var info = (0, _identifiers.getIdentifierInfo)(o, p);
51
-
52
- if (!info.spec.isReferenced) {
53
- return;
54
- }
55
-
56
- if (info.spec.isDefined) {
57
- if (info.isFunctionDeclaration || info.isClassDeclaration) {
58
- illegal.add(o.name);
59
- } else {
60
- if (defined.has(o.name)) {
61
- illegal.add(o.name);
62
- } else {
63
- defined.add(o.name);
64
- }
65
- }
66
- }
67
- }
68
- }
36
+ var forInitializeType = (0, _insert.isForInitialize)(object, parents); // Get the block statement or Program node
69
37
 
70
- if (o.type == "VariableDeclaration") {
71
- return () => {
72
- if (o.declarations.length === 1 && o.declarations[0].id.type === "Identifier") {
73
- var name = o.declarations[0].id.name; // Check if duplicate
74
-
75
- if (variableDeclarations[name] || o.kind !== "var") {
76
- illegal.add(name);
77
- return;
78
- } // Check if already at top
79
-
80
-
81
- if (body[0] === o) {
82
- illegal.add(name);
83
- return;
84
- }
85
-
86
- var replace = (0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(name), o.declarations[0].init || (0, _gen.Identifier)("undefined"));
87
- var forType = (0, _insert.isForInitialize)(o, p);
88
-
89
- if (forType === "left-hand") {
90
- replace = (0, _gen.Identifier)(name);
91
- } else if (!forType) {
92
- replace = (0, _gen.ExpressionStatement)(replace);
93
- }
94
-
95
- variableDeclarations[name] = {
96
- location: [o, p],
97
- replace: replace
98
- };
99
- }
100
- };
101
- }
102
- });
103
- illegal.forEach(name => {
104
- delete variableDeclarations[name];
105
- });
106
- var movingNames = Object.keys(variableDeclarations);
107
-
108
- if (movingNames.length === 0) {
109
- return;
110
- }
38
+ var blockIndex = parents.findIndex(x => (0, _traverse.isBlock)(x));
39
+ var block = parents[blockIndex];
40
+ var body = block.body;
41
+ var bodyObject = parents[blockIndex - 2] || object; // Make sure in the block statement, and not already at the top of it
111
42
 
112
- var variableDeclaration = (0, _gen.VariableDeclaration)(movingNames.map(name => {
113
- return (0, _gen.VariableDeclarator)(name);
114
- }));
43
+ var index = body.indexOf(bodyObject);
44
+ if (index === -1 || index === 0) return;
45
+ var topVariableDeclaration;
115
46
 
116
- if (object.type == "Program") {
117
- (0, _insert.prepend)(object, variableDeclaration);
47
+ if (body[0].type === "VariableDeclaration" && body[0].kind === "var") {
48
+ topVariableDeclaration = body[0];
118
49
  } else {
119
- body.unshift(variableDeclaration);
50
+ topVariableDeclaration = {
51
+ type: "VariableDeclaration",
52
+ declarations: [],
53
+ kind: "var"
54
+ };
55
+ (0, _insert.prepend)(block, topVariableDeclaration);
120
56
  }
121
57
 
122
- movingNames.forEach(name => {
123
- var {
124
- location,
125
- replace
126
- } = variableDeclarations[name];
127
- this.replace(location[0], replace);
128
- });
58
+ var varName = object.declarations[0].id.name;
59
+ (0, _assert.ok)(typeof varName === "string"); // Add `var x` at the top of the block
60
+
61
+ topVariableDeclaration.declarations.push((0, _gen.VariableDeclarator)((0, _gen.Identifier)(varName)));
62
+ var assignmentExpression = (0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(varName), object.declarations[0].init || (0, _gen.Identifier)(varName));
63
+
64
+ if (forInitializeType) {
65
+ if (forInitializeType === "initializer") {
66
+ // Replace `for (var i = 0...)` to `for (i = 0...)`
67
+ this.replace(object, assignmentExpression);
68
+ } else if (forInitializeType === "left-hand") {
69
+ // Replace `for (var k in...)` to `for (k in ...)`
70
+ this.replace(object, (0, _gen.Identifier)(varName));
71
+ }
72
+ } else {
73
+ // Replace `var x = value` to `x = value`
74
+ this.replace(object, (0, _gen.ExpressionStatement)(assignmentExpression));
75
+ }
129
76
  };
130
77
  }
131
78
 
@@ -30,52 +30,58 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
30
30
  /**
31
31
  * Rename variables to randomly generated names.
32
32
  *
33
- * - Attempts to re-use already generated names in nested scopes.
33
+ * - 1. First collect data on identifiers in all scope using 'VariableAnalysis'
34
+ * - 2. After 'VariableAnalysis' is finished start applying to each scope (top-down)
35
+ * - 3. Each scope, find the all names used here and exclude those names from being re-named
36
+ * - 4. Now loop through all the defined names in this scope and set it to a random name (or re-use previously generated name)
37
+ * - 5. Update all the Identifiers node's 'name' property to reflect this change
34
38
  */
35
39
  class RenameVariables extends _transform.default {
36
- // Generator object
37
40
  // Names already used
38
41
  // Map of Context->Object of changes
39
42
  // Ref to VariableAnalysis data
43
+ // Option to re-use previously generated names
40
44
  constructor(o) {
41
45
  super(o, _order.ObfuscateOrder.RenameVariables);
42
46
 
43
- _defineProperty(this, "gen", void 0);
44
-
45
47
  _defineProperty(this, "generated", void 0);
46
48
 
47
49
  _defineProperty(this, "changed", void 0);
48
50
 
49
51
  _defineProperty(this, "variableAnalysis", void 0);
50
52
 
51
- this.changed = new Map();
53
+ _defineProperty(this, "reusePreviousNames", true);
54
+
55
+ this.changed = new Map(); // 1.
56
+
52
57
  this.variableAnalysis = new _variableAnalysis.default(o);
53
58
  this.before.push(this.variableAnalysis);
54
- this.gen = this.getGenerator();
55
59
  this.generated = [];
56
60
  }
57
61
 
58
62
  match(object, parents) {
59
- return (0, _insert.isContext)(object);
63
+ return (0, _insert.isContext)(object) || object.type === "Identifier";
60
64
  }
61
65
 
62
- transform(object, parents) {
66
+ transformContext(object, parents) {
67
+ // 2. Notice this is on 'onEnter' (top-down)
63
68
  var isGlobal = object.type == "Program";
64
69
  var type = isGlobal ? "root" : (0, _insert.isVarContext)(object) ? "var" : (0, _insert.isLexContext)(object) ? "lex" : undefined;
65
70
  (0, _assert.ok)(type);
66
71
  var newNames = Object.create(null);
67
72
  var defined = this.variableAnalysis.defined.get(object) || new Set();
68
- var references = this.variableAnalysis.references.get(object) || new Set();
73
+ var references = this.variableAnalysis.references.get(object) || new Set(); // No changes needed here
69
74
 
70
75
  if (!defined && !this.changed.has(object)) {
71
76
  this.changed.set(object, Object.create(null));
72
77
  return;
73
- }
78
+ } // Names possible to be re-used here
79
+
74
80
 
75
- var possible = new Set();
81
+ var possible = new Set(); // 3. Try to re-use names when possible
76
82
 
77
- if (this.generated.length && !isGlobal) {
78
- var allReferences = new Set(references || []);
83
+ if (this.reusePreviousNames && this.generated.length && !isGlobal) {
84
+ var allReferences = new Set();
79
85
  var nope = new Set(defined);
80
86
  (0, _traverse.walk)(object, [], (o, p) => {
81
87
  var ref = this.variableAnalysis.references.get(o);
@@ -98,7 +104,7 @@ class RenameVariables extends _transform.default {
98
104
  Object.keys(changes).forEach(x => {
99
105
  var name = changes[x];
100
106
 
101
- if (!allReferences.has(x)) {
107
+ if (!allReferences.has(x) && !references.has(x)) {
102
108
  passed.add(name);
103
109
  } else {
104
110
  nope.add(name);
@@ -108,80 +114,139 @@ class RenameVariables extends _transform.default {
108
114
  });
109
115
  nope.forEach(x => passed.delete(x));
110
116
  possible = passed;
111
- }
117
+ } // 4. Defined names to new names
112
118
 
113
- defined.forEach(name => {
114
- if ((isGlobal && !name.startsWith("__p_") ? (0, _probability.ComputeProbabilityMap)(this.options.renameGlobals, x => x, name) : true) && (0, _probability.ComputeProbabilityMap)(this.options.renameVariables, x => x, name, isGlobal)) {
115
- // Fix 2. Ensure global names aren't overridden
119
+
120
+ for (var name of defined) {
121
+ if (!name.startsWith(_constants.noRenameVariablePrefix) && ( // Variables prefixed with '__NO_JS_CONFUSER_RENAME__' are never renamed
122
+ isGlobal && !name.startsWith(_constants.placeholderVariablePrefix) // Variables prefixed with '__p_' are created by the obfuscator, always renamed
123
+ ? (0, _probability.ComputeProbabilityMap)(this.options.renameGlobals, x => x, name) : true) && (0, _probability.ComputeProbabilityMap)( // Check the user's option for renaming variables
124
+ this.options.renameVariables, x => x, name, isGlobal)) {
125
+ // Create a new name from (1) or (2) methods
116
126
  var newName;
117
127
 
118
128
  do {
119
129
  if (possible.size) {
130
+ // (1) Re-use previously generated name
120
131
  var first = possible.values().next().value;
121
132
  possible.delete(first);
122
133
  newName = first;
123
134
  } else {
124
- // Fix 1. Use `generateIdentifier` over `gen.generate()` so Integrity can get unique variable names
125
- var g = this.generateIdentifier();
126
- newName = g;
127
- this.generated.push(g);
135
+ // (2) Create a new name with `generateIdentifier` function
136
+ var generatedName = this.generateIdentifier();
137
+ newName = generatedName;
138
+ this.generated.push(generatedName);
128
139
  }
129
- } while (this.variableAnalysis.globals.has(newName));
140
+ } while (this.variableAnalysis.globals.has(newName)); // Ensure global names aren't overridden
141
+
130
142
 
131
143
  newNames[name] = newName;
132
144
  } else {
145
+ // This variable name was deemed not to be renamed.
133
146
  newNames[name] = name;
134
147
  }
135
- });
148
+ } // console.log(object.type, newNames);
149
+
150
+
136
151
  this.changed.set(object, newNames);
137
- (0, _traverse.walk)(object, parents, (o, p) => {
138
- if (o.type == "Identifier") {
139
- if (_constants.reservedIdentifiers.has(o.name) || this.options.globalVariables.has(o.name)) {
140
- return;
141
- }
152
+ }
142
153
 
143
- var info = (0, _identifiers.getIdentifierInfo)(o, p);
154
+ transformIdentifier(object, parents) {
155
+ const identifierName = object.name;
144
156
 
145
- if (info.spec.isExported) {
146
- return;
147
- }
157
+ if (_constants.reservedIdentifiers.has(identifierName) || this.options.globalVariables.has(identifierName)) {
158
+ return;
159
+ }
148
160
 
149
- if (!info.spec.isReferenced) {
150
- return;
151
- }
161
+ if (object.$renamed) {
162
+ return;
163
+ }
152
164
 
153
- var contexts = [o, ...p].filter(x => (0, _insert.isContext)(x));
154
- var newName = null;
165
+ var info = (0, _identifiers.getIdentifierInfo)(object, parents);
155
166
 
156
- for (var check of contexts) {
157
- if (this.variableAnalysis.defined.has(check) && this.variableAnalysis.defined.get(check).has(o.name)) {
158
- if (this.changed.has(check) && this.changed.get(check)[o.name]) {
159
- newName = this.changed.get(check)[o.name];
160
- break;
161
- }
162
- }
163
- }
167
+ if (info.spec.isExported) {
168
+ return;
169
+ }
170
+
171
+ if (!info.spec.isReferenced) {
172
+ return;
173
+ }
164
174
 
165
- if (newName && typeof newName === "string") {
166
- if (o.$renamed) {
167
- return;
168
- } // Strange behavior where the `local` and `imported` objects are the same
175
+ var contexts = [object, ...parents].filter(x => (0, _insert.isContext)(x));
176
+ var newName = null; // Function default parameter check!
169
177
 
178
+ var functionIndices = [];
170
179
 
171
- if (info.isImportSpecifier) {
172
- var importSpecifierIndex = p.findIndex(x => x.type === "ImportSpecifier");
180
+ for (var i in parents) {
181
+ if ((0, _insert.isFunction)(parents[i])) {
182
+ functionIndices.push(i);
183
+ }
184
+ }
173
185
 
174
- if (importSpecifierIndex != -1 && p[importSpecifierIndex].imported === (p[importSpecifierIndex - 1] || o) && p[importSpecifierIndex].imported && p[importSpecifierIndex].imported.type === "Identifier") {
175
- p[importSpecifierIndex].imported = (0, _insert.clone)(p[importSpecifierIndex - 1] || o);
176
- }
177
- } // console.log(o.name, "->", newName);
186
+ for (var functionIndex of functionIndices) {
187
+ if (parents[functionIndex].id === object) {
188
+ // This context is not referenced, so remove it
189
+ contexts = contexts.filter(context => context != parents[functionIndex]);
190
+ continue;
191
+ }
192
+
193
+ if (parents[functionIndex].params === parents[functionIndex - 1]) {
194
+ var isReferencedHere = true;
195
+ var slicedParents = parents.slice(0, functionIndex);
196
+ var forIndex = 0;
197
+
198
+ for (var parent of slicedParents) {
199
+ var childNode = slicedParents[forIndex - 1] || object;
178
200
 
201
+ if (parent.type === "AssignmentPattern" && parent.right === childNode) {
202
+ isReferencedHere = false;
203
+ break;
204
+ }
205
+
206
+ forIndex++;
207
+ }
208
+
209
+ if (!isReferencedHere) {
210
+ // This context is not referenced, so remove it
211
+ contexts = contexts.filter(context => context != parents[functionIndex]);
212
+ }
213
+ }
214
+ }
179
215
 
180
- o.name = newName;
181
- o.$renamed = true;
216
+ for (var check of contexts) {
217
+ if (this.variableAnalysis.defined.has(check) && this.variableAnalysis.defined.get(check).has(identifierName)) {
218
+ if (this.changed.has(check) && this.changed.get(check)[identifierName]) {
219
+ newName = this.changed.get(check)[identifierName];
220
+ break;
182
221
  }
183
222
  }
184
- });
223
+ }
224
+
225
+ if (newName && typeof newName === "string") {
226
+ // Strange behavior where the `local` and `imported` objects are the same
227
+ if (info.isImportSpecifier) {
228
+ var importSpecifierIndex = parents.findIndex(x => x.type === "ImportSpecifier");
229
+
230
+ if (importSpecifierIndex != -1 && parents[importSpecifierIndex].imported === (parents[importSpecifierIndex - 1] || object) && parents[importSpecifierIndex].imported && parents[importSpecifierIndex].imported.type === "Identifier") {
231
+ parents[importSpecifierIndex].imported = (0, _insert.clone)(parents[importSpecifierIndex - 1] || object);
232
+ }
233
+ } // console.log(o.name, "->", newName);
234
+ // 5. Update Identifier node's 'name' property
235
+
236
+
237
+ object.name = newName;
238
+ object.$renamed = true;
239
+ }
240
+ }
241
+
242
+ transform(object, parents) {
243
+ var matchType = object.type === "Identifier" ? "Identifier" : "Context";
244
+
245
+ if (matchType === "Identifier") {
246
+ this.transformIdentifier(object, parents);
247
+ } else {
248
+ this.transformContext(object, parents);
249
+ }
185
250
  }
186
251
 
187
252
  }