js-confuser 1.5.8 → 1.6.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 (139) hide show
  1. package/.github/workflows/node.js.yml +2 -2
  2. package/CHANGELOG.md +69 -0
  3. package/README.md +143 -7
  4. package/dist/index.js +33 -4
  5. package/dist/obfuscator.js +30 -31
  6. package/dist/options.js +4 -5
  7. package/dist/order.js +4 -6
  8. package/dist/probability.js +2 -4
  9. package/dist/templates/bufferToString.js +13 -0
  10. package/dist/templates/crash.js +2 -2
  11. package/dist/templates/es5.js +18 -0
  12. package/dist/transforms/antiTooling.js +1 -1
  13. package/dist/transforms/calculator.js +77 -21
  14. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
  15. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +8 -3
  16. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
  17. package/dist/transforms/deadCode.js +33 -25
  18. package/dist/transforms/dispatcher.js +7 -6
  19. package/dist/transforms/es5/antiClass.js +6 -2
  20. package/dist/transforms/es5/antiDestructuring.js +3 -1
  21. package/dist/transforms/es5/es5.js +31 -34
  22. package/dist/transforms/eval.js +11 -0
  23. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +8 -5
  24. package/dist/transforms/extraction/objectExtraction.js +6 -1
  25. package/dist/transforms/finalizer.js +82 -0
  26. package/dist/transforms/flatten.js +82 -55
  27. package/dist/transforms/hexadecimalNumbers.js +34 -9
  28. package/dist/transforms/identifier/globalAnalysis.js +88 -0
  29. package/dist/transforms/identifier/globalConcealing.js +10 -83
  30. package/dist/transforms/identifier/movedDeclarations.js +2 -8
  31. package/dist/transforms/identifier/renameVariables.js +39 -27
  32. package/dist/transforms/identifier/variableAnalysis.js +58 -62
  33. package/dist/transforms/minify.js +80 -61
  34. package/dist/transforms/opaquePredicates.js +1 -1
  35. package/dist/transforms/preparation/preparation.js +2 -2
  36. package/dist/transforms/preparation.js +231 -0
  37. package/dist/transforms/renameLabels.js +1 -1
  38. package/dist/transforms/rgf.js +4 -5
  39. package/dist/transforms/stack.js +87 -26
  40. package/dist/transforms/string/encoding.js +150 -179
  41. package/dist/transforms/string/stringCompression.js +14 -15
  42. package/dist/transforms/string/stringConcealing.js +25 -8
  43. package/dist/transforms/string/stringEncoding.js +13 -24
  44. package/dist/transforms/transform.js +11 -18
  45. package/dist/traverse.js +24 -18
  46. package/dist/util/compare.js +2 -2
  47. package/dist/util/gen.js +15 -0
  48. package/dist/util/insert.js +31 -7
  49. package/dist/util/random.js +15 -0
  50. package/package.json +5 -5
  51. package/src/index.ts +57 -19
  52. package/src/obfuscator.ts +26 -29
  53. package/src/options.ts +17 -21
  54. package/src/order.ts +4 -8
  55. package/src/probability.ts +2 -3
  56. package/src/templates/bufferToString.ts +68 -0
  57. package/src/templates/crash.ts +5 -9
  58. package/src/templates/es5.ts +131 -0
  59. package/src/transforms/antiTooling.ts +1 -1
  60. package/src/transforms/calculator.ts +122 -59
  61. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
  62. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +18 -3
  63. package/src/transforms/deadCode.ts +383 -26
  64. package/src/transforms/dispatcher.ts +8 -6
  65. package/src/transforms/es5/antiClass.ts +10 -1
  66. package/src/transforms/es5/antiDestructuring.ts +3 -1
  67. package/src/transforms/es5/es5.ts +32 -77
  68. package/src/transforms/eval.ts +18 -0
  69. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +9 -6
  70. package/src/transforms/extraction/objectExtraction.ts +12 -5
  71. package/src/transforms/finalizer.ts +75 -0
  72. package/src/transforms/flatten.ts +194 -151
  73. package/src/transforms/identifier/globalAnalysis.ts +85 -0
  74. package/src/transforms/identifier/globalConcealing.ts +14 -103
  75. package/src/transforms/identifier/movedDeclarations.ts +4 -11
  76. package/src/transforms/identifier/renameVariables.ts +37 -30
  77. package/src/transforms/identifier/variableAnalysis.ts +66 -73
  78. package/src/transforms/minify.ts +116 -77
  79. package/src/transforms/opaquePredicates.ts +2 -2
  80. package/src/transforms/preparation.ts +238 -0
  81. package/src/transforms/renameLabels.ts +2 -2
  82. package/src/transforms/rgf.ts +6 -7
  83. package/src/transforms/stack.ts +97 -37
  84. package/src/transforms/string/encoding.ts +115 -212
  85. package/src/transforms/string/stringCompression.ts +27 -18
  86. package/src/transforms/string/stringConcealing.ts +41 -11
  87. package/src/transforms/string/stringEncoding.ts +18 -18
  88. package/src/transforms/transform.ts +15 -21
  89. package/src/traverse.ts +24 -12
  90. package/src/types.ts +11 -2
  91. package/src/util/compare.ts +2 -2
  92. package/src/util/gen.ts +21 -1
  93. package/src/util/insert.ts +49 -9
  94. package/src/util/random.ts +13 -0
  95. package/test/code/Cash.test.ts +1 -1
  96. package/test/code/Dynamic.test.ts +12 -10
  97. package/test/code/ES6.src.js +136 -0
  98. package/test/code/ES6.test.ts +28 -2
  99. package/test/code/NewFeatures.test.ts +19 -0
  100. package/test/index.test.ts +15 -2
  101. package/test/probability.test.ts +44 -0
  102. package/test/templates/template.test.ts +1 -1
  103. package/test/transforms/antiTooling.test.ts +52 -0
  104. package/test/transforms/calculator.test.ts +40 -0
  105. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +713 -149
  106. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
  107. package/test/transforms/deadCode.test.ts +66 -15
  108. package/test/transforms/dispatcher.test.ts +44 -1
  109. package/test/transforms/es5/antiClass.test.ts +33 -0
  110. package/test/transforms/es5/antiDestructuring.test.ts +16 -0
  111. package/test/transforms/eval.test.ts +53 -0
  112. package/test/transforms/extraction/objectExtraction.test.ts +21 -0
  113. package/test/transforms/flatten.test.ts +195 -3
  114. package/test/transforms/identifier/movedDeclarations.test.ts +27 -0
  115. package/test/transforms/identifier/renameVariables.test.ts +108 -0
  116. package/test/transforms/lock/antiDebug.test.ts +2 -2
  117. package/test/transforms/minify.test.ts +151 -0
  118. package/test/transforms/preparation.test.ts +157 -0
  119. package/test/transforms/rgf.test.ts +56 -29
  120. package/test/transforms/stack.test.ts +91 -21
  121. package/test/transforms/string/stringCompression.test.ts +39 -0
  122. package/test/transforms/string/stringConcealing.test.ts +115 -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/compare.test.ts +23 -1
  127. package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
  128. package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
  129. package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
  130. package/src/transforms/hexadecimalNumbers.ts +0 -31
  131. package/src/transforms/hideInitializingCode.ts +0 -432
  132. package/src/transforms/label.ts +0 -64
  133. package/src/transforms/preparation/nameConflicts.ts +0 -102
  134. package/src/transforms/preparation/preparation.ts +0 -176
  135. package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
  136. package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
  137. package/test/transforms/hideInitializingCode.test.ts +0 -336
  138. package/test/transforms/preparation/nameConflicts.test.ts +0 -52
  139. package/test/transforms/preparation/preparation.test.ts +0 -62
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _transform = _interopRequireDefault(require("./transform"));
9
+
10
+ var _gen = require("../util/gen");
11
+
12
+ var _order = require("../order");
13
+
14
+ var _insert = require("../util/insert");
15
+
16
+ var _identifiers = require("../util/identifiers");
17
+
18
+ var _compare = require("../util/compare");
19
+
20
+ var _traverse = require("../traverse");
21
+
22
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23
+
24
+ /**
25
+ * Preparation arranges the user's code into an AST the obfuscator can easily transform.
26
+ *
27
+ * ExplicitIdentifiers
28
+ * - `object.IDENTIFIER` -> `object['IDENTIFIER']` // Now String Concealing can apply on it
29
+ * - `{ IDENTIFIER: ... }` -> `{ "IDENTIFIER": ... }`
30
+ *
31
+ * ExplicitDeclarations
32
+ * - `var a,b,c` -> `var a; var b; var c;` // Now Stack can apply on it
33
+ *
34
+ * Block
35
+ * - `x => x * 2` -> `x => { return x * 2 }` // Change into Block Statements
36
+ * - `if(true) return` -> `if (true) { return }`
37
+ * - `while(a) a--;` -> `while(a) { a-- }`
38
+ *
39
+ * Label
40
+ * - `for(...) { break; }` -> `_1: for(...) { break _1; }`
41
+ * - `switch(v) { case 1...break }` -> `_2: switch(v) { case 1...break _2; }`
42
+ * - // Control Flow Flattening can safely apply now
43
+ */
44
+ class Preparation extends _transform.default {
45
+ constructor(o) {
46
+ super(o, _order.ObfuscateOrder.Preparation);
47
+ }
48
+
49
+ match(object, parents) {
50
+ return !!object.type;
51
+ }
52
+
53
+ transform(object, parents) {
54
+ // ExplicitIdentifiers
55
+ if (object.type === "Identifier") {
56
+ return this.transformExplicitIdentifiers(object, parents);
57
+ } // ExplicitDeclarations
58
+
59
+
60
+ if (object.type === "VariableDeclaration") {
61
+ return this.transformExplicitDeclarations(object, parents);
62
+ } // Block
63
+
64
+
65
+ switch (object.type) {
66
+ /**
67
+ * People use shortcuts and its harder to parse.
68
+ *
69
+ * - `if (a) b()` -> `if (a) { b() }`
70
+ * - Ensures all bodies are `BlockStatement`, not individual expression statements
71
+ */
72
+ case "IfStatement":
73
+ if (object.consequent.type != "BlockStatement") {
74
+ object.consequent = (0, _gen.BlockStatement)([(0, _insert.clone)(object.consequent)]);
75
+ }
76
+
77
+ if (object.alternate && object.alternate.type != "BlockStatement") {
78
+ object.alternate = (0, _gen.BlockStatement)([(0, _insert.clone)(object.alternate)]);
79
+ }
80
+
81
+ break;
82
+
83
+ case "WhileStatement":
84
+ case "WithStatement":
85
+ case "ForStatement":
86
+ case "ForOfStatement":
87
+ case "ForInStatement":
88
+ if (object.body.type != "BlockStatement") {
89
+ object.body = (0, _gen.BlockStatement)([(0, _insert.clone)(object.body)]);
90
+ }
91
+
92
+ break;
93
+
94
+ case "ArrowFunctionExpression":
95
+ if (object.body.type !== "BlockStatement" && object.expression) {
96
+ object.body = (0, _gen.BlockStatement)([(0, _gen.ReturnStatement)((0, _insert.clone)(object.body))]);
97
+ object.expression = false;
98
+ }
99
+
100
+ break;
101
+ } // Label
102
+
103
+
104
+ if ((0, _compare.isLoop)(object) || object.type == "BlockStatement" && parents[0] && parents[0].type == "LabeledStatement" && parents[0].body === object) {
105
+ return this.transformLabel(object, parents);
106
+ }
107
+ }
108
+ /**
109
+ * Ensures every break; statement has a label to point to.
110
+ *
111
+ * This is because Control Flow Flattening adds For Loops which label-less break statements point to the nearest,
112
+ * when they actually need to point to the original statement.
113
+ */
114
+
115
+
116
+ transformLabel(object, parents) {
117
+ return () => {
118
+ var currentLabel = parents[0].type == "LabeledStatement" && parents[0].label.name;
119
+ var label = currentLabel || this.getPlaceholder();
120
+ (0, _traverse.walk)(object, parents, (o, p) => {
121
+ if (o.type == "BreakStatement" || o.type == "ContinueStatement") {
122
+ function isContinuableStatement(x) {
123
+ return (0, _compare.isLoop)(x) && x.type !== "SwitchStatement";
124
+ }
125
+
126
+ function isBreakableStatement(x) {
127
+ return (0, _compare.isLoop)(x) || o.label && x.type == "BlockStatement";
128
+ }
129
+
130
+ var fn = o.type == "ContinueStatement" ? isContinuableStatement : isBreakableStatement;
131
+ var loop = p.find(fn);
132
+
133
+ if (object == loop) {
134
+ if (!o.label) {
135
+ o.label = (0, _gen.Identifier)(label);
136
+ }
137
+ }
138
+ }
139
+ }); // Append label statement as this loop has none
140
+
141
+ if (!currentLabel) {
142
+ this.replace(object, (0, _gen.LabeledStatement)(label, { ...object
143
+ }));
144
+ }
145
+ };
146
+ }
147
+ /**
148
+ * Transforms Identifiers (a.IDENTIFIER, {IDENTIFIER:...}) into string properties
149
+ */
150
+
151
+
152
+ transformExplicitIdentifiers(object, parents) {
153
+ // Mark functions containing 'eval'
154
+ // Some transformations avoid functions that have 'eval' to not break them
155
+ if (object.name === "eval") {
156
+ var fn = (0, _insert.getFunction)(object, parents);
157
+
158
+ if (fn) {
159
+ fn.$requiresEval = true;
160
+ }
161
+ }
162
+
163
+ var info = (0, _identifiers.getIdentifierInfo)(object, parents);
164
+
165
+ if (info.isPropertyKey || info.isAccessor) {
166
+ var propIndex = parents.findIndex(x => x.type == "MethodDefinition" || x.type == "Property"); // Don't change constructor!
167
+
168
+ if (propIndex !== -1) {
169
+ if (parents[propIndex].type == "MethodDefinition" && parents[propIndex].kind == "constructor") {
170
+ return;
171
+ }
172
+ }
173
+
174
+ this.replace(object, (0, _gen.Literal)(object.name));
175
+ parents[0].computed = true;
176
+ parents[0].shorthand = false;
177
+ }
178
+ }
179
+ /**
180
+ * Transforms VariableDeclaration into single declarations.
181
+ */
182
+
183
+
184
+ transformExplicitDeclarations(object, parents) {
185
+ // for ( var x in ... ) {...}
186
+ var forIndex = parents.findIndex(x => x.type == "ForInStatement" || x.type == "ForOfStatement");
187
+
188
+ if (forIndex != -1 && parents[forIndex].left == (parents[forIndex - 1] || object)) {
189
+ object.declarations.forEach(x => {
190
+ x.init = null;
191
+ });
192
+ return;
193
+ }
194
+
195
+ var body = parents[0];
196
+
197
+ if ((0, _compare.isLoop)(body) || body.type == "LabeledStatement") {
198
+ return;
199
+ }
200
+
201
+ if (body.type == "ExportNamedDeclaration") {
202
+ return;
203
+ }
204
+
205
+ if (!Array.isArray(body)) {
206
+ this.error(new Error("body is " + body.type));
207
+ }
208
+
209
+ if (object.declarations.length > 1) {
210
+ // Make singular
211
+ var index = body.indexOf(object);
212
+
213
+ if (index == -1) {
214
+ this.error(new Error("index is -1"));
215
+ }
216
+
217
+ var after = object.declarations.slice(1);
218
+ body.splice(index + 1, 0, ...after.map(x => {
219
+ return {
220
+ type: "VariableDeclaration",
221
+ declarations: [(0, _insert.clone)(x)],
222
+ kind: object.kind
223
+ };
224
+ }));
225
+ object.declarations.length = 1;
226
+ }
227
+ }
228
+
229
+ }
230
+
231
+ exports.default = Preparation;
@@ -30,7 +30,7 @@ class RenameLabels extends _transform.default {
30
30
 
31
31
  _defineProperty(this, "gen", void 0);
32
32
 
33
- this.gen = this.getGenerator();
33
+ this.gen = this.getGenerator("randomized");
34
34
  }
35
35
 
36
36
  match(object, parents) {
@@ -241,7 +241,8 @@ class RGF extends _transform.default {
241
241
  // fn
242
242
  // In most cases the identifier is being used like this (call expression, or referenced to be called later)
243
243
  // Replace it with a simple wrapper function that will pass on the reference array
244
- var conditionalExpression = (0, _gen.ConditionalExpression)((0, _template.default)("typeof ".concat(referenceArray, "[").concat(index, "] === \"function\" && ").concat(referenceArray, "[").concat(index, "][\"").concat(referenceSignatures[index] || "_", "\"]")).single().expression, (0, _gen.FunctionExpression)([], [(0, _gen.ReturnStatement)((0, _gen.CallExpression)(memberExpression, [(0, _gen.Identifier)(referenceArray), (0, _gen.SpreadElement)((0, _gen.Identifier)("arguments"))]))]), memberExpression);
244
+ var conditionalExpression = (0, _gen.ConditionalExpression)((0, _template.default)("typeof ".concat(referenceArray, "[").concat(index, "] === \"function\" && ").concat(referenceArray, "[").concat(index, "][\"").concat(referenceSignatures[index] || "_", "\"]")).single().expression, (0, _gen.FunctionExpression)([], [(0, _gen.ReturnStatement)( // clone() is required!
245
+ (0, _gen.CallExpression)((0, _insert.clone)(memberExpression), [(0, _gen.Identifier)(referenceArray), (0, _gen.SpreadElement)((0, _gen.Identifier)("arguments"))]))]), (0, _insert.clone)(memberExpression));
245
246
  this.replace(o, conditionalExpression);
246
247
  }
247
248
  }
@@ -258,8 +259,6 @@ class RGF extends _transform.default {
258
259
 
259
260
  let [object, parents] = _ref2;
260
261
  var name = object === null || object === void 0 ? void 0 : (_object$id2 = object.id) === null || _object$id2 === void 0 ? void 0 : _object$id2.name;
261
- var hasName = !!name;
262
- var params = object.params.map(x => x.name) || [];
263
262
  var signature = referenceSignatures[names.get(name)];
264
263
  var embeddedName = name || this.getPlaceholder(); // Since `new Function` is completely isolated, create an entire new obfuscator and run remaining transformations.
265
264
  // RGF runs early and needs completed code before converting to a string.
@@ -272,9 +271,9 @@ class RGF extends _transform.default {
272
271
  integrity: false
273
272
  },
274
273
  eval: false,
275
- hideInitializingCode: false
274
+ stringEncoding: false
276
275
  });
277
- var transforms = Object.values(obfuscator.transforms).filter(x => x.priority > this.priority);
276
+ var transforms = obfuscator.array.filter(x => x.priority > this.priority);
278
277
  var embeddedFunction = { ...object,
279
278
  type: "FunctionDeclaration",
280
279
  id: (0, _gen.Identifier)(embeddedName)
@@ -9,6 +9,8 @@ var _assert = require("assert");
9
9
 
10
10
  var _order = require("../order");
11
11
 
12
+ var _probability = require("../probability");
13
+
12
14
  var _template = _interopRequireDefault(require("../templates/template"));
13
15
 
14
16
  var _traverse = require("../traverse");
@@ -31,9 +33,9 @@ class Stack extends _transform.default {
31
33
  constructor(o) {
32
34
  super(o, _order.ObfuscateOrder.Stack);
33
35
 
34
- _defineProperty(this, "made", void 0);
36
+ _defineProperty(this, "mangledExpressionsMade", void 0);
35
37
 
36
- this.made = 0;
38
+ this.mangledExpressionsMade = 0;
37
39
  }
38
40
 
39
41
  match(object, parents) {
@@ -41,10 +43,14 @@ class Stack extends _transform.default {
41
43
  }
42
44
 
43
45
  transform(object, parents) {
46
+ var _this = this;
47
+
44
48
  return () => {
49
+ var _getBlockBody$;
50
+
45
51
  // Uncaught SyntaxError: Getter must not have any formal parameters.
46
52
  // Uncaught SyntaxError: Setter must have exactly one formal parameter
47
- var propIndex = parents.findIndex(x => x.type == "Property");
53
+ var propIndex = parents.findIndex(x => x.type === "Property" || x.type === "MethodDefinition");
48
54
 
49
55
  if (propIndex !== -1) {
50
56
  if (parents[propIndex].value === (parents[propIndex - 1] || object)) {
@@ -52,13 +58,40 @@ class Stack extends _transform.default {
52
58
  return;
53
59
  }
54
60
  }
61
+ } // Don't apply to functions with 'use strict' directive
62
+
63
+
64
+ if ((_getBlockBody$ = (0, _insert.getBlockBody)(object.body)[0]) !== null && _getBlockBody$ !== void 0 && _getBlockBody$.directive) {
65
+ return;
66
+ }
67
+
68
+ if (!(0, _probability.ComputeProbabilityMap)(this.options.stack)) {
69
+ return;
55
70
  }
56
71
 
57
72
  var defined = new Set();
58
73
  var referenced = new Set();
59
74
  var illegal = new Set();
75
+ /**
76
+ * Maps old names to new indices
77
+ */
78
+
60
79
  var subscripts = new Map();
61
80
  var deadValues = Object.create(null);
81
+ var propertyGen = this.getGenerator();
82
+
83
+ function isTransformableFunction(functionNode) {
84
+ if (functionNode.$requiresEval) return false; // Check for 'this'
85
+
86
+ var isIllegal = false;
87
+ (0, _traverse.walk)(functionNode.body, [], (o, p) => {
88
+ if (o.type === "ThisExpression") {
89
+ isIllegal = true;
90
+ return "EXIT";
91
+ }
92
+ });
93
+ return !isIllegal;
94
+ }
62
95
 
63
96
  function setSubscript(string, index) {
64
97
  subscripts.set(string, index + "");
@@ -74,19 +107,21 @@ class Stack extends _transform.default {
74
107
  if (o.type == "Identifier") {
75
108
  var info = (0, _identifiers.getIdentifierInfo)(o, p);
76
109
 
77
- if (!info.spec.isReferenced) {
110
+ if (!info.spec.isReferenced || info.spec.isExported) {
78
111
  return;
79
112
  }
80
113
 
81
114
  var c = info.spec.isDefined ? (0, _insert.getDefiningContext)(o, p) : (0, _insert.getReferencingContexts)(o, p).find(x => (0, _insert.isVarContext)(x));
82
115
 
83
116
  if (c !== object) {
84
- this.log(o.name + " is illegal due to different context");
117
+ // this.log(o.name + " is illegal due to different context");
85
118
  illegal.add(o.name);
86
119
  }
87
120
 
88
121
  if (info.isClauseParameter || info.isFunctionParameter || (0, _insert.isForInitialize)(o, p)) {
89
- this.log(o.name + " is illegal due to clause parameter/function parameter");
122
+ // this.log(
123
+ // o.name + " is illegal due to clause parameter/function parameter"
124
+ // );
90
125
  illegal.add(o.name);
91
126
  }
92
127
 
@@ -100,19 +135,47 @@ class Stack extends _transform.default {
100
135
  }
101
136
 
102
137
  if (info.isFunctionDeclaration) {
103
- if (p[0] !== object.body.body[0]) {
138
+ (0, _assert.ok)(p[0].type === "FunctionDeclaration");
139
+
140
+ if (p[0] !== object.body.body[0] || !isTransformableFunction(p[0])) {
104
141
  illegal.add(o.name);
105
142
  }
106
- }
143
+ } // The new accessors will either be numbered: [index] or as a string .string
144
+
145
+
146
+ var newSubscript = (0, _random.choice)([subscripts.size, propertyGen.generate()]);
147
+ setSubscript(o.name, newSubscript);
148
+ defined.add(o.name); // Stack can only process single VariableDeclarations
107
149
 
108
- setSubscript(o.name, subscripts.size);
109
- defined.add(o.name);
110
150
  var varIndex = p.findIndex(x => x.type == "VariableDeclaration");
111
151
 
112
- if (varIndex !== -1 && (varIndex !== 2 || p[varIndex].declarations.length > 1)) {
113
- illegal.add(o.name);
152
+ if (varIndex !== -1) {
153
+ // Invalid 'id' property (must be Identifier)
154
+ if (varIndex !== 2) {
155
+ illegal.add(o.name);
156
+ } else if (p[varIndex].declarations.length > 1) {
157
+ illegal.add(o.name);
158
+ } else {
159
+ var value = p[varIndex].declarations[0].init;
160
+
161
+ if (value && !isTransformableFunction(value)) {
162
+ illegal.add(o.name);
163
+ }
164
+ }
114
165
  }
115
166
  } else if (info.spec.isReferenced) {
167
+ if (info.spec.isModified) {
168
+ var assignmentIndex = p.findIndex(x => x.type === "AssignmentExpression");
169
+
170
+ if (assignmentIndex !== -1) {
171
+ var value = p[assignmentIndex].right;
172
+
173
+ if (value && !isTransformableFunction(value)) {
174
+ illegal.add(o.name);
175
+ }
176
+ }
177
+ }
178
+
116
179
  referenced.add(o.name);
117
180
  }
118
181
  }
@@ -136,14 +199,15 @@ class Stack extends _transform.default {
136
199
  return;
137
200
  }
138
201
 
139
- function numberLiteral(number) {
202
+ const numberLiteral = function (number) {
140
203
  let depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
141
204
  (0, _assert.ok)(number === number);
142
205
 
143
- if (typeof number !== "number" || !Object.keys(deadValues).length || depth > 5 || Math.random() > (depth == 0 ? 0.9 : 0.8 / (depth * 2))) {
206
+ if (typeof number !== "number" || !Object.keys(deadValues).length || depth > 4 || (0, _random.chance)(75 + depth * 15 + _this.mangledExpressionsMade / 25)) {
144
207
  return (0, _gen.Literal)(number);
145
208
  }
146
209
 
210
+ _this.mangledExpressionsMade++;
147
211
  var opposingIndex = (0, _random.choice)(Object.keys(deadValues));
148
212
 
149
213
  if (typeof opposingIndex === "undefined") {
@@ -153,15 +217,14 @@ class Stack extends _transform.default {
153
217
  var actualValue = deadValues[opposingIndex];
154
218
  (0, _assert.ok)(typeof actualValue === "number");
155
219
  return (0, _gen.BinaryExpression)("-", (0, _gen.MemberExpression)((0, _gen.Identifier)(stackName), numberLiteral(isNaN(parseFloat(opposingIndex)) ? opposingIndex : parseFloat(opposingIndex), depth + 1), true), numberLiteral(actualValue - number, depth + 1));
156
- }
220
+ };
157
221
 
158
222
  function getMemberExpression(index) {
159
223
  (0, _assert.ok)(typeof index === "string", typeof index);
160
224
  return (0, _gen.MemberExpression)((0, _gen.Identifier)(stackName), numberLiteral(isNaN(parseFloat(index)) ? index : parseFloat(index)), true);
161
225
  }
162
226
 
163
- var stackName = this.getPlaceholder();
164
- var made = 1;
227
+ var stackName = this.getPlaceholder() + "_stack";
165
228
 
166
229
  const scan = (o, p) => {
167
230
  if (o.type == "Identifier") {
@@ -216,8 +279,7 @@ class Stack extends _transform.default {
216
279
  }
217
280
  }
218
281
 
219
- if (o.type == "Literal" && typeof o.value === "number" && Math.floor(o.value) === o.value && Math.abs(o.value) < 100000 && Math.random() < 4 / made && p.find(x => (0, _insert.isFunction)(x)) === object) {
220
- made++;
282
+ if (o.type == "Literal" && typeof o.value === "number" && Math.floor(o.value) === o.value && Math.abs(o.value) < 100000 && p.find(x => (0, _insert.isFunction)(x)) === object && (0, _random.chance)(50)) {
221
283
  return () => {
222
284
  this.replaceIdentifierOrLiteral(o, numberLiteral(o.value, 0), p);
223
285
  };
@@ -228,9 +290,9 @@ class Stack extends _transform.default {
228
290
  object.body.body.forEach((stmt, index) => {
229
291
  var isFirst = index == 0;
230
292
 
231
- if (isFirst || Math.random() < 0.9 / index) {
293
+ if (isFirst || (0, _random.chance)(50 - index * 10)) {
232
294
  var exprs = [];
233
- var changes = (0, _random.getRandomInteger)(isFirst ? 2 : 1, isFirst ? 3 : 2);
295
+ var changes = (0, _random.getRandomInteger)(1, 3);
234
296
 
235
297
  for (var i = 0; i < changes; i++) {
236
298
  var expr;
@@ -240,7 +302,7 @@ class Stack extends _transform.default {
240
302
  var i = 0;
241
303
 
242
304
  do {
243
- newIndex = (0, _random.getRandomInteger)(0, 250 + subscripts.size + i * 1000) + "";
305
+ newIndex = (0, _random.choice)([propertyGen.generate(), (0, _random.getRandomInteger)(0, 250 + subscripts.size + i * 1000) + ""]);
244
306
  i++;
245
307
  } while (valueSet.has(newIndex));
246
308
 
@@ -254,9 +316,9 @@ class Stack extends _transform.default {
254
316
  break;
255
317
 
256
318
  case "deadValue":
257
- var rand = (0, _random.getRandomInteger)(-250, 250); // modify an already existing dead value index
319
+ var rand = (0, _random.getRandomInteger)(-150, 150); // modify an already existing dead value index
258
320
 
259
- if (Math.random() > 0.5) {
321
+ if ((0, _random.chance)(50)) {
260
322
  var alreadyExisting = (0, _random.choice)(Object.keys(deadValues));
261
323
 
262
324
  if (typeof alreadyExisting === "string") {
@@ -265,7 +327,6 @@ class Stack extends _transform.default {
265
327
  }
266
328
 
267
329
  expr = (0, _gen.AssignmentExpression)("=", getMemberExpression(newIndex), numberLiteral(rand));
268
- (0, _assert.ok)(!subscripts.has(newIndex));
269
330
  deadValues[newIndex] = rand;
270
331
  break;
271
332
  }
@@ -295,7 +356,7 @@ class Stack extends _transform.default {
295
356
 
296
357
  object.params = [(0, _gen.RestElement)((0, _gen.Identifier)(stackName))]; // Ensure the array is correct length
297
358
 
298
- (0, _insert.prepend)(object.body, (0, _template.default)("".concat(stackName, ".length = ").concat(startingSize)).single());
359
+ (0, _insert.prepend)(object.body, (0, _template.default)("".concat(stackName, "[\"length\"] = ").concat(startingSize)).single());
299
360
  };
300
361
  }
301
362