js-confuser 1.7.2 → 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 (263) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +6 -4
  2. package/.github/workflows/node.js.yml +1 -1
  3. package/CHANGELOG.md +105 -0
  4. package/Migration.md +57 -0
  5. package/README.md +23 -913
  6. package/dist/constants.js +69 -13
  7. package/dist/index.js +108 -152
  8. package/dist/obfuscator.js +316 -118
  9. package/dist/options.js +1 -109
  10. package/dist/order.js +30 -30
  11. package/dist/presets.js +47 -45
  12. package/dist/probability.js +25 -32
  13. package/dist/templates/bufferToStringTemplate.js +9 -0
  14. package/dist/templates/deadCodeTemplates.js +9 -0
  15. package/dist/templates/getGlobalTemplate.js +19 -0
  16. package/dist/templates/integrityTemplate.js +30 -0
  17. package/dist/templates/setFunctionLengthTemplate.js +9 -0
  18. package/dist/templates/stringCompressionTemplate.js +10 -0
  19. package/dist/templates/tamperProtectionTemplates.js +21 -0
  20. package/dist/templates/template.js +213 -93
  21. package/dist/transforms/astScrambler.js +100 -0
  22. package/dist/transforms/calculator.js +70 -127
  23. package/dist/transforms/controlFlowFlattening.js +1182 -0
  24. package/dist/transforms/deadCode.js +62 -577
  25. package/dist/transforms/dispatcher.js +300 -309
  26. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +88 -189
  27. package/dist/transforms/extraction/objectExtraction.js +131 -215
  28. package/dist/transforms/finalizer.js +56 -59
  29. package/dist/transforms/flatten.js +275 -276
  30. package/dist/transforms/functionOutlining.js +230 -0
  31. package/dist/transforms/identifier/globalConcealing.js +217 -103
  32. package/dist/transforms/identifier/movedDeclarations.js +167 -91
  33. package/dist/transforms/identifier/renameVariables.js +240 -187
  34. package/dist/transforms/lock/integrity.js +61 -184
  35. package/dist/transforms/lock/lock.js +263 -303
  36. package/dist/transforms/minify.js +431 -436
  37. package/dist/transforms/opaquePredicates.js +65 -118
  38. package/dist/transforms/pack.js +160 -0
  39. package/dist/transforms/plugin.js +179 -0
  40. package/dist/transforms/preparation.js +263 -163
  41. package/dist/transforms/renameLabels.js +132 -56
  42. package/dist/transforms/rgf.js +142 -240
  43. package/dist/transforms/shuffle.js +52 -145
  44. package/dist/transforms/string/encoding.js +45 -173
  45. package/dist/transforms/string/stringCompression.js +81 -126
  46. package/dist/transforms/string/stringConcealing.js +189 -224
  47. package/dist/transforms/string/stringEncoding.js +32 -40
  48. package/dist/transforms/string/stringSplitting.js +54 -55
  49. package/dist/transforms/variableMasking.js +232 -0
  50. package/dist/utils/ControlObject.js +125 -0
  51. package/dist/utils/IntGen.js +46 -0
  52. package/dist/utils/NameGen.js +106 -0
  53. package/dist/utils/ast-utils.js +560 -0
  54. package/dist/utils/function-utils.js +56 -0
  55. package/dist/utils/gen-utils.js +48 -0
  56. package/dist/utils/node.js +77 -0
  57. package/dist/utils/object-utils.js +21 -0
  58. package/dist/utils/random-utils.js +91 -0
  59. package/dist/utils/static-utils.js +64 -0
  60. package/dist/validateOptions.js +122 -0
  61. package/index.d.ts +1 -17
  62. package/package.json +27 -22
  63. package/src/constants.ts +139 -77
  64. package/src/index.ts +70 -163
  65. package/src/obfuscationResult.ts +43 -0
  66. package/src/obfuscator.ts +328 -135
  67. package/src/options.ts +154 -623
  68. package/src/order.ts +14 -14
  69. package/src/presets.ts +39 -34
  70. package/src/probability.ts +21 -36
  71. package/src/templates/{bufferToString.ts → bufferToStringTemplate.ts} +5 -54
  72. package/src/templates/deadCodeTemplates.ts +1185 -0
  73. package/src/templates/getGlobalTemplate.ts +72 -0
  74. package/src/templates/integrityTemplate.ts +69 -0
  75. package/src/templates/setFunctionLengthTemplate.ts +11 -0
  76. package/src/templates/stringCompressionTemplate.ts +42 -0
  77. package/src/templates/tamperProtectionTemplates.ts +116 -0
  78. package/src/templates/template.ts +183 -92
  79. package/src/transforms/astScrambler.ts +99 -0
  80. package/src/transforms/calculator.ts +96 -224
  81. package/src/transforms/controlFlowFlattening.ts +1594 -0
  82. package/src/transforms/deadCode.ts +85 -628
  83. package/src/transforms/dispatcher.ts +431 -636
  84. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +147 -299
  85. package/src/transforms/extraction/objectExtraction.ts +160 -333
  86. package/src/transforms/finalizer.ts +63 -64
  87. package/src/transforms/flatten.ts +439 -557
  88. package/src/transforms/functionOutlining.ts +225 -0
  89. package/src/transforms/identifier/globalConcealing.ts +261 -189
  90. package/src/transforms/identifier/movedDeclarations.ts +228 -142
  91. package/src/transforms/identifier/renameVariables.ts +252 -258
  92. package/src/transforms/lock/integrity.ts +84 -260
  93. package/src/transforms/lock/lock.ts +342 -491
  94. package/src/transforms/minify.ts +523 -663
  95. package/src/transforms/opaquePredicates.ts +90 -229
  96. package/src/transforms/pack.ts +195 -0
  97. package/src/transforms/plugin.ts +185 -0
  98. package/src/transforms/preparation.ts +337 -215
  99. package/src/transforms/renameLabels.ts +176 -77
  100. package/src/transforms/rgf.ts +293 -386
  101. package/src/transforms/shuffle.ts +80 -254
  102. package/src/transforms/string/encoding.ts +26 -129
  103. package/src/transforms/string/stringCompression.ts +118 -236
  104. package/src/transforms/string/stringConcealing.ts +255 -339
  105. package/src/transforms/string/stringEncoding.ts +28 -47
  106. package/src/transforms/string/stringSplitting.ts +61 -75
  107. package/src/transforms/variableMasking.ts +257 -0
  108. package/src/utils/ControlObject.ts +141 -0
  109. package/src/utils/IntGen.ts +33 -0
  110. package/src/utils/NameGen.ts +106 -0
  111. package/src/utils/ast-utils.ts +667 -0
  112. package/src/utils/function-utils.ts +50 -0
  113. package/src/utils/gen-utils.ts +48 -0
  114. package/src/utils/node.ts +78 -0
  115. package/src/utils/object-utils.ts +21 -0
  116. package/src/utils/random-utils.ts +79 -0
  117. package/src/utils/static-utils.ts +66 -0
  118. package/src/validateOptions.ts +256 -0
  119. package/tsconfig.json +13 -8
  120. package/babel.config.js +0 -12
  121. package/dev.js +0 -8
  122. package/dist/compiler.js +0 -34
  123. package/dist/parser.js +0 -59
  124. package/dist/precedence.js +0 -66
  125. package/dist/templates/bufferToString.js +0 -108
  126. package/dist/templates/crash.js +0 -59
  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 -1281
  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 -70
  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 -343
  144. package/dist/transforms/transform.js +0 -350
  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 -9
  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 -130
  154. package/dist/util/scope.js +0 -20
  155. package/docs/ControlFlowFlattening.md +0 -595
  156. package/docs/Countermeasures.md +0 -63
  157. package/docs/ES5.md +0 -197
  158. package/docs/Integrity.md +0 -75
  159. package/docs/RGF.md +0 -419
  160. package/samples/example.js +0 -15
  161. package/samples/high.js +0 -1
  162. package/samples/input.js +0 -3
  163. package/samples/javascriptobfuscator.com.js +0 -8
  164. package/samples/jscrambler_advanced.js +0 -1894
  165. package/samples/jscrambler_light.js +0 -1134
  166. package/samples/low.js +0 -1
  167. package/samples/medium.js +0 -1
  168. package/samples/obfuscator.io.js +0 -1686
  169. package/samples/preemptive.com.js +0 -16
  170. package/src/compiler.ts +0 -35
  171. package/src/parser.ts +0 -49
  172. package/src/precedence.ts +0 -61
  173. package/src/templates/crash.ts +0 -55
  174. package/src/templates/es5.ts +0 -131
  175. package/src/templates/functionLength.ts +0 -32
  176. package/src/templates/globals.ts +0 -3
  177. package/src/transforms/antiTooling.ts +0 -102
  178. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +0 -2146
  179. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +0 -179
  180. package/src/transforms/es5/antiClass.ts +0 -272
  181. package/src/transforms/es5/antiDestructuring.ts +0 -294
  182. package/src/transforms/es5/antiES6Object.ts +0 -267
  183. package/src/transforms/es5/antiSpreadOperator.ts +0 -56
  184. package/src/transforms/es5/antiTemplate.ts +0 -98
  185. package/src/transforms/es5/es5.ts +0 -149
  186. package/src/transforms/extraction/classExtraction.ts +0 -168
  187. package/src/transforms/identifier/globalAnalysis.ts +0 -85
  188. package/src/transforms/identifier/variableAnalysis.ts +0 -118
  189. package/src/transforms/lock/antiDebug.ts +0 -112
  190. package/src/transforms/stack.ts +0 -551
  191. package/src/transforms/transform.ts +0 -453
  192. package/src/traverse.ts +0 -120
  193. package/src/types.ts +0 -131
  194. package/src/util/compare.ts +0 -181
  195. package/src/util/gen.ts +0 -651
  196. package/src/util/guard.ts +0 -7
  197. package/src/util/identifiers.ts +0 -494
  198. package/src/util/insert.ts +0 -419
  199. package/src/util/math.ts +0 -15
  200. package/src/util/object.ts +0 -39
  201. package/src/util/random.ts +0 -141
  202. package/src/util/scope.ts +0 -21
  203. package/test/code/Cash.src.js +0 -1011
  204. package/test/code/Cash.test.ts +0 -49
  205. package/test/code/Dynamic.src.js +0 -118
  206. package/test/code/Dynamic.test.ts +0 -49
  207. package/test/code/ES6.src.js +0 -235
  208. package/test/code/ES6.test.ts +0 -42
  209. package/test/code/NewFeatures.test.ts +0 -19
  210. package/test/code/StrictMode.src.js +0 -65
  211. package/test/code/StrictMode.test.js +0 -37
  212. package/test/compare.test.ts +0 -104
  213. package/test/index.test.ts +0 -249
  214. package/test/options.test.ts +0 -132
  215. package/test/presets.test.ts +0 -22
  216. package/test/probability.test.ts +0 -44
  217. package/test/templates/template.test.ts +0 -14
  218. package/test/transforms/antiTooling.test.ts +0 -52
  219. package/test/transforms/calculator.test.ts +0 -78
  220. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +0 -1274
  221. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +0 -192
  222. package/test/transforms/deadCode.test.ts +0 -85
  223. package/test/transforms/dispatcher.test.ts +0 -457
  224. package/test/transforms/es5/antiClass.test.ts +0 -427
  225. package/test/transforms/es5/antiDestructuring.test.ts +0 -157
  226. package/test/transforms/es5/antiES6Object.test.ts +0 -245
  227. package/test/transforms/es5/antiTemplate.test.ts +0 -116
  228. package/test/transforms/es5/es5.test.ts +0 -110
  229. package/test/transforms/extraction/classExtraction.test.ts +0 -86
  230. package/test/transforms/extraction/duplicateLiteralsRemoval.test.ts +0 -200
  231. package/test/transforms/extraction/objectExtraction.test.ts +0 -491
  232. package/test/transforms/flatten.test.ts +0 -721
  233. package/test/transforms/hexadecimalNumbers.test.ts +0 -62
  234. package/test/transforms/identifier/globalConcealing.test.ts +0 -72
  235. package/test/transforms/identifier/movedDeclarations.test.ts +0 -275
  236. package/test/transforms/identifier/renameVariables.test.ts +0 -621
  237. package/test/transforms/lock/antiDebug.test.ts +0 -66
  238. package/test/transforms/lock/browserLock.test.ts +0 -129
  239. package/test/transforms/lock/countermeasures.test.ts +0 -100
  240. package/test/transforms/lock/integrity.test.ts +0 -161
  241. package/test/transforms/lock/lock.test.ts +0 -204
  242. package/test/transforms/lock/osLock.test.ts +0 -312
  243. package/test/transforms/lock/selfDefending.test.ts +0 -68
  244. package/test/transforms/minify.test.ts +0 -575
  245. package/test/transforms/opaquePredicates.test.ts +0 -43
  246. package/test/transforms/preparation.test.ts +0 -157
  247. package/test/transforms/renameLabels.test.ts +0 -95
  248. package/test/transforms/rgf.test.ts +0 -378
  249. package/test/transforms/shuffle.test.ts +0 -135
  250. package/test/transforms/stack.test.ts +0 -573
  251. package/test/transforms/string/stringCompression.test.ts +0 -120
  252. package/test/transforms/string/stringConcealing.test.ts +0 -299
  253. package/test/transforms/string/stringEncoding.test.ts +0 -95
  254. package/test/transforms/string/stringSplitting.test.ts +0 -135
  255. package/test/transforms/transform.test.ts +0 -66
  256. package/test/traverse.test.ts +0 -139
  257. package/test/util/compare.test.ts +0 -34
  258. package/test/util/gen.test.ts +0 -121
  259. package/test/util/identifiers.test.ts +0 -253
  260. package/test/util/insert.test.ts +0 -142
  261. package/test/util/math.test.ts +0 -5
  262. package/test/util/random.test.ts +0 -71
  263. /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
+ };