js-confuser 1.7.3 → 2.0.0-alpha.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 (269) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +6 -4
  2. package/CHANGELOG.md +70 -0
  3. package/Migration.md +57 -0
  4. package/README.md +23 -929
  5. package/dist/constants.js +65 -14
  6. package/dist/index.js +108 -160
  7. package/dist/obfuscator.js +316 -118
  8. package/dist/options.js +1 -119
  9. package/dist/order.js +30 -30
  10. package/dist/presets.js +47 -45
  11. package/dist/probability.js +25 -32
  12. package/dist/templates/bufferToStringTemplate.js +9 -0
  13. package/dist/templates/deadCodeTemplates.js +9 -0
  14. package/dist/templates/getGlobalTemplate.js +19 -0
  15. package/dist/templates/integrityTemplate.js +30 -0
  16. package/dist/templates/setFunctionLengthTemplate.js +9 -0
  17. package/dist/templates/stringCompressionTemplate.js +10 -0
  18. package/dist/templates/tamperProtectionTemplates.js +21 -0
  19. package/dist/templates/template.js +199 -184
  20. package/dist/transforms/astScrambler.js +100 -0
  21. package/dist/transforms/calculator.js +70 -127
  22. package/dist/transforms/controlFlowFlattening.js +1182 -0
  23. package/dist/transforms/deadCode.js +62 -587
  24. package/dist/transforms/dispatcher.js +300 -313
  25. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +88 -189
  26. package/dist/transforms/extraction/objectExtraction.js +131 -215
  27. package/dist/transforms/finalizer.js +56 -59
  28. package/dist/transforms/flatten.js +275 -276
  29. package/dist/transforms/functionOutlining.js +230 -0
  30. package/dist/transforms/identifier/globalConcealing.js +214 -135
  31. package/dist/transforms/identifier/movedDeclarations.js +167 -91
  32. package/dist/transforms/identifier/renameVariables.js +239 -193
  33. package/dist/transforms/lock/integrity.js +61 -184
  34. package/dist/transforms/lock/lock.js +261 -387
  35. package/dist/transforms/minify.js +431 -436
  36. package/dist/transforms/opaquePredicates.js +65 -118
  37. package/dist/transforms/pack.js +160 -0
  38. package/dist/transforms/plugin.js +179 -0
  39. package/dist/transforms/preparation.js +261 -173
  40. package/dist/transforms/renameLabels.js +132 -56
  41. package/dist/transforms/rgf.js +140 -267
  42. package/dist/transforms/shuffle.js +52 -145
  43. package/dist/transforms/string/encoding.js +44 -175
  44. package/dist/transforms/string/stringCompression.js +79 -155
  45. package/dist/transforms/string/stringConcealing.js +189 -225
  46. package/dist/transforms/string/stringEncoding.js +32 -40
  47. package/dist/transforms/string/stringSplitting.js +54 -55
  48. package/dist/transforms/variableMasking.js +232 -0
  49. package/dist/utils/ControlObject.js +125 -0
  50. package/dist/utils/IntGen.js +46 -0
  51. package/dist/utils/NameGen.js +106 -0
  52. package/dist/utils/ast-utils.js +560 -0
  53. package/dist/utils/function-utils.js +56 -0
  54. package/dist/utils/gen-utils.js +48 -0
  55. package/dist/utils/node.js +77 -0
  56. package/dist/utils/object-utils.js +21 -0
  57. package/dist/utils/random-utils.js +91 -0
  58. package/dist/utils/static-utils.js +64 -0
  59. package/dist/validateOptions.js +122 -0
  60. package/index.d.ts +1 -17
  61. package/package.json +27 -22
  62. package/src/constants.ts +139 -82
  63. package/src/index.ts +70 -165
  64. package/src/obfuscationResult.ts +43 -0
  65. package/src/obfuscator.ts +328 -135
  66. package/src/options.ts +149 -658
  67. package/src/order.ts +14 -14
  68. package/src/presets.ts +39 -34
  69. package/src/probability.ts +21 -36
  70. package/src/templates/bufferToStringTemplate.ts +57 -0
  71. package/src/templates/deadCodeTemplates.ts +1185 -0
  72. package/src/templates/getGlobalTemplate.ts +72 -0
  73. package/src/templates/integrityTemplate.ts +69 -0
  74. package/src/templates/setFunctionLengthTemplate.ts +11 -0
  75. package/src/templates/stringCompressionTemplate.ts +42 -0
  76. package/src/templates/tamperProtectionTemplates.ts +116 -0
  77. package/src/templates/template.ts +149 -157
  78. package/src/transforms/astScrambler.ts +99 -0
  79. package/src/transforms/calculator.ts +96 -226
  80. package/src/transforms/controlFlowFlattening.ts +1594 -0
  81. package/src/transforms/deadCode.ts +85 -676
  82. package/src/transforms/dispatcher.ts +431 -640
  83. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +147 -295
  84. package/src/transforms/extraction/objectExtraction.ts +160 -333
  85. package/src/transforms/finalizer.ts +63 -64
  86. package/src/transforms/flatten.ts +439 -557
  87. package/src/transforms/functionOutlining.ts +225 -0
  88. package/src/transforms/identifier/globalConcealing.ts +255 -266
  89. package/src/transforms/identifier/movedDeclarations.ts +228 -142
  90. package/src/transforms/identifier/renameVariables.ts +250 -271
  91. package/src/transforms/lock/integrity.ts +85 -263
  92. package/src/transforms/lock/lock.ts +338 -579
  93. package/src/transforms/minify.ts +523 -663
  94. package/src/transforms/opaquePredicates.ts +90 -229
  95. package/src/transforms/pack.ts +195 -0
  96. package/src/transforms/plugin.ts +185 -0
  97. package/src/transforms/preparation.ts +337 -231
  98. package/src/transforms/renameLabels.ts +176 -77
  99. package/src/transforms/rgf.ts +293 -424
  100. package/src/transforms/shuffle.ts +80 -254
  101. package/src/transforms/string/encoding.ts +20 -126
  102. package/src/transforms/string/stringCompression.ts +117 -307
  103. package/src/transforms/string/stringConcealing.ts +254 -342
  104. package/src/transforms/string/stringEncoding.ts +28 -47
  105. package/src/transforms/string/stringSplitting.ts +61 -75
  106. package/src/transforms/variableMasking.ts +257 -0
  107. package/src/utils/ControlObject.ts +141 -0
  108. package/src/utils/IntGen.ts +33 -0
  109. package/src/utils/NameGen.ts +106 -0
  110. package/src/utils/ast-utils.ts +667 -0
  111. package/src/utils/function-utils.ts +50 -0
  112. package/src/utils/gen-utils.ts +48 -0
  113. package/src/utils/node.ts +78 -0
  114. package/src/utils/object-utils.ts +21 -0
  115. package/src/utils/random-utils.ts +79 -0
  116. package/src/utils/static-utils.ts +66 -0
  117. package/src/validateOptions.ts +256 -0
  118. package/tsconfig.json +13 -8
  119. package/babel.config.js +0 -12
  120. package/dev.js +0 -8
  121. package/dist/compiler.js +0 -34
  122. package/dist/parser.js +0 -59
  123. package/dist/precedence.js +0 -66
  124. package/dist/templates/bufferToString.js +0 -129
  125. package/dist/templates/core.js +0 -35
  126. package/dist/templates/crash.js +0 -28
  127. package/dist/templates/es5.js +0 -137
  128. package/dist/templates/functionLength.js +0 -34
  129. package/dist/templates/globals.js +0 -9
  130. package/dist/transforms/antiTooling.js +0 -88
  131. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +0 -1287
  132. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +0 -131
  133. package/dist/transforms/es5/antiClass.js +0 -164
  134. package/dist/transforms/es5/antiDestructuring.js +0 -193
  135. package/dist/transforms/es5/antiES6Object.js +0 -185
  136. package/dist/transforms/es5/antiSpreadOperator.js +0 -35
  137. package/dist/transforms/es5/antiTemplate.js +0 -66
  138. package/dist/transforms/es5/es5.js +0 -123
  139. package/dist/transforms/extraction/classExtraction.js +0 -83
  140. package/dist/transforms/identifier/globalAnalysis.js +0 -83
  141. package/dist/transforms/identifier/variableAnalysis.js +0 -104
  142. package/dist/transforms/lock/antiDebug.js +0 -76
  143. package/dist/transforms/stack.js +0 -349
  144. package/dist/transforms/transform.js +0 -372
  145. package/dist/traverse.js +0 -110
  146. package/dist/util/compare.js +0 -145
  147. package/dist/util/gen.js +0 -564
  148. package/dist/util/guard.js +0 -14
  149. package/dist/util/identifiers.js +0 -355
  150. package/dist/util/insert.js +0 -362
  151. package/dist/util/math.js +0 -19
  152. package/dist/util/object.js +0 -40
  153. package/dist/util/random.js +0 -156
  154. package/dist/util/scope.js +0 -20
  155. package/docs/ControlFlowFlattening.md +0 -595
  156. package/docs/Countermeasures.md +0 -70
  157. package/docs/ES5.md +0 -197
  158. package/docs/Integrity.md +0 -82
  159. package/docs/RGF.md +0 -424
  160. package/docs/RenameVariables.md +0 -116
  161. package/docs/TamperProtection.md +0 -100
  162. package/docs/Template.md +0 -117
  163. package/samples/example.js +0 -15
  164. package/samples/high.js +0 -1
  165. package/samples/input.js +0 -3
  166. package/samples/javascriptobfuscator.com.js +0 -8
  167. package/samples/jscrambler_advanced.js +0 -1894
  168. package/samples/jscrambler_light.js +0 -1134
  169. package/samples/low.js +0 -1
  170. package/samples/medium.js +0 -1
  171. package/samples/obfuscator.io.js +0 -1686
  172. package/samples/preemptive.com.js +0 -16
  173. package/src/compiler.ts +0 -35
  174. package/src/parser.ts +0 -49
  175. package/src/precedence.ts +0 -61
  176. package/src/templates/bufferToString.ts +0 -136
  177. package/src/templates/core.ts +0 -29
  178. package/src/templates/crash.ts +0 -23
  179. package/src/templates/es5.ts +0 -131
  180. package/src/templates/functionLength.ts +0 -32
  181. package/src/templates/globals.ts +0 -3
  182. package/src/transforms/antiTooling.ts +0 -102
  183. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +0 -2153
  184. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +0 -179
  185. package/src/transforms/es5/antiClass.ts +0 -276
  186. package/src/transforms/es5/antiDestructuring.ts +0 -294
  187. package/src/transforms/es5/antiES6Object.ts +0 -267
  188. package/src/transforms/es5/antiSpreadOperator.ts +0 -56
  189. package/src/transforms/es5/antiTemplate.ts +0 -98
  190. package/src/transforms/es5/es5.ts +0 -149
  191. package/src/transforms/extraction/classExtraction.ts +0 -168
  192. package/src/transforms/identifier/globalAnalysis.ts +0 -102
  193. package/src/transforms/identifier/variableAnalysis.ts +0 -118
  194. package/src/transforms/lock/antiDebug.ts +0 -112
  195. package/src/transforms/stack.ts +0 -557
  196. package/src/transforms/transform.ts +0 -441
  197. package/src/traverse.ts +0 -120
  198. package/src/types.ts +0 -133
  199. package/src/util/compare.ts +0 -181
  200. package/src/util/gen.ts +0 -651
  201. package/src/util/guard.ts +0 -17
  202. package/src/util/identifiers.ts +0 -494
  203. package/src/util/insert.ts +0 -419
  204. package/src/util/math.ts +0 -15
  205. package/src/util/object.ts +0 -39
  206. package/src/util/random.ts +0 -221
  207. package/src/util/scope.ts +0 -21
  208. package/test/code/Cash.src.js +0 -1011
  209. package/test/code/Cash.test.ts +0 -132
  210. package/test/code/Dynamic.src.js +0 -118
  211. package/test/code/Dynamic.test.ts +0 -49
  212. package/test/code/ES6.src.js +0 -235
  213. package/test/code/ES6.test.ts +0 -42
  214. package/test/code/NewFeatures.test.ts +0 -19
  215. package/test/code/StrictMode.src.js +0 -65
  216. package/test/code/StrictMode.test.js +0 -37
  217. package/test/compare.test.ts +0 -104
  218. package/test/index.test.ts +0 -249
  219. package/test/options.test.ts +0 -150
  220. package/test/presets.test.ts +0 -22
  221. package/test/probability.test.ts +0 -44
  222. package/test/templates/template.test.ts +0 -224
  223. package/test/transforms/antiTooling.test.ts +0 -52
  224. package/test/transforms/calculator.test.ts +0 -78
  225. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +0 -1274
  226. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +0 -192
  227. package/test/transforms/deadCode.test.ts +0 -85
  228. package/test/transforms/dispatcher.test.ts +0 -457
  229. package/test/transforms/es5/antiClass.test.ts +0 -427
  230. package/test/transforms/es5/antiDestructuring.test.ts +0 -157
  231. package/test/transforms/es5/antiES6Object.test.ts +0 -245
  232. package/test/transforms/es5/antiTemplate.test.ts +0 -116
  233. package/test/transforms/es5/es5.test.ts +0 -110
  234. package/test/transforms/extraction/classExtraction.test.ts +0 -86
  235. package/test/transforms/extraction/duplicateLiteralsRemoval.test.ts +0 -200
  236. package/test/transforms/extraction/objectExtraction.test.ts +0 -491
  237. package/test/transforms/flatten.test.ts +0 -721
  238. package/test/transforms/hexadecimalNumbers.test.ts +0 -62
  239. package/test/transforms/identifier/globalConcealing.test.ts +0 -142
  240. package/test/transforms/identifier/movedDeclarations.test.ts +0 -275
  241. package/test/transforms/identifier/renameVariables.test.ts +0 -695
  242. package/test/transforms/lock/antiDebug.test.ts +0 -66
  243. package/test/transforms/lock/browserLock.test.ts +0 -129
  244. package/test/transforms/lock/countermeasures.test.ts +0 -100
  245. package/test/transforms/lock/integrity.test.ts +0 -161
  246. package/test/transforms/lock/lock.test.ts +0 -204
  247. package/test/transforms/lock/osLock.test.ts +0 -312
  248. package/test/transforms/lock/selfDefending.test.ts +0 -68
  249. package/test/transforms/lock/tamperProtection.test.ts +0 -336
  250. package/test/transforms/minify.test.ts +0 -575
  251. package/test/transforms/opaquePredicates.test.ts +0 -43
  252. package/test/transforms/preparation.test.ts +0 -157
  253. package/test/transforms/renameLabels.test.ts +0 -95
  254. package/test/transforms/rgf.test.ts +0 -378
  255. package/test/transforms/shuffle.test.ts +0 -135
  256. package/test/transforms/stack.test.ts +0 -573
  257. package/test/transforms/string/stringCompression.test.ts +0 -120
  258. package/test/transforms/string/stringConcealing.test.ts +0 -299
  259. package/test/transforms/string/stringEncoding.test.ts +0 -95
  260. package/test/transforms/string/stringSplitting.test.ts +0 -135
  261. package/test/transforms/transform.test.ts +0 -66
  262. package/test/traverse.test.ts +0 -139
  263. package/test/util/compare.test.ts +0 -34
  264. package/test/util/gen.test.ts +0 -121
  265. package/test/util/identifiers.test.ts +0 -253
  266. package/test/util/insert.test.ts +0 -142
  267. package/test/util/math.test.ts +0 -5
  268. package/test/util/random.test.ts +0 -71
  269. /package/dist/{types.js → obfuscationResult.js} +0 -0
@@ -1,311 +1,310 @@
1
1
  "use strict";
2
2
 
3
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
3
4
  Object.defineProperty(exports, "__esModule", {
4
5
  value: true
5
6
  });
6
- exports.default = void 0;
7
- var _assert = require("assert");
8
- var _constants = require("../constants");
7
+ exports["default"] = void 0;
8
+ var t = _interopRequireWildcard(require("@babel/types"));
9
+ var _astUtils = require("../utils/ast-utils");
10
+ var _probability = require("../probability");
9
11
  var _order = require("../order");
10
- var _traverse = require("../traverse");
11
- var _gen = require("../util/gen");
12
- var _identifiers = require("../util/identifiers");
13
- var _insert = require("../util/insert");
14
- var _random = require("../util/random");
15
- var _transform = _interopRequireDefault(require("./transform"));
16
- var _functionLength = require("../templates/functionLength");
17
- var _globals = require("../templates/globals");
18
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
19
- 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; }
20
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
21
- 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); }
22
- /**
23
- * Flatten takes functions and isolates them from their original scope, and brings it to the top level of the program.
24
- *
25
- * An additional `flatObject` parameter is passed in, giving access to the original scoped variables.
26
- *
27
- * The `flatObject` uses `get` and `set` properties to allow easy an AST transformation:
28
- *
29
- * ```js
30
- * // Input
31
- * function myFunction(myParam){
32
- * modified = true;
33
- * if(reference) {
34
- *
35
- * }
36
- * ...
37
- * console.log(myParam);
38
- * }
39
- *
40
- * // Output
41
- * function myFunction_flat([myParam], flatObject){
42
- * flatObject["set_modified"] = true;
43
- * if(flatObject["get_reference"]) {
44
- *
45
- * }
46
- * ...
47
- * console.log(myParam)
48
- * }
49
- *
50
- * function myFunction(){
51
- * var flatObject = {
52
- * set set_modified(v) { modified = v }
53
- * get get_reference() { return reference }
54
- * }
55
- * return myFunction_flat([...arguments], flatObject)
56
- * }
57
- * ```
58
- *
59
- * Flatten is used to make functions eligible for the RGF transformation.
60
- *
61
- * - `myFunction_flat` is now eligible because it does not rely on outside scoped variables
62
- */
63
- class Flatten extends _transform.default {
64
- constructor(o) {
65
- super(o, _order.ObfuscateOrder.Flatten);
66
- _defineProperty(this, "isDebug", false);
67
- _defineProperty(this, "definedNames", void 0);
68
- // Array of FunctionDeclaration nodes
69
- _defineProperty(this, "flattenedFns", void 0);
70
- _defineProperty(this, "gen", void 0);
71
- _defineProperty(this, "functionLengthName", void 0);
72
- this.definedNames = new Map();
73
- this.flattenedFns = [];
74
- this.gen = this.getGenerator("mangled");
75
- if (this.isDebug) {
76
- console.warn("Flatten debug mode");
12
+ var _constants = require("../constants");
13
+ var _functionUtils = require("../utils/function-utils");
14
+ var _assert = require("assert");
15
+ var _NameGen = require("../utils/NameGen");
16
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
17
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
18
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
19
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
20
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
21
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
22
+ function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
23
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
24
+ function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
25
+ function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
26
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
27
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
28
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
29
+ var _default = exports["default"] = function _default(_ref) {
30
+ var Plugin = _ref.Plugin;
31
+ var me = Plugin(_order.Order.Flatten, {
32
+ changeData: {
33
+ functions: 0
77
34
  }
78
- }
79
- apply(tree) {
80
- super.apply(tree);
81
- if (this.flattenedFns.length) {
82
- (0, _insert.prepend)(tree, ...this.flattenedFns);
35
+ });
36
+ var isDebug = false;
37
+ function flattenFunction(fnPath) {
38
+ // Skip if already processed
39
+ if (me.isSkipped(fnPath)) return;
40
+
41
+ // Don't apply to generator functions
42
+ if (fnPath.node.generator) return;
43
+
44
+ // Skip getter/setter methods
45
+ if (fnPath.isObjectMethod() || fnPath.isClassMethod()) {
46
+ if (fnPath.node.kind !== "method") return;
83
47
  }
84
- }
85
- match(object, parents) {
86
- return (object.type == "FunctionDeclaration" || object.type === "FunctionExpression") && object.body.type == "BlockStatement" && !object.$requiresEval && !object.generator && !object.params.find(x => x.type !== "Identifier");
87
- }
88
- transform(object, parents) {
89
- return () => {
90
- var _object$id, _parents$, _parents$0$id, _parents$0$id2, _parents$2, _parents$3;
91
- if (parents[0]) {
92
- // Don't change class methods
93
- if (parents[0].type === "MethodDefinition" && parents[0].value === object) {
94
- return;
95
- }
96
48
 
97
- // Don't change getter/setter methods
98
- if (parents[0].type === "Property" && parents[0].value === object && (parents[0].kind !== "init" || parents[0].method)) {
99
- return;
100
- }
101
- }
102
- (0, _assert.ok)(object.type === "FunctionDeclaration" || object.type === "FunctionExpression");
49
+ // Do not apply to arrow functions
50
+ if (t.isArrowFunctionExpression(fnPath.node)) return;
51
+ if (!t.isBlockStatement(fnPath.node.body)) return;
103
52
 
104
- // The name is purely for debugging purposes
105
- var currentFnName = object.type === "FunctionDeclaration" ? (_object$id = object.id) === null || _object$id === void 0 ? void 0 : _object$id.name : ((_parents$ = parents[0]) === null || _parents$ === void 0 ? void 0 : _parents$.type) === "VariableDeclarator" && ((_parents$0$id = parents[0].id) === null || _parents$0$id === void 0 ? void 0 : _parents$0$id.type) === "Identifier" && ((_parents$0$id2 = parents[0].id) === null || _parents$0$id2 === void 0 ? void 0 : _parents$0$id2.name);
106
- if (((_parents$2 = parents[0]) === null || _parents$2 === void 0 ? void 0 : _parents$2.type) === "Property" && (_parents$3 = parents[0]) !== null && _parents$3 !== void 0 && _parents$3.key) {
107
- var _parents$4, _parents$4$key;
108
- currentFnName = currentFnName || String((_parents$4 = parents[0]) === null || _parents$4 === void 0 ? void 0 : (_parents$4$key = _parents$4.key) === null || _parents$4$key === void 0 ? void 0 : _parents$4$key.name);
109
- }
110
- if (!currentFnName) currentFnName = "unnamed";
111
- var definedMap = new Map();
112
- var illegal = new Set();
113
- var isIllegal = false;
114
- var identifierNodes = [];
115
- (0, _traverse.walk)(object, parents, (o, p) => {
116
- if (o.type === "Identifier" && o.name === "arguments" || o.type === "UnaryExpression" && o.operator === "delete" || o.type == "ThisExpression" || o.type == "Super" || o.type == "MetaProperty") {
117
- isIllegal = true;
118
- return "EXIT";
119
- }
120
- if (o.type == "Identifier" && o !== object.id && !this.options.globalVariables.has(o.name) && !_constants.reservedIdentifiers.has(o.name)) {
121
- var info = (0, _identifiers.getIdentifierInfo)(o, p);
122
- if (!info.spec.isReferenced) {
123
- return;
124
- }
125
- if (info.spec.isExported || o.name.startsWith(_constants.noRenameVariablePrefix)) {
126
- illegal.add(o.name);
53
+ // Skip if marked as unsafe
54
+ if (fnPath.node[_constants.UNSAFE]) return;
55
+ var program = fnPath.findParent(function (p) {
56
+ return p.isProgram();
57
+ });
58
+ var functionName = (0, _astUtils.getFunctionName)(fnPath);
59
+ if (!t.isValidIdentifier(functionName, true)) {
60
+ functionName = "anonymous";
61
+ }
62
+ if (!(0, _probability.computeProbabilityMap)(me.options.flatten, functionName)) {
63
+ return;
64
+ }
65
+ var strictMode = fnPath.find(function (path) {
66
+ return (0, _astUtils.isStrictMode)(path);
67
+ });
68
+ if (strictMode === fnPath) return;
69
+ me.log("Transforming", functionName);
70
+ var flatObjectName = "".concat(me.getPlaceholder(), "_flat_object");
71
+ var newFnName = "".concat(me.getPlaceholder(), "_flat_").concat(functionName);
72
+ var nameGen = new _NameGen.NameGen(me.options.identifierGenerator);
73
+ function generateProp(originalName, type) {
74
+ var newPropertyName;
75
+ do {
76
+ newPropertyName = isDebug ? type + "_" + originalName : nameGen.generate();
77
+ } while (allPropertyNames.has(newPropertyName));
78
+ allPropertyNames.add(newPropertyName);
79
+ return newPropertyName;
80
+ }
81
+ var standardProps = new Map();
82
+ var setterPropsNeeded = new Set();
83
+ var typeofProps = new Map();
84
+ var functionCallProps = new Map();
85
+ var allPropertyNames = new Set();
86
+ var identifierPaths = [];
87
+
88
+ // Traverse function to identify variables to be replaced with flat object properties
89
+ fnPath.traverse({
90
+ Identifier: {
91
+ exit: function exit(identifierPath) {
92
+ if (!(0, _astUtils.isVariableIdentifier)(identifierPath)) return;
93
+ if (identifierPath.isBindingIdentifier() && (0, _astUtils.isDefiningIdentifier)(identifierPath)) return;
94
+ if ((0, _functionUtils.isVariableFunctionIdentifier)(identifierPath)) return;
95
+ if (identifierPath.node[_constants.UNSAFE]) return;
96
+ var identifierName = identifierPath.node.name;
97
+ if (identifierName === "arguments") return;
98
+ var binding = identifierPath.scope.getBinding(identifierName);
99
+ if (!binding) {
127
100
  return;
128
101
  }
129
- if (info.spec.isDefined) {
130
- var definingContext = (0, _insert.getDefiningContext)(o, p);
131
- if (!definedMap.has(definingContext)) {
132
- definedMap.set(definingContext, new Set([o.name]));
133
- } else {
134
- definedMap.get(definingContext).add(o.name);
102
+ var definedLocal = identifierPath.scope;
103
+ do {
104
+ if (definedLocal.hasOwnBinding(identifierName)) return;
105
+ if (definedLocal === fnPath.scope) break;
106
+ definedLocal = definedLocal.parent;
107
+ if (definedLocal === program.scope) (0, _assert.ok)(functionName + ":" + identifierName);
108
+ } while (definedLocal);
109
+ var cursor = fnPath.scope.parent;
110
+ var isOutsideVariable = false;
111
+ do {
112
+ if (cursor.hasBinding(identifierName)) {
113
+ isOutsideVariable = true;
114
+ break;
135
115
  }
116
+ cursor = cursor.parent;
117
+ } while (cursor);
118
+ if (!isOutsideVariable) {
136
119
  return;
137
120
  }
138
- var isDefined = p.find(x => definedMap.has(x) && definedMap.get(x).has(o.name));
139
- if (!isDefined) {
140
- identifierNodes.push([o, p, info]);
141
- }
121
+ identifierPaths.push(identifierPath);
142
122
  }
143
- if (o.type == "TryStatement") {
144
- isIllegal = true;
145
- return "EXIT";
146
- }
147
- });
148
- if (isIllegal) {
149
- return;
150
123
  }
151
- if (illegal.size) {
152
- return;
153
- }
154
- var newFnName = this.getPlaceholder() + "_flat_" + currentFnName + _constants.predictableFunctionTag;
155
- var flatObjectName = this.getPlaceholder() + "_flat_object";
156
- const getFlatObjectMember = propertyName => {
157
- return (0, _gen.MemberExpression)((0, _gen.Identifier)(flatObjectName), (0, _gen.Literal)(propertyName), true);
158
- };
159
- var getterPropNames = Object.create(null);
160
- var setterPropNames = Object.create(null);
161
- var typeofPropNames = Object.create(null);
162
- var callPropNames = Object.create(null);
163
- for (var [o, p, info] of identifierNodes) {
164
- var identifierName = o.name;
165
- if (p.find(x => definedMap.has(x) && definedMap.get(x).has(identifierName))) continue;
166
- (0, _assert.ok)(!info.spec.isDefined);
167
- var type = info.spec.isModified ? "setter" : "getter";
168
- switch (type) {
169
- case "setter":
170
- var setterPropName = setterPropNames[identifierName];
171
- if (typeof setterPropName === "undefined") {
172
- // No getter function made yet, make it (Try to re-use getter name if available)
173
- setterPropName = getterPropNames[identifierName] || (this.isDebug ? "set_" + identifierName : this.gen.generate());
174
- setterPropNames[identifierName] = setterPropName;
175
- }
176
-
177
- // If an update expression, ensure a getter function is also available. Ex: a++
178
- if (p[0].type === "UpdateExpression") {
179
- getterPropNames[identifierName] = setterPropName;
180
- } else {
181
- // If assignment on member expression, ensure a getter function is also available: Ex. myObject.property = ...
182
- var assignmentIndex = p.findIndex(x => x.type === "AssignmentExpression");
183
- if (assignmentIndex !== -1 && p[assignmentIndex].left.type !== "Identifier") {
184
- getterPropNames[identifierName] = setterPropName;
185
- }
186
- }
187
-
188
- // calls flatObject.set_identifier_value(newValue)
189
- this.replace(o, getFlatObjectMember(setterPropName));
190
- break;
191
- case "getter":
192
- var getterPropName = getterPropNames[identifierName];
193
- if (typeof getterPropName === "undefined") {
194
- // No getter function made yet, make it (Try to re-use setter name if available)
195
- getterPropName = setterPropNames[identifierName] || (this.isDebug ? "get_" + identifierName : this.gen.generate());
196
- getterPropNames[identifierName] = getterPropName;
197
- }
124
+ });
125
+ me.log("Function ".concat(functionName), "requires", Array.from(new Set(identifierPaths.map(function (x) {
126
+ return x.node.name;
127
+ }))));
128
+ for (var _i = 0, _identifierPaths = identifierPaths; _i < _identifierPaths.length; _i++) {
129
+ var identifierPath = _identifierPaths[_i];
130
+ var identifierName = identifierPath.node.name;
131
+ if (typeof identifierName !== "string") continue;
132
+ var isTypeof = identifierPath.parentPath.isUnaryExpression({
133
+ operator: "typeof"
134
+ });
135
+ var isFunctionCall = identifierPath.parentPath.isCallExpression() && identifierPath.parentPath.node.callee === identifierPath.node;
136
+ if (isTypeof) {
137
+ var typeofProp = typeofProps.get(identifierName);
138
+ if (!typeofProp) {
139
+ typeofProp = generateProp(identifierName, "typeof");
140
+ typeofProps.set(identifierName, typeofProp);
141
+ }
142
+ (0, _astUtils.ensureComputedExpression)(identifierPath.parentPath);
143
+ identifierPath.parentPath.replaceWith(t.memberExpression(t.identifier(flatObjectName), t.stringLiteral(typeofProp), true))[0].skip();
144
+ } else if (isFunctionCall) {
145
+ var functionCallProp = functionCallProps.get(identifierName);
146
+ if (!functionCallProp) {
147
+ functionCallProp = generateProp(identifierName, "call");
148
+ functionCallProps.set(identifierName, functionCallProp);
149
+ }
150
+ (0, _astUtils.ensureComputedExpression)(identifierPath);
198
151
 
199
- // Typeof expression check
200
- if (p[0].type === "UnaryExpression" && p[0].operator === "typeof" && p[0].argument === o) {
201
- var typeofPropName = typeofPropNames[identifierName];
202
- if (typeof typeofPropName === "undefined") {
203
- // No typeof getter function made yet, make it (Don't re-use getter/setter names)
204
- typeofPropName = this.isDebug ? "get_typeof_" + identifierName : this.gen.generate();
205
- typeofPropNames[identifierName] = typeofPropName;
206
- }
152
+ // Replace identifier with a reference to the flat object property
153
+ identifierPath.replaceWith(t.memberExpression(t.identifier(flatObjectName), t.stringLiteral(functionCallProp), true))[0].skip();
154
+ } else {
155
+ var standardProp = standardProps.get(identifierName);
156
+ if (!standardProp) {
157
+ standardProp = generateProp(identifierName, "standard");
158
+ standardProps.set(identifierName, standardProp);
159
+ }
160
+ if (!setterPropsNeeded.has(identifierName)) {
161
+ // Only provide 'set' method if the variable is modified
162
+ var isModification = (0, _astUtils.isModifiedIdentifier)(identifierPath);
163
+ if (isModification) {
164
+ setterPropsNeeded.add(identifierName);
165
+ }
166
+ }
167
+ (0, _astUtils.ensureComputedExpression)(identifierPath);
207
168
 
208
- // Replace the entire unary expression not just the identifier node
209
- // calls flatObject.get_typeof_identifier()
210
- this.replace(p[0], getFlatObjectMember(typeofPropName));
211
- break;
212
- }
169
+ // Replace identifier with a reference to the flat object property
170
+ identifierPath.replaceWith(t.memberExpression(t.identifier(flatObjectName), t.stringLiteral(standardProp), true))[0].skip();
171
+ }
172
+ }
213
173
 
214
- // Bound call-expression check
215
- if (p[0].type === "CallExpression" && p[0].callee === o) {
216
- var callPropName = callPropNames[identifierName];
217
- if (typeof callPropName === "undefined") {
218
- callPropName = this.isDebug ? "call_" + identifierName : this.gen.generate();
219
- callPropNames[identifierName] = callPropName;
220
- }
174
+ // for (const prop of [...typeofProps.keys(), ...functionCallProps.keys()]) {
175
+ // if (!standardProps.has(prop)) {
176
+ // standardProps.set(prop, generateProp());
177
+ // }
178
+ // }
221
179
 
222
- // Replace the entire call expression not just the identifier node
223
- // calls flatObject.call_identifier(...arguments)
224
- this.replace(p[0], (0, _gen.CallExpression)(getFlatObjectMember(callPropName), p[0].arguments));
225
- break;
226
- }
180
+ var flatObjectProperties = [];
181
+ var _iterator = _createForOfIteratorHelper(standardProps),
182
+ _step;
183
+ try {
184
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
185
+ var entry = _step.value;
186
+ var _entry = entry,
187
+ _entry2 = _slicedToArray(_entry, 2),
188
+ _identifierName = _entry2[0],
189
+ objectProp = _entry2[1];
190
+ flatObjectProperties.push(me.skip(t.objectMethod("get", t.stringLiteral(objectProp), [], t.blockStatement([t.returnStatement(t.identifier(_identifierName))]), false, false, false)));
227
191
 
228
- // calls flatObject.get_identifier_value()
229
- this.replace(o, getFlatObjectMember(getterPropName));
230
- break;
192
+ // Not all properties need a setter
193
+ if (setterPropsNeeded.has(_identifierName)) {
194
+ var valueArgName = me.getPlaceholder() + "_value";
195
+ flatObjectProperties.push(me.skip(t.objectMethod("set", t.stringLiteral(objectProp), [t.identifier(valueArgName)], t.blockStatement([t.expressionStatement(t.assignmentExpression("=", t.identifier(_identifierName), t.identifier(valueArgName)))]), false, false, false)));
231
196
  }
232
197
  }
198
+ } catch (err) {
199
+ _iterator.e(err);
200
+ } finally {
201
+ _iterator.f();
202
+ }
203
+ var _iterator2 = _createForOfIteratorHelper(typeofProps),
204
+ _step2;
205
+ try {
206
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
207
+ var _entry3 = _step2.value;
208
+ var _entry4 = _slicedToArray(_entry3, 2),
209
+ _identifierName2 = _entry4[0],
210
+ _objectProp = _entry4[1];
211
+ flatObjectProperties.push(me.skip(t.objectMethod("get", t.stringLiteral(_objectProp), [], t.blockStatement([t.returnStatement(t.unaryExpression("typeof", t.identifier(_identifierName2)))]), false, false, false)));
212
+ }
213
+ } catch (err) {
214
+ _iterator2.e(err);
215
+ } finally {
216
+ _iterator2.f();
217
+ }
218
+ var _iterator3 = _createForOfIteratorHelper(functionCallProps),
219
+ _step3;
220
+ try {
221
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
222
+ var _entry5 = _step3.value;
223
+ var _entry6 = _slicedToArray(_entry5, 2),
224
+ _identifierName3 = _entry6[0],
225
+ _objectProp2 = _entry6[1];
226
+ flatObjectProperties.push(me.skip(t.objectMethod("method", t.stringLiteral(_objectProp2), [t.restElement(t.identifier("args"))], t.blockStatement([t.returnStatement(t.callExpression(t.identifier(_identifierName3), [t.spreadElement(t.identifier("args"))]))]), false, false, false)));
227
+ }
233
228
 
234
- // Create the getter and setter functions
235
- var flatObjectProperties = [];
229
+ // Create the new flattened function
230
+ } catch (err) {
231
+ _iterator3.e(err);
232
+ } finally {
233
+ _iterator3.f();
234
+ }
235
+ var flattenedFunctionDeclaration = t.functionDeclaration(t.identifier(newFnName), [t.arrayPattern(_toConsumableArray(fnPath.node.params)), t.identifier(flatObjectName)], t.blockStatement(_toConsumableArray(fnPath.node.body.body).concat()), false, fnPath.node.async);
236
236
 
237
- // Getter functions
238
- for (var identifierName in getterPropNames) {
239
- var getterPropName = getterPropNames[identifierName];
240
- flatObjectProperties.push((0, _gen.Property)((0, _gen.Literal)(getterPropName), (0, _gen.FunctionExpression)([], [(0, _gen.ReturnStatement)((0, _gen.Identifier)(identifierName))]), true, "get"));
241
- }
237
+ // Create the flat object variable declaration
238
+ var flatObjectDeclaration = t.variableDeclaration("var", [t.variableDeclarator(t.identifier(flatObjectName), t.objectExpression(flatObjectProperties))]);
239
+ var argName = me.getPlaceholder() + "_args";
242
240
 
243
- // Get typeof functions
244
- for (var identifierName in typeofPropNames) {
245
- var typeofPropName = typeofPropNames[identifierName];
246
- flatObjectProperties.push((0, _gen.Property)((0, _gen.Literal)(typeofPropName), (0, _gen.FunctionExpression)([], [(0, _gen.ReturnStatement)((0, _gen.UnaryExpression)("typeof", (0, _gen.Identifier)(identifierName)))]), true, "get"));
247
- }
241
+ // Replace original function body with a call to the flattened function
242
+ fnPath.node.body = t.blockStatement([flatObjectDeclaration, t.returnStatement(t.callExpression(t.identifier(newFnName), [t.identifier(argName), t.identifier(flatObjectName)]))]);
243
+ var originalLength = (0, _functionUtils.computeFunctionLength)(fnPath);
244
+ fnPath.node.params = [t.restElement(t.identifier(argName))];
248
245
 
249
- // Call functions
250
- for (var identifierName in callPropNames) {
251
- var callPropName = callPropNames[identifierName];
252
- var argumentsName = this.getPlaceholder();
253
- flatObjectProperties.push((0, _gen.Property)((0, _gen.Literal)(callPropName), (0, _gen.FunctionExpression)([(0, _gen.RestElement)((0, _gen.Identifier)(argumentsName))], [(0, _gen.ReturnStatement)((0, _gen.CallExpression)((0, _gen.Identifier)(identifierName), [(0, _gen.SpreadElement)((0, _gen.Identifier)(argumentsName))]))]), true));
254
- }
246
+ // Ensure updated parameter gets registered in the function scope
247
+ fnPath.scope.crawl();
248
+ fnPath.skip();
255
249
 
256
- // Setter functions
257
- for (var identifierName in setterPropNames) {
258
- var setterPropName = setterPropNames[identifierName];
259
- var newValueParameterName = this.getPlaceholder();
260
- flatObjectProperties.push((0, _gen.Property)((0, _gen.Literal)(setterPropName), (0, _gen.FunctionExpression)([(0, _gen.Identifier)(newValueParameterName)], [(0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(identifierName), (0, _gen.Identifier)(newValueParameterName)))]), true, "set"));
261
- }
262
- if (!this.isDebug) {
263
- (0, _random.shuffle)(flatObjectProperties);
264
- }
265
- var newBody = (0, _insert.getBlockBody)(object.body);
250
+ // Add the new flattened function at the top level
251
+ var newPath = (0, _astUtils.prependProgram)(program, flattenedFunctionDeclaration)[0];
252
+ me.skip(newPath);
266
253
 
267
- // Remove 'use strict' directive
268
- if (newBody.length > 0 && newBody[0].directive) {
269
- newBody.shift();
254
+ // Copy over all properties except the predictable flag
255
+ var _iterator4 = _createForOfIteratorHelper(Object.getOwnPropertySymbols(fnPath.node)),
256
+ _step4;
257
+ try {
258
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
259
+ var symbol = _step4.value;
260
+ if (symbol !== _constants.PREDICTABLE) {
261
+ newPath.node[symbol] = fnPath.node[symbol];
262
+ }
270
263
  }
271
- var newFunctionDeclaration = (0, _gen.FunctionDeclaration)(newFnName, [(0, _gen.ArrayPattern)((0, _insert.clone)(object.params)), (0, _gen.Identifier)(flatObjectName)], newBody);
272
- newFunctionDeclaration.async = !!object.async;
273
- newFunctionDeclaration.generator = false;
274
- this.flattenedFns.push(newFunctionDeclaration);
275
- var argumentsName = this.getPlaceholder();
276
264
 
277
- // newFn.call([...arguments], flatObject)
278
- var callExpression = (0, _gen.CallExpression)((0, _gen.Identifier)(newFnName), [(0, _gen.Identifier)(argumentsName), (0, _gen.Identifier)(flatObjectName)]);
279
- var newObjectBody = [
280
- // var flatObject = { get(), set() };
281
- (0, _gen.VariableDeclaration)([(0, _gen.VariableDeclarator)(flatObjectName, (0, _gen.ObjectExpression)(flatObjectProperties))]), (0, _gen.ReturnStatement)(newFunctionDeclaration.async ? (0, _gen.AwaitExpression)(callExpression) : callExpression)];
282
- object.body = (0, _gen.BlockStatement)(newObjectBody);
265
+ // Old function is no longer predictable (rest element parameter)
266
+ } catch (err) {
267
+ _iterator4.e(err);
268
+ } finally {
269
+ _iterator4.f();
270
+ }
271
+ fnPath.node[_constants.PREDICTABLE] = false;
272
+ // Old function is unsafe (uses arguments, this)
273
+ fnPath.node[_constants.UNSAFE] = true;
274
+ newPath.node[_constants.PREDICTABLE] = true;
283
275
 
284
- // Preserve function.length property
285
- var originalFunctionLength = (0, _insert.computeFunctionLength)(object.params);
286
- object.params = [(0, _gen.RestElement)((0, _gen.Identifier)(argumentsName))];
287
- if (this.options.preserveFunctionLength && originalFunctionLength !== 0) {
288
- if (!this.functionLengthName) {
289
- this.functionLengthName = this.getPlaceholder();
290
- (0, _insert.prepend)(parents[parents.length - 1] || object, _functionLength.FunctionLengthTemplate.single({
291
- name: this.functionLengthName,
292
- ObjectDefineProperty: this.createInitVariable(_globals.ObjectDefineProperty, parents)
293
- }));
294
- }
295
- if (object.type === "FunctionDeclaration") {
296
- var body = parents[0];
297
- if (Array.isArray(body)) {
298
- var index = body.indexOf(object);
299
- body.splice(index + 1, 0, (0, _gen.ExpressionStatement)((0, _gen.CallExpression)((0, _gen.Identifier)(this.functionLengthName), [(0, _gen.Identifier)(object.id.name), (0, _gen.Literal)(originalFunctionLength)])));
300
- }
301
- } else {
302
- (0, _assert.ok)(object.type === "FunctionExpression");
303
- this.replace(object, (0, _gen.CallExpression)((0, _gen.Identifier)(this.functionLengthName), [{
304
- ...object
305
- }, (0, _gen.Literal)(originalFunctionLength)]));
276
+ // Carry over 'use strict' directive if not already present
277
+ if (strictMode) {
278
+ newPath.node.body.directives.push(t.directive(t.directiveLiteral("use strict")));
279
+
280
+ // Non-simple parameter list conversion
281
+ (0, _astUtils.prepend)(newPath, t.variableDeclaration("var", [t.variableDeclarator(t.arrayPattern(newPath.node.params), t.identifier("arguments"))]));
282
+ newPath.node.params = [];
283
+ // Using 'arguments' is unsafe
284
+ newPath.node[_constants.UNSAFE] = true;
285
+ // Params changed and using 'arguments'
286
+ newPath.node[_constants.PREDICTABLE] = false;
287
+ }
288
+
289
+ // Ensure parameters are registered in the new function scope
290
+ newPath.scope.crawl();
291
+ newPath.skip();
292
+ me.skip(newPath);
293
+
294
+ // Set function length
295
+ me.setFunctionLength(fnPath, originalLength);
296
+ me.changeData.functions++;
297
+ }
298
+ return {
299
+ visitor: {
300
+ Function: {
301
+ exit: function exit(path) {
302
+ flattenFunction(path);
306
303
  }
304
+ },
305
+ Program: function Program(path) {
306
+ path.scope.crawl();
307
307
  }
308
- };
309
- }
310
- }
311
- exports.default = Flatten;
308
+ }
309
+ };
310
+ };