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
@@ -4,33 +4,24 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var _compiler = require("../compiler");
9
-
10
8
  var _constants = require("../constants");
11
-
12
9
  var _obfuscator = _interopRequireDefault(require("../obfuscator"));
13
-
14
10
  var _order = require("../order");
15
-
16
11
  var _probability = require("../probability");
17
-
12
+ var _functionLength = require("../templates/functionLength");
13
+ var _globals = require("../templates/globals");
14
+ var _template = _interopRequireDefault(require("../templates/template"));
18
15
  var _traverse = require("../traverse");
19
-
20
16
  var _gen = require("../util/gen");
21
-
22
17
  var _identifiers = require("../util/identifiers");
23
-
24
18
  var _insert = require("../util/insert");
25
-
26
19
  var _integrity = _interopRequireDefault(require("./lock/integrity"));
27
-
28
20
  var _transform = _interopRequireDefault(require("./transform"));
29
-
30
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
31
-
32
- 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; }
33
-
21
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
22
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
23
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
24
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
34
25
  /**
35
26
  * Converts function to `new Function("..code..")` syntax as an alternative to `eval`. Eval is disabled in many environments.
36
27
  *
@@ -41,66 +32,98 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
41
32
  * `flatten` can attempt to make function reference-less. Recommended to have flatten enabled with RGF.
42
33
  */
43
34
  class RGF extends _transform.default {
44
- // Array of all the `new Function` calls
45
- // The name of the array holding all the `new Function` expressions
35
+ getFunctionLengthName(parents) {
36
+ if (!this.functionLengthName) {
37
+ this.functionLengthName = this.getPlaceholder();
38
+ }
39
+ return this.functionLengthName;
40
+ }
46
41
  constructor(o) {
47
42
  super(o, _order.ObfuscateOrder.RGF);
48
-
43
+ // Array of all the `new Function` calls
49
44
  _defineProperty(this, "arrayExpressionElements", void 0);
50
-
45
+ // The name of the array holding all the `new Function` expressions
51
46
  _defineProperty(this, "arrayExpressionName", void 0);
52
-
47
+ _defineProperty(this, "functionLengthName", void 0);
53
48
  this.arrayExpressionName = this.getPlaceholder() + "_rgf";
54
49
  this.arrayExpressionElements = [];
55
50
  }
56
-
57
51
  apply(tree) {
58
- super.apply(tree); // Only add the array if there were converted functions
52
+ super.apply(tree);
59
53
 
54
+ // Only add the array if there were converted functions
60
55
  if (this.arrayExpressionElements.length > 0) {
61
- (0, _insert.prepend)(tree, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)((0, _gen.Identifier)(this.arrayExpressionName), (0, _gen.ArrayExpression)(this.arrayExpressionElements))));
56
+ var _this$options$lock;
57
+ var variableDeclaration = (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)((0, _gen.Identifier)(this.arrayExpressionName), (0, _gen.ArrayExpression)(this.arrayExpressionElements)));
58
+ var nodes = [variableDeclaration];
59
+ if ((_this$options$lock = this.options.lock) !== null && _this$options$lock !== void 0 && _this$options$lock.tamperProtection) {
60
+ // The name of the variable flag if eval is safe to use
61
+ var tamperProtectionCheckName = this.getPlaceholder() + "_rgfEvalCheck";
62
+ variableDeclaration.declarations[0].init = (0, _gen.LogicalExpression)("&&", (0, _gen.Identifier)(tamperProtectionCheckName), {
63
+ ...variableDeclaration.declarations[0].init
64
+ });
65
+ nodes.unshift(...new _template.default(`
66
+ var ${tamperProtectionCheckName} = false;
67
+ eval(${this.jsConfuserVar(tamperProtectionCheckName)} + "=true");
68
+ if(!${tamperProtectionCheckName}) {
69
+ {countermeasures}
70
+ }
71
+ `).compile({
72
+ countermeasures: this.lockTransform.getCounterMeasuresCode(tree, [])
73
+ }));
74
+ }
75
+ (0, _insert.prepend)(tree, ...nodes);
62
76
  }
63
- }
64
77
 
78
+ // The function.length helper function must be placed last
79
+ if (this.functionLengthName) {
80
+ (0, _insert.prepend)(tree, _functionLength.FunctionLengthTemplate.single({
81
+ name: this.functionLengthName,
82
+ ObjectDefineProperty: this.createInitVariable(_globals.ObjectDefineProperty, [tree])
83
+ }));
84
+ }
85
+ }
65
86
  match(object, parents) {
66
- return (object.type === "FunctionDeclaration" || object.type === "FunctionExpression") && // Does not apply to Arrow functions
67
- !object.async && // Does not apply to async/generator functions
87
+ return (object.type === "FunctionDeclaration" || object.type === "FunctionExpression") &&
88
+ // Does not apply to Arrow functions
89
+ !object.async &&
90
+ // Does not apply to async/generator functions
68
91
  !object.generator;
69
92
  }
70
-
71
93
  transform(object, parents) {
72
- var _this$options$lock, _object$id;
73
-
94
+ var _this$options$lock2, _object$id;
74
95
  // Discard getter/setter methods
75
96
  if (parents[0].type === "Property" && parents[0].value === object) {
76
97
  if (parents[0].method || parents[0].kind === "get" || parents[0].kind === "set") {
77
98
  return;
78
99
  }
79
- } // Discard class methods
80
-
100
+ }
81
101
 
102
+ // Discard class methods
82
103
  if (parents[0].type === "MethodDefinition" && parents[0].value === object) {
83
104
  return;
84
- } // Avoid applying to the countermeasures function
85
-
105
+ }
86
106
 
87
- if (typeof ((_this$options$lock = this.options.lock) === null || _this$options$lock === void 0 ? void 0 : _this$options$lock.countermeasures) === "string") {
107
+ // Avoid applying to the countermeasures function
108
+ if (typeof ((_this$options$lock2 = this.options.lock) === null || _this$options$lock2 === void 0 ? void 0 : _this$options$lock2.countermeasures) === "string") {
88
109
  // function countermeasures(){...}
89
110
  if (object.type === "FunctionDeclaration" && object.id.type === "Identifier" && object.id.name === this.options.lock.countermeasures) {
90
111
  return;
91
- } // var countermeasures = function(){...}
92
-
112
+ }
93
113
 
114
+ // var countermeasures = function(){...}
94
115
  if (parents[0].type === "VariableDeclarator" && parents[0].init === object && parents[0].id.type === "Identifier" && parents[0].id.name === this.options.lock.countermeasures) {
95
116
  return;
96
117
  }
97
- } // Check user option
98
-
118
+ }
99
119
 
100
- if (!(0, _probability.ComputeProbabilityMap)(this.options.rgf, x => x, object === null || object === void 0 ? void 0 : (_object$id = object.id) === null || _object$id === void 0 ? void 0 : _object$id.name)) return; // Discard functions that use 'eval' function
120
+ // Check user option
121
+ if (!(0, _probability.ComputeProbabilityMap)(this.options.rgf, x => x, object === null || object === void 0 ? void 0 : (_object$id = object.id) === null || _object$id === void 0 ? void 0 : _object$id.name)) return;
101
122
 
102
- if (object.$requiresEval) return; // Check for 'this', 'arguments' (not allowed!)
123
+ // Discard functions that use 'eval' function
124
+ if (object.$requiresEval) return;
103
125
 
126
+ // Check for 'this', 'arguments' (not allowed!)
104
127
  var isIllegal = false;
105
128
  (0, _traverse.walk)(object, parents, (o, p) => {
106
129
  if (o.type === "ThisExpression" || o.type === "Super" || o.type === "Identifier" && o.name === "arguments") {
@@ -110,22 +133,20 @@ class RGF extends _transform.default {
110
133
  });
111
134
  if (isIllegal) return;
112
135
  return () => {
136
+ var _this$options$lock3;
113
137
  // Make sure function is 'reference-less'
114
138
  var definedMap = new Map();
115
139
  var isReferenceLess = true;
116
140
  var identifierPreventingTransformation;
117
141
  (0, _traverse.walk)(object, parents, (o, p) => {
118
- if (o.type === "Identifier" && !_constants.reservedIdentifiers.has(o.name) && !this.options.globalVariables.has(o.name)) {
142
+ if (o.type === "Identifier" && o.name !== this.arrayExpressionName && !_constants.reservedIdentifiers.has(o.name) && !this.options.globalVariables.has(o.name)) {
119
143
  var info = (0, _identifiers.getIdentifierInfo)(o, p);
120
-
121
144
  if (!info.spec.isReferenced) {
122
145
  return;
123
146
  }
124
-
125
147
  if (info.spec.isDefined) {
126
148
  // Add to defined map
127
149
  var definingContext = (0, _insert.getDefiningContext)(o, p);
128
-
129
150
  if (!definedMap.has(definingContext)) {
130
151
  definedMap.set(definingContext, new Set([o.name]));
131
152
  } else {
@@ -134,7 +155,6 @@ class RGF extends _transform.default {
134
155
  } else {
135
156
  // This approach is dirty and does not account for hoisted FunctionDeclarations
136
157
  var isDefinedAbove = false;
137
-
138
158
  for (var pNode of p) {
139
159
  if (definedMap.has(pNode)) {
140
160
  if (definedMap.get(pNode).has(o.name)) {
@@ -143,7 +163,6 @@ class RGF extends _transform.default {
143
163
  }
144
164
  }
145
165
  }
146
-
147
166
  if (!isDefinedAbove) {
148
167
  isReferenceLess = false;
149
168
  identifierPreventingTransformation = o.name;
@@ -151,36 +170,37 @@ class RGF extends _transform.default {
151
170
  }
152
171
  }
153
172
  }
154
- }); // This function is not 'reference-less', cannot be RGF'd
173
+ });
155
174
 
175
+ // This function is not 'reference-less', cannot be RGF'd
156
176
  if (!isReferenceLess) {
157
177
  if (object.id) {
158
178
  var _object$id2;
159
-
160
- this.log("".concat(object === null || object === void 0 ? void 0 : (_object$id2 = object.id) === null || _object$id2 === void 0 ? void 0 : _object$id2.name, "() cannot be transformed because of ").concat(identifierPreventingTransformation));
179
+ this.log(`${object === null || object === void 0 ? void 0 : (_object$id2 = object.id) === null || _object$id2 === void 0 ? void 0 : _object$id2.name}() cannot be transformed because of ${identifierPreventingTransformation}`);
161
180
  }
162
-
163
181
  return;
164
- } // Since `new Function` is completely isolated, create an entire new obfuscator and run remaining transformations.
182
+ }
183
+
184
+ // Since `new Function` is completely isolated, create an entire new obfuscator and run remaining transformations.
165
185
  // RGF runs early and needs completed code before converting to a string.
166
186
  // (^ the variables haven't been renamed yet)
167
-
168
-
169
- var obfuscator = new _obfuscator.default({ ...this.options,
187
+ var obfuscator = new _obfuscator.default({
188
+ ...this.options,
170
189
  stringEncoding: false,
171
190
  compact: true
172
191
  });
173
-
174
192
  if (obfuscator.options.lock) {
175
- delete obfuscator.options.lock.countermeasures; // Integrity will not recursively apply to RGF'd functions. This is intended.
193
+ obfuscator.options.lock = {
194
+ ...obfuscator.options.lock
195
+ };
196
+ delete obfuscator.options.lock.countermeasures;
176
197
 
198
+ // Integrity will not recursively apply to RGF'd functions. This is intended.
177
199
  var lockTransform = obfuscator.transforms["Lock"];
178
-
179
200
  if (lockTransform) {
180
201
  lockTransform.before = lockTransform.before.filter(beforeTransform => !(beforeTransform instanceof _integrity.default));
181
202
  }
182
203
  }
183
-
184
204
  var transforms = obfuscator.array.filter(x => x.priority > this.priority);
185
205
  var embeddedFunctionName = this.getPlaceholder();
186
206
  var embeddedFunction = {
@@ -191,41 +211,74 @@ class RGF extends _transform.default {
191
211
  async: false,
192
212
  generator: false
193
213
  };
214
+
215
+ // The new program will look like this
216
+ // new Function(`
217
+ // var rgf_array = this[0]
218
+ // function greet(message){
219
+ // console.log(message)
220
+ // }
221
+ // return greet.apply(this[1], arguments)
222
+ // `)
223
+ //
224
+ // And called like
225
+ // f.apply([ rgf_array, this ], arguments)
194
226
  var tree = {
195
227
  type: "Program",
196
- body: [embeddedFunction, (0, _gen.ReturnStatement)((0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(embeddedFunctionName), (0, _gen.Literal)("apply"), true), [(0, _gen.ThisExpression)(), (0, _gen.Identifier)("arguments")]))]
228
+ body: [(0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(this.arrayExpressionName, (0, _gen.MemberExpression)((0, _gen.ThisExpression)(), (0, _gen.Literal)(0)))), embeddedFunction, (0, _gen.ReturnStatement)((0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(embeddedFunctionName), (0, _gen.Literal)("apply"), true), [(0, _gen.MemberExpression)((0, _gen.ThisExpression)(), (0, _gen.Literal)(1)), (0, _gen.Identifier)("arguments")]))]
197
229
  };
198
230
  transforms.forEach(transform => {
199
231
  transform.apply(tree);
200
232
  });
201
- var toString = (0, _compiler.compileJsSync)(tree, obfuscator.options); // new Function(code)
233
+ var toString = (0, _compiler.compileJsSync)(tree, obfuscator.options);
234
+
235
+ // new Function(code)
236
+ var newFunctionExpression = (0, _gen.NewExpression)((0, _gen.Identifier)("Function"), [(0, _gen.Literal)(toString)]);
237
+ if ((_this$options$lock3 = this.options.lock) !== null && _this$options$lock3 !== void 0 && _this$options$lock3.tamperProtection) {
238
+ // If tamper protection is enabled, wrap the function in an eval
239
+ var randomName = this.getGenerator("randomized").generate();
240
+ newFunctionExpression = (0, _gen.CallExpression)((0, _gen.Identifier)("eval"), [(0, _gen.Literal)(`function ${randomName}(){ ${toString} } ${randomName}`)]);
241
+ }
202
242
 
203
- var newFunctionExpression = (0, _gen.NewExpression)((0, _gen.Identifier)("Function"), [(0, _gen.Literal)(toString)]); // The index where this function is placed in the array
243
+ // The index where this function is placed in the array
244
+ var newFunctionExpressionIndex = this.arrayExpressionElements.length;
204
245
 
205
- var newFunctionExpressionIndex = this.arrayExpressionElements.length; // Add it to the array
246
+ // Add it to the array
247
+ this.arrayExpressionElements.push(newFunctionExpression);
206
248
 
207
- this.arrayExpressionElements.push(newFunctionExpression); // The member expression to retrieve this function
249
+ // The member expression to retrieve this function
250
+ var memberExpression = (0, _gen.MemberExpression)((0, _gen.Identifier)(this.arrayExpressionName), (0, _gen.Literal)(newFunctionExpressionIndex), true);
251
+ var originalFunctionLength = (0, _insert.computeFunctionLength)(object.params);
252
+
253
+ // Replace based on type
208
254
 
209
- var memberExpression = (0, _gen.MemberExpression)((0, _gen.Identifier)(this.arrayExpressionName), (0, _gen.Literal)(newFunctionExpressionIndex), true); // Replace based on type
210
255
  // (1) Function Declaration:
211
256
  // - Replace body with call to new function
212
-
213
257
  if (object.type === "FunctionDeclaration") {
214
- object.body = (0, _gen.BlockStatement)([(0, _gen.ReturnStatement)((0, _gen.CallExpression)((0, _gen.MemberExpression)(memberExpression, (0, _gen.Literal)("apply"), true), [(0, _gen.ThisExpression)(), (0, _gen.Identifier)("arguments")]))]); // The parameters are no longer needed ('arguments' is used to capture them)
258
+ object.body = (0, _gen.BlockStatement)([(0, _gen.ReturnStatement)((0, _gen.CallExpression)((0, _gen.MemberExpression)(memberExpression, (0, _gen.Literal)("apply"), true), [(0, _gen.ArrayExpression)([(0, _gen.Identifier)(this.arrayExpressionName), (0, _gen.ThisExpression)()]), (0, _gen.Identifier)("arguments")]))]);
215
259
 
260
+ // The parameters are no longer needed ('arguments' is used to capture them)
216
261
  object.params = [];
217
- return;
218
- } // (2) Function Expression:
219
- // - Replace expression with member expression pointing to new function
220
262
 
263
+ // The function is no longer guaranteed to not have extraneous parameters passed in
264
+ object[_constants.predictableFunctionTag] = false;
265
+ if (this.options.preserveFunctionLength && originalFunctionLength !== 0) {
266
+ var body = parents[0];
267
+ body.splice(body.indexOf(object), 0, (0, _gen.ExpressionStatement)((0, _gen.CallExpression)((0, _gen.Identifier)(this.getFunctionLengthName(parents)), [(0, _gen.Identifier)(object.id.name), (0, _gen.Literal)(originalFunctionLength)])));
268
+ }
269
+ return;
270
+ }
221
271
 
272
+ // (2) Function Expression:
273
+ // - Replace expression with member expression pointing to new function
222
274
  if (object.type === "FunctionExpression") {
275
+ if (this.options.preserveFunctionLength && originalFunctionLength !== 0) {
276
+ memberExpression = (0, _gen.CallExpression)((0, _gen.Identifier)(this.getFunctionLengthName(parents)), [memberExpression, (0, _gen.Literal)(originalFunctionLength)]);
277
+ }
223
278
  this.replace(object, memberExpression);
224
279
  return;
225
280
  }
226
281
  };
227
282
  }
228
-
229
283
  }
230
-
231
284
  exports.default = RGF;
@@ -4,36 +4,25 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var _assert = require("assert");
9
-
10
8
  var _order = require("../order");
11
-
12
9
  var _probability = require("../probability");
13
-
14
10
  var _template = _interopRequireDefault(require("../templates/template"));
15
-
16
11
  var _gen = require("../util/gen");
17
-
18
12
  var _insert = require("../util/insert");
19
-
20
13
  var _random = require("../util/random");
21
-
22
14
  var _transform = _interopRequireDefault(require("./transform"));
23
-
24
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
-
26
- 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; }
27
-
15
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
17
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
18
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
28
19
  var Hash = function (s) {
29
20
  var a = 1,
30
- c = 0,
31
- h,
32
- o;
33
-
21
+ c = 0,
22
+ h,
23
+ o;
34
24
  if (s) {
35
25
  a = 0;
36
-
37
26
  for (h = s.length - 1; h >= 0; h--) {
38
27
  o = s.charCodeAt(h);
39
28
  a = (a << 6 & 268435455) + o + (o << 14);
@@ -41,72 +30,72 @@ var Hash = function (s) {
41
30
  a = c !== 0 ? a ^ c >> 21 : a;
42
31
  }
43
32
  }
44
-
45
33
  return ~~String(a).slice(0, 3);
46
34
  };
35
+ var HashTemplate = new _template.default(`
36
+ var {name} = function(arr) {
37
+ var s = arr.map(x=>x+"").join(''), a = 1, c = 0, h, o;
38
+ if (s) {
39
+ a = 0;
40
+ for (h = s.length - 1; h >= 0; h--) {
41
+ o = s.charCodeAt(h);
42
+ a = (a<<6&268435455) + o + (o<<14);
43
+ c = a & 266338304;
44
+ a = c!==0?a^c>>21:a;
45
+ }
46
+ }
47
+ return ~~String(a).slice(0, 3);
48
+ };`);
47
49
 
48
- var HashTemplate = (0, _template.default)("\n var {name} = function(arr) {\n var s = arr.map(x=>x+\"\").join(''), a = 1, c = 0, h, o;\n if (s) {\n a = 0;\n for (h = s.length - 1; h >= 0; h--) {\n o = s.charCodeAt(h);\n a = (a<<6&268435455) + o + (o<<14);\n c = a & 266338304;\n a = c!==0?a^c>>21:a;\n }\n }\n return ~~String(a).slice(0, 3);\n};");
49
50
  /**
50
51
  * Shuffles arrays initial order of elements.
51
52
  *
52
53
  * "Un-shuffles" the array at runtime.
53
54
  */
54
-
55
55
  class Shuffle extends _transform.default {
56
56
  constructor(o) {
57
57
  super(o, _order.ObfuscateOrder.Shuffle);
58
-
59
58
  _defineProperty(this, "hashName", void 0);
60
59
  }
61
-
62
60
  match(object, parents) {
63
- return object.type == "ArrayExpression" && !parents.find(x => x.$dispatcherSkip);
61
+ return object.type == "ArrayExpression" && !parents.find(x => x.$multiTransformSkip);
64
62
  }
65
-
66
63
  transform(object, parents) {
67
64
  return () => {
68
65
  if (object.elements.length < 3) {
69
66
  // Min: 4 elements
70
67
  return;
71
68
  }
72
-
73
69
  function isAllowed(e) {
74
70
  return e.type == "Literal" && {
75
71
  number: 1,
76
72
  boolean: 1,
77
73
  string: 1
78
74
  }[typeof e.value];
79
- } // Only arrays with only literals
80
-
75
+ }
81
76
 
77
+ // Only arrays with only literals
82
78
  var illegal = object.elements.find(x => !isAllowed(x));
83
-
84
79
  if (illegal) {
85
80
  return;
86
81
  }
87
-
88
82
  var mapped = object.elements.map(x => x.value);
89
83
  var mode = (0, _probability.ComputeProbabilityMap)(this.options.shuffle, x => x, mapped);
90
-
91
84
  if (mode) {
92
85
  var shift = (0, _random.getRandomInteger)(1, Math.min(60, object.elements.length * 6));
93
86
  var expr = (0, _gen.Literal)(shift);
94
87
  var name = this.getPlaceholder();
95
-
96
88
  if (mode == "hash") {
97
89
  var str = mapped.join("");
98
90
  shift = Hash(str);
99
-
100
91
  if (!this.hashName) {
101
92
  (0, _insert.prepend)(parents[parents.length - 1], HashTemplate.single({
102
93
  name: this.hashName = this.getPlaceholder()
103
94
  }));
104
95
  }
105
-
106
96
  for (var i = 0; i < shift; i++) {
107
97
  object.elements.push(object.elements.shift());
108
98
  }
109
-
110
99
  var shiftedHash = Hash(object.elements.map(x => x.value + "").join(""));
111
100
  expr = (0, _gen.BinaryExpression)("-", (0, _gen.CallExpression)((0, _gen.Identifier)(this.hashName), [(0, _gen.Identifier)(name)]), (0, _gen.Literal)(shiftedHash - shift));
112
101
  } else {
@@ -114,7 +103,6 @@ class Shuffle extends _transform.default {
114
103
  object.elements.push(object.elements.shift());
115
104
  }
116
105
  }
117
-
118
106
  var code = [];
119
107
  var iName = this.getPlaceholder();
120
108
  var inPlace = false;
@@ -122,13 +110,10 @@ class Shuffle extends _transform.default {
122
110
  var inPlaceBody;
123
111
  var inPlaceIndex;
124
112
  var varDeclarator = parents[0];
125
-
126
113
  if (varDeclarator.type == "VariableDeclarator") {
127
114
  var varDec = parents[2];
128
-
129
115
  if (varDec.type == "VariableDeclaration" && varDec.kind !== "const") {
130
116
  var body = parents[3];
131
-
132
117
  if (varDec.declarations.length == 1 && Array.isArray(body) && varDeclarator.id.type === "Identifier" && varDeclarator.init === object) {
133
118
  inPlaceIndex = body.indexOf(varDec);
134
119
  inPlaceBody = body;
@@ -137,28 +122,38 @@ class Shuffle extends _transform.default {
137
122
  }
138
123
  }
139
124
  }
140
-
141
125
  if (mode !== "hash") {
142
126
  var varPrefix = this.getPlaceholder();
143
- code.push((0, _template.default)("\n for ( var ".concat(varPrefix, "x = 16; ").concat(varPrefix, "x%4 === 0; ").concat(varPrefix, "x++) {\n var ").concat(varPrefix, "z = 0;\n ").concat(inPlace ? "".concat(inPlaceName, " = ").concat(name) : name, " = ").concat(name, ".concat((function(){\n ").concat(varPrefix, "z++;\n if(").concat(varPrefix, "z === 1){\n return [];\n }\n\n for( var ").concat(varPrefix, "i = ").concat((0, _random.getRandomInteger)(5, 105), "; ").concat(varPrefix, "i; ").concat(varPrefix, "i-- ){\n ").concat(name, ".unshift(").concat(name, ".pop());\n }\n return [];\n })());\n }\n ")).single());
127
+ code.push(new _template.default(`
128
+ for ( var ${varPrefix}x = 16; ${varPrefix}x%4 === 0; ${varPrefix}x++) {
129
+ var ${varPrefix}z = 0;
130
+ ${inPlace ? `${inPlaceName} = ${name}` : name} = ${name}.concat((function(){
131
+ ${varPrefix}z++;
132
+ if(${varPrefix}z === 1){
133
+ return [];
134
+ }
135
+
136
+ for( var ${varPrefix}i = ${(0, _random.getRandomInteger)(5, 105)}; ${varPrefix}i; ${varPrefix}i-- ){
137
+ ${name}.unshift(${name}.pop());
138
+ }
139
+ return [];
140
+ })());
141
+ }
142
+ `).single());
144
143
  }
145
-
146
- code.push((0, _gen.ForStatement)((0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(iName, expr)), (0, _gen.Identifier)(iName), (0, _gen.UpdateExpression)("--", (0, _gen.Identifier)(iName), false), [// ${name}.unshift(${name}.pop());
144
+ code.push((0, _gen.ForStatement)((0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(iName, expr)), (0, _gen.Identifier)(iName), (0, _gen.UpdateExpression)("--", (0, _gen.Identifier)(iName), false), [
145
+ // ${name}.unshift(${name}.pop());
147
146
  (0, _gen.ExpressionStatement)((0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(name), (0, _gen.Identifier)("unshift"), false), [(0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(name), (0, _gen.Identifier)("pop"), false), [])]))]));
148
-
149
147
  if (inPlace) {
150
148
  var varDeclarator = parents[0];
151
149
  (0, _assert.ok)(i != -1);
152
150
  inPlaceBody.splice(inPlaceIndex + 1, 0, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(name, (0, _gen.Identifier)(varDeclarator.id.name))), ...code);
153
151
  }
154
-
155
152
  if (!inPlace) {
156
153
  this.replace(object, (0, _gen.CallExpression)((0, _gen.FunctionExpression)([(0, _gen.Identifier)(name)], [...code, (0, _gen.ReturnStatement)((0, _gen.Identifier)(name))]), [(0, _insert.clone)(object)]));
157
154
  }
158
155
  }
159
156
  };
160
157
  }
161
-
162
158
  }
163
-
164
159
  exports.default = Shuffle;