浏览代码

using stirngArrayStorage id as string array nodes name

sanex3339 8 年之前
父节点
当前提交
8508af3891

+ 225 - 200
dist/index.js

@@ -187,10 +187,12 @@ var RandomGeneratorUtils = function () {
         key: "getRandomVariableName",
         value: function getRandomVariableName() {
             var length = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 6;
+            var withPrefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
 
-            var rangeMinInteger = 10000,
-                rangeMaxInteger = 99999999;
-            return "_" + Utils_1.Utils.hexadecimalPrefix + Utils_1.Utils.decToHex(RandomGeneratorUtils.getRandomInteger(rangeMinInteger, rangeMaxInteger)).substr(0, length);
+            var prefix = withPrefix ? "_" + Utils_1.Utils.hexadecimalPrefix : '';
+            var rangeMinInteger = 10000;
+            var rangeMaxInteger = 99999999;
+            return "" + prefix + Utils_1.Utils.decToHex(RandomGeneratorUtils.getRandomInteger(rangeMinInteger, rangeMaxInteger)).substr(0, length);
         }
     }, {
         key: "setRandomGeneratorSeed",
@@ -424,8 +426,8 @@ var _createClass = (function () { function defineProperties(target, props) { for
 
 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
 
-var _ = __webpack_require__(34);
-var JSFuck_1 = __webpack_require__(27);
+var _ = __webpack_require__(27);
+var JSFuck_1 = __webpack_require__(28);
 
 var Utils = function () {
     function Utils() {
@@ -623,7 +625,7 @@ var _createClass = (function () { function defineProperties(target, props) { for
 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
 
 var escodegen = __webpack_require__(17);
-var esprima = __webpack_require__(33);
+var esprima = __webpack_require__(34);
 var estraverse = __webpack_require__(5);
 var NodeType_1 = __webpack_require__(10);
 var Node_1 = __webpack_require__(4);
@@ -951,7 +953,7 @@ var JavaScriptObfuscator = function () {
     }
 
     _createClass(JavaScriptObfuscator, null, [{
-        key: "obfuscate",
+        key: 'obfuscate',
         value: function obfuscate(sourceCode) {
             var inputOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
 
@@ -960,7 +962,7 @@ var JavaScriptObfuscator = function () {
             return javaScriptObfuscator.obfuscate(sourceCode);
         }
     }, {
-        key: "runCLI",
+        key: 'runCLI',
         value: function runCLI(argv) {
             new JavaScriptObfuscatorCLI_1.JavaScriptObfuscatorCLI(argv).run();
         }
@@ -1245,6 +1247,87 @@ exports.NO_CUSTOM_NODES_PRESET = Object.freeze({
 
 /***/ },
 /* 22 */
+/***/ function(module, exports, __webpack_require__) {
+
+"use strict";
+"use strict";
+
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _get = (function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } });
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+var __decorate = undefined && undefined.__decorate || function (decorators, target, key, desc) {
+    var c = arguments.length,
+        r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,
+        d;
+    if ((typeof Reflect === "undefined" ? "undefined" : _typeof(Reflect)) === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) {
+        if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+    }return c > 3 && r && Object.defineProperty(target, key, r), r;
+};
+var __metadata = undefined && undefined.__metadata || function (k, v) {
+    if ((typeof Reflect === "undefined" ? "undefined" : _typeof(Reflect)) === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+var __param = undefined && undefined.__param || function (paramIndex, decorator) {
+    return function (target, key) {
+        decorator(target, key, paramIndex);
+    };
+};
+var inversify_1 = __webpack_require__(0);
+var ServiceIdentifiers_1 = __webpack_require__(1);
+var format = __webpack_require__(8);
+var Initializable_1 = __webpack_require__(3);
+var StringArrayTemplate_1 = __webpack_require__(111);
+var AbstractCustomNode_1 = __webpack_require__(7);
+var StringArrayNode = function (_AbstractCustomNode_) {
+    _inherits(StringArrayNode, _AbstractCustomNode_);
+
+    function StringArrayNode(options) {
+        _classCallCheck(this, StringArrayNode);
+
+        return _possibleConstructorReturn(this, (StringArrayNode.__proto__ || Object.getPrototypeOf(StringArrayNode)).call(this, options));
+    }
+
+    _createClass(StringArrayNode, [{
+        key: "initialize",
+        value: function initialize(stringArrayStorage, stringArrayName, stringArrayRotateValue) {
+            this.stringArrayStorage = stringArrayStorage;
+            this.stringArrayName = stringArrayName;
+            this.stringArrayRotateValue = stringArrayRotateValue;
+        }
+    }, {
+        key: "getNode",
+        value: function getNode() {
+            this.stringArrayStorage.rotateArray(this.stringArrayRotateValue);
+            return _get(StringArrayNode.prototype.__proto__ || Object.getPrototypeOf(StringArrayNode.prototype), "getNode", this).call(this);
+        }
+    }, {
+        key: "getTemplate",
+        value: function getTemplate() {
+            return format(StringArrayTemplate_1.StringArrayTemplate(), {
+                stringArrayName: this.stringArrayName,
+                stringArray: this.stringArrayStorage.toString()
+            });
+        }
+    }]);
+
+    return StringArrayNode;
+}(AbstractCustomNode_1.AbstractCustomNode);
+__decorate([Initializable_1.initializable(), __metadata("design:type", Object)], StringArrayNode.prototype, "stringArrayStorage", void 0);
+__decorate([Initializable_1.initializable(), __metadata("design:type", String)], StringArrayNode.prototype, "stringArrayName", void 0);
+__decorate([Initializable_1.initializable(), __metadata("design:type", Number)], StringArrayNode.prototype, "stringArrayRotateValue", void 0);
+StringArrayNode = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata("design:paramtypes", [Object])], StringArrayNode);
+exports.StringArrayNode = StringArrayNode;
+
+/***/ },
+/* 23 */
 /***/ function(module, exports) {
 
 "use strict";
@@ -1256,7 +1339,7 @@ exports.StringArrayEncoding = {
 };
 
 /***/ },
-/* 23 */
+/* 24 */
 /***/ function(module, exports) {
 
 "use strict";
@@ -1272,7 +1355,7 @@ exports.StringArrayEncoding = {
 var CustomNodeGroups = exports.CustomNodeGroups;
 
 /***/ },
-/* 24 */
+/* 25 */
 /***/ function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -1301,7 +1384,7 @@ AbstractCalleeDataExtractor = __decorate([inversify_1.injectable(), __metadata('
 exports.AbstractCalleeDataExtractor = AbstractCalleeDataExtractor;
 
 /***/ },
-/* 25 */
+/* 26 */
 /***/ function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -1401,89 +1484,13 @@ var CryptUtils = function () {
 exports.CryptUtils = CryptUtils;
 
 /***/ },
-/* 26 */
-/***/ function(module, exports, __webpack_require__) {
-
-"use strict";
-"use strict";
-
-var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
-
-var _get = (function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } });
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
-
-function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
-
-var __decorate = undefined && undefined.__decorate || function (decorators, target, key, desc) {
-    var c = arguments.length,
-        r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,
-        d;
-    if ((typeof Reflect === "undefined" ? "undefined" : _typeof(Reflect)) === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) {
-        if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
-    }return c > 3 && r && Object.defineProperty(target, key, r), r;
-};
-var __metadata = undefined && undefined.__metadata || function (k, v) {
-    if ((typeof Reflect === "undefined" ? "undefined" : _typeof(Reflect)) === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
-};
-var __param = undefined && undefined.__param || function (paramIndex, decorator) {
-    return function (target, key) {
-        decorator(target, key, paramIndex);
-    };
-};
-var inversify_1 = __webpack_require__(0);
-var ServiceIdentifiers_1 = __webpack_require__(1);
-var format = __webpack_require__(8);
-var Initializable_1 = __webpack_require__(3);
-var StringArrayTemplate_1 = __webpack_require__(111);
-var AbstractCustomNode_1 = __webpack_require__(7);
-var StringArrayNode = function (_AbstractCustomNode_) {
-    _inherits(StringArrayNode, _AbstractCustomNode_);
-
-    function StringArrayNode(options) {
-        _classCallCheck(this, StringArrayNode);
-
-        return _possibleConstructorReturn(this, (StringArrayNode.__proto__ || Object.getPrototypeOf(StringArrayNode)).call(this, options));
-    }
-
-    _createClass(StringArrayNode, [{
-        key: "initialize",
-        value: function initialize(stringArray, stringArrayName, stringArrayRotateValue) {
-            this.stringArray = stringArray;
-            this.stringArrayName = stringArrayName;
-            this.stringArrayRotateValue = stringArrayRotateValue;
-        }
-    }, {
-        key: "getNode",
-        value: function getNode() {
-            this.stringArray.rotateArray(this.stringArrayRotateValue);
-            return _get(StringArrayNode.prototype.__proto__ || Object.getPrototypeOf(StringArrayNode.prototype), "getNode", this).call(this);
-        }
-    }, {
-        key: "getTemplate",
-        value: function getTemplate() {
-            return format(StringArrayTemplate_1.StringArrayTemplate(), {
-                stringArrayName: this.stringArrayName,
-                stringArray: this.stringArray.toString()
-            });
-        }
-    }]);
+/* 27 */
+/***/ function(module, exports) {
 
-    return StringArrayNode;
-}(AbstractCustomNode_1.AbstractCustomNode);
-StringArrayNode.ARRAY_RANDOM_LENGTH = 4;
-__decorate([Initializable_1.initializable(), __metadata("design:type", Object)], StringArrayNode.prototype, "stringArray", void 0);
-__decorate([Initializable_1.initializable(), __metadata("design:type", String)], StringArrayNode.prototype, "stringArrayName", void 0);
-__decorate([Initializable_1.initializable(), __metadata("design:type", Number)], StringArrayNode.prototype, "stringArrayRotateValue", void 0);
-StringArrayNode = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata("design:paramtypes", [Object])], StringArrayNode);
-exports.StringArrayNode = StringArrayNode;
+module.exports = require("lodash");
 
 /***/ },
-/* 27 */
+/* 28 */
 /***/ function(module, exports) {
 
 "use strict";
@@ -1547,7 +1554,7 @@ exports.JSFuck = {
 };
 
 /***/ },
-/* 28 */
+/* 29 */
 /***/ function(module, exports) {
 
 "use strict";
@@ -1561,7 +1568,7 @@ exports.JSFuck = {
 var CalleeDataExtractors = exports.CalleeDataExtractors;
 
 /***/ },
-/* 29 */
+/* 30 */
 /***/ function(module, exports) {
 
 "use strict";
@@ -1573,7 +1580,7 @@ var NodeControlFlowReplacers;
 })(NodeControlFlowReplacers = exports.NodeControlFlowReplacers || (exports.NodeControlFlowReplacers = {}));
 
 /***/ },
-/* 30 */
+/* 31 */
 /***/ function(module, exports) {
 
 "use strict";
@@ -1594,7 +1601,7 @@ var NodeControlFlowReplacers;
 var NodeTransformers = exports.NodeTransformers;
 
 /***/ },
-/* 31 */
+/* 32 */
 /***/ function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -1623,7 +1630,7 @@ exports.DEFAULT_PRESET = Object.freeze({
 });
 
 /***/ },
-/* 32 */
+/* 33 */
 /***/ function(module, exports, __webpack_require__) {
 
 "use strict";
@@ -1650,6 +1657,7 @@ var __metadata = undefined && undefined.__metadata || function (k, v) {
 };
 var inversify_1 = __webpack_require__(0);
 var Initializable_1 = __webpack_require__(3);
+var RandomGeneratorUtils_1 = __webpack_require__(2);
 var Utils_1 = __webpack_require__(6);
 var MapStorage = function () {
     function MapStorage() {
@@ -1680,15 +1688,26 @@ var MapStorage = function () {
         value: function getStorage() {
             return this.storage;
         }
+    }, {
+        key: "getStorageId",
+        value: function getStorageId() {
+            return this.storageId;
+        }
     }, {
         key: "initialize",
         value: function initialize() {
             this.storage = new Map();
+            this.storageId = RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomString(6);
         }
     }, {
         key: "mergeWith",
         value: function mergeWith(storage) {
+            var mergeId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+
             this.storage = new Map([].concat(_toConsumableArray(this.storage), _toConsumableArray(storage.getStorage())));
+            if (mergeId) {
+                this.storageId = storage.getStorageId();
+            }
         }
     }, {
         key: "set",
@@ -1699,21 +1718,16 @@ var MapStorage = function () {
 
     return MapStorage;
 }();
+__decorate([Initializable_1.initializable(), __metadata("design:type", String)], MapStorage.prototype, "storageId", void 0);
 __decorate([Initializable_1.initializable(), __metadata("design:type", Map)], MapStorage.prototype, "storage", void 0);
 MapStorage = __decorate([inversify_1.injectable(), __metadata("design:paramtypes", [])], MapStorage);
 exports.MapStorage = MapStorage;
 
-/***/ },
-/* 33 */
-/***/ function(module, exports) {
-
-module.exports = require("esprima");
-
 /***/ },
 /* 34 */
 /***/ function(module, exports) {
 
-module.exports = require("lodash");
+module.exports = require("esprima");
 
 /***/ },
 /* 35 */
@@ -1761,7 +1775,7 @@ var __param = undefined && undefined.__param || function (paramIndex, decorator)
 };
 var inversify_1 = __webpack_require__(0);
 var ServiceIdentifiers_1 = __webpack_require__(1);
-var esprima = __webpack_require__(33);
+var esprima = __webpack_require__(34);
 var escodegen = __webpack_require__(17);
 var RandomGeneratorUtils_1 = __webpack_require__(2);
 var JavaScriptObfuscatorInternal = JavaScriptObfuscatorInternal_1 = function () {
@@ -1914,7 +1928,7 @@ var __param = undefined && undefined.__param || function (paramIndex, decorator)
 var inversify_1 = __webpack_require__(0);
 var ServiceIdentifiers_1 = __webpack_require__(1);
 var estraverse = __webpack_require__(5);
-var NodeTransformers_1 = __webpack_require__(30);
+var NodeTransformers_1 = __webpack_require__(31);
 var NodeType_1 = __webpack_require__(10);
 var ObfuscationEvents_1 = __webpack_require__(14);
 var VisitorDirection_1 = __webpack_require__(66);
@@ -2005,7 +2019,7 @@ var __param = undefined && undefined.__param || function (paramIndex, decorator)
 var inversify_1 = __webpack_require__(0);
 var ServiceIdentifiers_1 = __webpack_require__(1);
 var SourceMapMode_1 = __webpack_require__(19);
-var CryptUtils_1 = __webpack_require__(25);
+var CryptUtils_1 = __webpack_require__(26);
 var SourceMapCorrector = function () {
     function SourceMapCorrector(obfuscationResultFactory, options) {
         _classCallCheck(this, SourceMapCorrector);
@@ -2162,8 +2176,8 @@ var __assign = undefined && undefined.__assign || Object.assign || function (t)
 var commander = __webpack_require__(117);
 var path = __webpack_require__(35);
 var SourceMapMode_1 = __webpack_require__(19);
-var StringArrayEncoding_1 = __webpack_require__(22);
-var DefaultPreset_1 = __webpack_require__(31);
+var StringArrayEncoding_1 = __webpack_require__(23);
+var DefaultPreset_1 = __webpack_require__(32);
 var CLIUtils_1 = __webpack_require__(40);
 var JavaScriptObfuscator_1 = __webpack_require__(15);
 
@@ -2376,7 +2390,7 @@ exports.InversifyContainerFacade = InversifyContainerFacade;
 var inversify_1 = __webpack_require__(0);
 var ServiceIdentifiers_1 = __webpack_require__(1);
 var CustomNodes_1 = __webpack_require__(12);
-var CustomNodeGroups_1 = __webpack_require__(23);
+var CustomNodeGroups_1 = __webpack_require__(24);
 var ConsoleOutputCustomNodeGroup_1 = __webpack_require__(50);
 var DebugProtectionCustomNodeGroup_1 = __webpack_require__(57);
 var DomainLockCustomNodeGroup_1 = __webpack_require__(59);
@@ -2393,7 +2407,7 @@ var DomainLockNode_1 = __webpack_require__(58);
 var NodeCallsControllerFunctionNode_1 = __webpack_require__(60);
 var SelfDefendingUnicodeNode_1 = __webpack_require__(61);
 var StringArrayCallsWrapper_1 = __webpack_require__(63);
-var StringArrayNode_1 = __webpack_require__(26);
+var StringArrayNode_1 = __webpack_require__(22);
 var StringArrayRotateFunctionNode_1 = __webpack_require__(64);
 exports.customNodesModule = new inversify_1.ContainerModule(function (bind) {
     bind(ServiceIdentifiers_1.ServiceIdentifiers.ICustomNode).to(BinaryExpressionFunctionNode_1.BinaryExpressionFunctionNode).whenTargetNamed(CustomNodes_1.CustomNodes.BinaryExpressionFunctionNode);
@@ -2435,7 +2449,7 @@ exports.customNodesModule = new inversify_1.ContainerModule(function (bind) {
 
 var inversify_1 = __webpack_require__(0);
 var ServiceIdentifiers_1 = __webpack_require__(1);
-var NodeControlFlowReplacers_1 = __webpack_require__(29);
+var NodeControlFlowReplacers_1 = __webpack_require__(30);
 var BinaryExpressionControlFlowReplacer_1 = __webpack_require__(70);
 exports.nodeControlFlowTransformersModule = new inversify_1.ContainerModule(function (bind) {
     bind(ServiceIdentifiers_1.ServiceIdentifiers.IControlFlowReplacer).to(BinaryExpressionControlFlowReplacer_1.BinaryExpressionControlFlowReplacer).whenTargetNamed(NodeControlFlowReplacers_1.NodeControlFlowReplacers.BinaryExpressionControlFlowReplacer);
@@ -2493,7 +2507,7 @@ exports.nodeObfuscatorsModule = new inversify_1.ContainerModule(function (bind)
 
 var inversify_1 = __webpack_require__(0);
 var ServiceIdentifiers_1 = __webpack_require__(1);
-var NodeTransformers_1 = __webpack_require__(30);
+var NodeTransformers_1 = __webpack_require__(31);
 var FunctionControlFlowTransformer_1 = __webpack_require__(68);
 var CatchClauseObfuscator_1 = __webpack_require__(71);
 var FunctionDeclarationObfuscator_1 = __webpack_require__(72);
@@ -2546,7 +2560,7 @@ exports.nodeTransformersModule = new inversify_1.ContainerModule(function (bind)
 
 var inversify_1 = __webpack_require__(0);
 var ServiceIdentifiers_1 = __webpack_require__(1);
-var CalleeDataExtractors_1 = __webpack_require__(28);
+var CalleeDataExtractors_1 = __webpack_require__(29);
 var FunctionDeclarationCalleeDataExtractor_1 = __webpack_require__(88);
 var FunctionExpressionCalleeDataExtractor_1 = __webpack_require__(89);
 var ObjectExpressionCalleeDataExtractor_1 = __webpack_require__(90);
@@ -2954,16 +2968,15 @@ var ControlFlowStorageNode = function (_AbstractCustomNode_) {
 
     _createClass(ControlFlowStorageNode, [{
         key: "initialize",
-        value: function initialize(controlFlowStorage, controlFlowStorageName) {
+        value: function initialize(controlFlowStorage) {
             this.controlFlowStorage = controlFlowStorage;
-            this.controlFlowStorageName = controlFlowStorageName;
         }
     }, {
         key: "getTemplate",
         value: function getTemplate() {
             return format(ControlFlowStorageTemplate_1.ControlFlowStorageTemplate(), {
                 controlFlowStorage: this.controlFlowStorage.toString(),
-                controlFlowStorageName: this.controlFlowStorageName
+                controlFlowStorageName: this.controlFlowStorage.getStorageId()
             });
         }
     }]);
@@ -2971,7 +2984,6 @@ var ControlFlowStorageNode = function (_AbstractCustomNode_) {
     return ControlFlowStorageNode;
 }(AbstractCustomNode_1.AbstractCustomNode);
 __decorate([Initializable_1.initializable(), __metadata("design:type", Object)], ControlFlowStorageNode.prototype, "controlFlowStorage", void 0);
-__decorate([Initializable_1.initializable(), __metadata("design:type", String)], ControlFlowStorageNode.prototype, "controlFlowStorageName", void 0);
 ControlFlowStorageNode = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata("design:paramtypes", [Object])], ControlFlowStorageNode);
 exports.ControlFlowStorageNode = ControlFlowStorageNode;
 
@@ -3318,7 +3330,7 @@ var format = __webpack_require__(8);
 var Initializable_1 = __webpack_require__(3);
 var DomainLockNodeTemplate_1 = __webpack_require__(105);
 var AbstractCustomNode_1 = __webpack_require__(7);
-var CryptUtils_1 = __webpack_require__(25);
+var CryptUtils_1 = __webpack_require__(26);
 var RandomGeneratorUtils_1 = __webpack_require__(2);
 var DomainLockNode = function (_AbstractCustomNode_) {
     _inherits(DomainLockNode, _AbstractCustomNode_);
@@ -3760,7 +3772,7 @@ var __param = undefined && undefined.__param || function (paramIndex, decorator)
 var inversify_1 = __webpack_require__(0);
 var ServiceIdentifiers_1 = __webpack_require__(1);
 var format = __webpack_require__(8);
-var StringArrayEncoding_1 = __webpack_require__(22);
+var StringArrayEncoding_1 = __webpack_require__(23);
 var Initializable_1 = __webpack_require__(3);
 var NoCustomNodesPreset_1 = __webpack_require__(21);
 var AtobTemplate_1 = __webpack_require__(95);
@@ -3782,16 +3794,11 @@ var StringArrayCallsWrapper = function (_AbstractCustomNode_) {
 
     _createClass(StringArrayCallsWrapper, [{
         key: "initialize",
-        value: function initialize(stringArray, stringArrayName, stringArrayCallsWrapperName) {
-            this.stringArray = stringArray;
+        value: function initialize(stringArrayStorage, stringArrayName, stringArrayCallsWrapperName) {
+            this.stringArrayStorage = stringArrayStorage;
             this.stringArrayName = stringArrayName;
             this.stringArrayCallsWrapperName = stringArrayCallsWrapperName;
         }
-    }, {
-        key: "getNodeIdentifier",
-        value: function getNodeIdentifier() {
-            return this.stringArrayCallsWrapperName;
-        }
     }, {
         key: "getDecodeStringArrayTemplate",
         value: function getDecodeStringArrayTemplate() {
@@ -3836,9 +3843,9 @@ var StringArrayCallsWrapper = function (_AbstractCustomNode_) {
 
     return StringArrayCallsWrapper;
 }(AbstractCustomNode_1.AbstractCustomNode);
-__decorate([Initializable_1.initializable(), __metadata("design:type", Object)], StringArrayCallsWrapper.prototype, "stringArray", void 0);
-__decorate([Initializable_1.initializable(), __metadata("design:type", String)], StringArrayCallsWrapper.prototype, "stringArrayCallsWrapperName", void 0);
+__decorate([Initializable_1.initializable(), __metadata("design:type", Object)], StringArrayCallsWrapper.prototype, "stringArrayStorage", void 0);
 __decorate([Initializable_1.initializable(), __metadata("design:type", String)], StringArrayCallsWrapper.prototype, "stringArrayName", void 0);
+__decorate([Initializable_1.initializable(), __metadata("design:type", String)], StringArrayCallsWrapper.prototype, "stringArrayCallsWrapperName", void 0);
 StringArrayCallsWrapper = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata("design:paramtypes", [Object])], StringArrayCallsWrapper);
 exports.StringArrayCallsWrapper = StringArrayCallsWrapper;
 
@@ -3906,8 +3913,8 @@ var StringArrayRotateFunctionNode = function (_AbstractCustomNode_) {
 
     _createClass(StringArrayRotateFunctionNode, [{
         key: "initialize",
-        value: function initialize(stringArray, stringArrayName, stringArrayRotateValue) {
-            this.stringArray = stringArray;
+        value: function initialize(stringArrayStorage, stringArrayName, stringArrayRotateValue) {
+            this.stringArrayStorage = stringArrayStorage;
             this.stringArrayName = stringArrayName;
             this.stringArrayRotateValue = stringArrayRotateValue;
         }
@@ -3937,7 +3944,7 @@ var StringArrayRotateFunctionNode = function (_AbstractCustomNode_) {
 
     return StringArrayRotateFunctionNode;
 }(AbstractCustomNode_1.AbstractCustomNode);
-__decorate([Initializable_1.initializable(), __metadata("design:type", Object)], StringArrayRotateFunctionNode.prototype, "stringArray", void 0);
+__decorate([Initializable_1.initializable(), __metadata("design:type", Object)], StringArrayRotateFunctionNode.prototype, "stringArrayStorage", void 0);
 __decorate([Initializable_1.initializable(), __metadata("design:type", String)], StringArrayRotateFunctionNode.prototype, "stringArrayName", void 0);
 __decorate([Initializable_1.initializable(), __metadata("design:type", Number)], StringArrayRotateFunctionNode.prototype, "stringArrayRotateValue", void 0);
 StringArrayRotateFunctionNode = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata("design:paramtypes", [Object])], StringArrayRotateFunctionNode);
@@ -3981,10 +3988,10 @@ var ServiceIdentifiers_1 = __webpack_require__(1);
 var Initializable_1 = __webpack_require__(3);
 var CustomNodes_1 = __webpack_require__(12);
 var ObfuscationEvents_1 = __webpack_require__(14);
-var StringArrayNode_1 = __webpack_require__(26);
 var AbstractCustomNodeGroup_1 = __webpack_require__(18);
 var NodeAppender_1 = __webpack_require__(16);
 var RandomGeneratorUtils_1 = __webpack_require__(2);
+var Utils_1 = __webpack_require__(6);
 var StringArrayCustomNodeGroup = function (_AbstractCustomNodeGr) {
     _inherits(StringArrayCustomNodeGroup, _AbstractCustomNodeGr);
 
@@ -4026,8 +4033,10 @@ var StringArrayCustomNodeGroup = function (_AbstractCustomNodeGr) {
             var stringArrayNode = this.customNodeFactory(CustomNodes_1.CustomNodes.StringArrayNode);
             var stringArrayCallsWrapper = this.customNodeFactory(CustomNodes_1.CustomNodes.StringArrayCallsWrapper);
             var stringArrayRotateFunctionNode = this.customNodeFactory(CustomNodes_1.CustomNodes.StringArrayRotateFunctionNode);
-            var stringArrayName = RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomVariableName(StringArrayNode_1.StringArrayNode.ARRAY_RANDOM_LENGTH);
-            var stringArrayCallsWrapperName = RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomVariableName(StringArrayNode_1.StringArrayNode.ARRAY_RANDOM_LENGTH);
+            var reversedStorageId = Array.from(this.stringArrayStorage.getStorageId()).reverse().join('');
+            var stringArrayName = "_" + Utils_1.Utils.hexadecimalPrefix + this.stringArrayStorage.getStorageId();
+            var stringArrayCallsWrapperName = "_" + Utils_1.Utils.hexadecimalPrefix + reversedStorageId;
+            console.log(stringArrayCallsWrapperName);
             var stringArrayRotateValue = void 0;
             if (this.options.rotateStringArray) {
                 stringArrayRotateValue = RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomInteger(100, 500);
@@ -4153,13 +4162,13 @@ var __param = undefined && undefined.__param || function (paramIndex, decorator)
 var inversify_1 = __webpack_require__(0);
 var ServiceIdentifiers_1 = __webpack_require__(1);
 var estraverse = __webpack_require__(5);
-var _ = __webpack_require__(34);
+var _ = __webpack_require__(27);
 var CustomNodes_1 = __webpack_require__(12);
 var NodeType_1 = __webpack_require__(10);
 var AbstractNodeTransformer_1 = __webpack_require__(11);
 var Node_1 = __webpack_require__(4);
 var NodeAppender_1 = __webpack_require__(16);
-var NodeControlFlowReplacers_1 = __webpack_require__(29);
+var NodeControlFlowReplacers_1 = __webpack_require__(30);
 var NodeUtils_1 = __webpack_require__(9);
 var RandomGeneratorUtils_1 = __webpack_require__(2);
 var FunctionControlFlowTransformer = FunctionControlFlowTransformer_1 = function (_AbstractNodeTransfor) {
@@ -4193,43 +4202,31 @@ var FunctionControlFlowTransformer = FunctionControlFlowTransformer_1 = function
             }
             var controlFlowStorage = this.controlFlowStorageFactory();
             var hostNode = FunctionControlFlowTransformer_1.getHostNode(functionNode);
-            var controlFlowStorageNodeName = RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomVariableName(6);
             if (!this.controlFlowData.has(hostNode)) {
-                this.controlFlowData.set(hostNode, {
-                    controlFlowStorage: controlFlowStorage,
-                    controlFlowStorageNodeName: controlFlowStorageNodeName
-                });
+                this.controlFlowData.set(hostNode, controlFlowStorage);
             } else {
                 hostNode.body = FunctionControlFlowTransformer_1.removeOldControlFlowNodeFromHostNodeBody(hostNode.body, this.controlFlowNodesList);
-
-                var _controlFlowData$get = this.controlFlowData.get(hostNode),
-                    hostControlFlowStorage = _controlFlowData$get.controlFlowStorage,
-                    hostControlFlowStorageNodeName = _controlFlowData$get.controlFlowStorageNodeName;
-
-                controlFlowStorage.mergeWith(hostControlFlowStorage);
-                controlFlowStorageNodeName = hostControlFlowStorageNodeName;
-                this.controlFlowData.set(hostNode, {
-                    controlFlowStorage: controlFlowStorage,
-                    controlFlowStorageNodeName: hostControlFlowStorageNodeName
-                });
+                var hostControlFlowStorage = this.controlFlowData.get(hostNode);
+                controlFlowStorage.mergeWith(hostControlFlowStorage, true);
+                this.controlFlowData.set(hostNode, controlFlowStorage);
             }
             estraverse.replace(functionNode.body, {
                 enter: function enter(node, parentNode) {
-                    if (Math.random() > FunctionControlFlowTransformer_1.controlFlowReplacersThreshold) {
+                    if (RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomFloat(0, 1) > FunctionControlFlowTransformer_1.controlFlowReplacersThreshold) {
                         return;
                     }
                     var controlFlowReplacerName = FunctionControlFlowTransformer_1.controlFlowReplacersMap.get(node.type);
                     if (controlFlowReplacerName === undefined) {
                         return;
                     }
-                    return __assign({}, _this2.controlFlowReplacerFactory(controlFlowReplacerName).replace(node, parentNode, controlFlowStorage, controlFlowStorageNodeName), { parentNode: parentNode });
+                    return __assign({}, _this2.controlFlowReplacerFactory(controlFlowReplacerName).replace(node, parentNode, controlFlowStorage), { parentNode: parentNode });
                 }
             });
             if (!controlFlowStorage.getLength()) {
                 return;
             }
             var controlFlowStorageCustomNode = this.customNodeFactory(CustomNodes_1.CustomNodes.ControlFlowStorageNode);
-            controlFlowStorageCustomNode.initialize(controlFlowStorage, controlFlowStorageNodeName);
+            controlFlowStorageCustomNode.initialize(controlFlowStorage);
             var controlFlowStorageNode = controlFlowStorageCustomNode.getNode();
             this.controlFlowNodesList.push(controlFlowStorageNode);
             NodeAppender_1.NodeAppender.prependNode(hostNode, controlFlowStorageNode);
@@ -4382,10 +4379,10 @@ var __param = undefined && undefined.__param || function (paramIndex, decorator)
 var inversify_1 = __webpack_require__(0);
 var ServiceIdentifiers_1 = __webpack_require__(1);
 var escodegen = __webpack_require__(17);
-var _ = __webpack_require__(34);
 var CustomNodes_1 = __webpack_require__(12);
 var AbstractControlFlowReplacer_1 = __webpack_require__(69);
 var Node_1 = __webpack_require__(4);
+var RandomGeneratorUtils_1 = __webpack_require__(2);
 var BinaryExpressionControlFlowReplacer = BinaryExpressionControlFlowReplacer_1 = function (_AbstractControlFlowR) {
     _inherits(BinaryExpressionControlFlowReplacer, _AbstractControlFlowR);
 
@@ -4401,7 +4398,8 @@ var BinaryExpressionControlFlowReplacer = BinaryExpressionControlFlowReplacer_1
 
     _createClass(BinaryExpressionControlFlowReplacer, [{
         key: "replace",
-        value: function replace(binaryExpressionNode, parentNode, controlFlowStorage, controlFlowStorageCustomNodeName) {
+        value: function replace(binaryExpressionNode, parentNode, controlFlowStorage) {
+            var controlFlowStorageCustomNodeName = controlFlowStorage.getStorageId();
             var binaryExpressionFunctionNode = this.customNodeFactory(CustomNodes_1.CustomNodes.BinaryExpressionFunctionNode);
             var binaryExpressionOperatorKeys = this.existingBinaryExpressionKeys.get(controlFlowStorageCustomNodeName) || {};
             var controlFlowStorageCallNode = this.customNodeFactory(CustomNodes_1.CustomNodes.ControlFlowStorageCallNode);
@@ -4410,8 +4408,8 @@ var BinaryExpressionControlFlowReplacer = BinaryExpressionControlFlowReplacer_1
                 binaryExpressionOperatorKeys[binaryExpressionNode.operator] = [];
             }
             binaryExpressionFunctionNode.initialize(binaryExpressionNode.operator);
-            if (Math.random() > BinaryExpressionControlFlowReplacer_1.useExistingOperatorKeyThreshold && binaryExpressionOperatorKeys[binaryExpressionNode.operator].length) {
-                key = _.sample(binaryExpressionOperatorKeys[binaryExpressionNode.operator]);
+            if (RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomFloat(0, 1) > BinaryExpressionControlFlowReplacer_1.useExistingOperatorKeyThreshold && binaryExpressionOperatorKeys[binaryExpressionNode.operator].length) {
+                key = RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomGenerator().pickone(binaryExpressionOperatorKeys[binaryExpressionNode.operator]);
             } else {
                 binaryExpressionOperatorKeys[binaryExpressionNode.operator].push(key);
                 this.existingBinaryExpressionKeys.set(controlFlowStorageCustomNodeName, binaryExpressionOperatorKeys);
@@ -5332,7 +5330,7 @@ var __param = undefined && undefined.__param || function (paramIndex, decorator)
 };
 var inversify_1 = __webpack_require__(0);
 var ServiceIdentifiers_1 = __webpack_require__(1);
-var JSFuck_1 = __webpack_require__(27);
+var JSFuck_1 = __webpack_require__(28);
 var AbstractReplacer_1 = __webpack_require__(20);
 var BooleanLiteralReplacer = function (_AbstractReplacer_1$A) {
     _inherits(BooleanLiteralReplacer, _AbstractReplacer_1$A);
@@ -5530,11 +5528,9 @@ var __param = undefined && undefined.__param || function (paramIndex, decorator)
 };
 var inversify_1 = __webpack_require__(0);
 var ServiceIdentifiers_1 = __webpack_require__(1);
-var StringArrayEncoding_1 = __webpack_require__(22);
+var StringArrayEncoding_1 = __webpack_require__(23);
 var AbstractReplacer_1 = __webpack_require__(20);
-var CryptUtils_1 = __webpack_require__(25);
-var CustomNodes_1 = __webpack_require__(12);
-var CustomNodeGroups_1 = __webpack_require__(23);
+var CryptUtils_1 = __webpack_require__(26);
 var RandomGeneratorUtils_1 = __webpack_require__(2);
 var Utils_1 = __webpack_require__(6);
 var StringLiteralReplacer = StringLiteralReplacer_1 = function (_AbstractReplacer_1$A) {
@@ -5562,7 +5558,6 @@ var StringLiteralReplacer = StringLiteralReplacer_1 = function (_AbstractReplace
     }, {
         key: "replaceStringLiteralWithStringArrayCall",
         value: function replaceStringLiteralWithStringArrayCall(value) {
-            var stringArrayCustomNodeGroupNodes = this.customNodeGroupStorage.get(CustomNodeGroups_1.CustomNodeGroups.StringArrayCustomNodeGroup).getCustomNodes();
             var rc4Key = '';
             switch (this.options.stringArrayEncoding) {
                 case StringArrayEncoding_1.StringArrayEncoding.base64:
@@ -5584,12 +5579,13 @@ var StringLiteralReplacer = StringLiteralReplacer_1 = function (_AbstractReplace
                 indexOfValue = this.stringArrayStorage.getLength();
                 this.stringArrayStorage.set(null, value);
             }
-            var stringArrayCallsWrapper = stringArrayCustomNodeGroupNodes.get(CustomNodes_1.CustomNodes.StringArrayCallsWrapper);
+            var reversedStringArrayId = Array.from(this.stringArrayStorage.getStorageId()).reverse().join('');
+            var stringArrayStorageCallsWrapperName = "_" + Utils_1.Utils.hexadecimalPrefix + reversedStringArrayId;
             var hexadecimalIndex = "" + Utils_1.Utils.hexadecimalPrefix + Utils_1.Utils.decToHex(indexOfValue);
             if (this.options.stringArrayEncoding === StringArrayEncoding_1.StringArrayEncoding.rc4) {
-                return stringArrayCallsWrapper.getNodeIdentifier() + "('" + hexadecimalIndex + "', '" + Utils_1.Utils.stringToUnicodeEscapeSequence(rc4Key) + "')";
+                return stringArrayStorageCallsWrapperName + "('" + hexadecimalIndex + "', '" + Utils_1.Utils.stringToUnicodeEscapeSequence(rc4Key) + "')";
             }
-            return stringArrayCallsWrapper.getNodeIdentifier() + "('" + hexadecimalIndex + "')";
+            return stringArrayStorageCallsWrapperName + "('" + hexadecimalIndex + "')";
         }
     }]);
 
@@ -5627,10 +5623,10 @@ var __metadata = undefined && undefined.__metadata || function (k, v) {
 };
 var inversify_1 = __webpack_require__(0);
 var class_validator_1 = __webpack_require__(116);
-var DefaultPreset_1 = __webpack_require__(31);
+var DefaultPreset_1 = __webpack_require__(32);
 var OptionsNormalizer_1 = __webpack_require__(85);
 var ValidationErrorsFormatter_1 = __webpack_require__(86);
-var Options = Options_1 = function Options(inputOptions) {
+var Options_1 = function Options(inputOptions) {
     _classCallCheck(this, Options);
 
     Object.assign(this, DefaultPreset_1.DEFAULT_PRESET, inputOptions);
@@ -5640,41 +5636,42 @@ var Options = Options_1 = function Options(inputOptions) {
     }
     Object.assign(this, OptionsNormalizer_1.OptionsNormalizer.normalizeOptions(this));
 };
+var Options = Options_1;
 Options.validatorOptions = {
     validationError: {
         target: false
     }
 };
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "compact", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "controlFlowFlattening", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "debugProtection", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "debugProtectionInterval", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "disableConsoleOutput", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "compact", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "controlFlowFlattening", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "debugProtection", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "debugProtectionInterval", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "disableConsoleOutput", void 0);
 __decorate([class_validator_1.IsArray(), class_validator_1.ArrayUnique(), class_validator_1.IsString({
     each: true
-}), __metadata("design:type", Array)], Options.prototype, "domainLock", void 0);
+}), __metadata('design:type', Array)], Options.prototype, "domainLock", void 0);
 __decorate([class_validator_1.IsArray(), class_validator_1.ArrayUnique(), class_validator_1.IsString({
     each: true
-}), __metadata("design:type", Array)], Options.prototype, "reservedNames", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "rotateStringArray", void 0);
-__decorate([class_validator_1.IsNumber(), __metadata("design:type", Number)], Options.prototype, "seed", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "selfDefending", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "sourceMap", void 0);
+}), __metadata('design:type', Array)], Options.prototype, "reservedNames", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "rotateStringArray", void 0);
+__decorate([class_validator_1.IsNumber(), __metadata('design:type', Number)], Options.prototype, "seed", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "selfDefending", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "sourceMap", void 0);
 __decorate([class_validator_1.IsString(), class_validator_1.ValidateIf(function (options) {
     return Boolean(options.sourceMapBaseUrl);
 }), class_validator_1.IsUrl({
     require_protocol: true,
     require_valid_protocol: true
-}), __metadata("design:type", String)], Options.prototype, "sourceMapBaseUrl", void 0);
-__decorate([class_validator_1.IsString(), __metadata("design:type", String)], Options.prototype, "sourceMapFileName", void 0);
-__decorate([class_validator_1.IsIn(['inline', 'separate']), __metadata("design:type", String)], Options.prototype, "sourceMapMode", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "stringArray", void 0);
-__decorate([class_validator_1.IsIn([true, false, 'base64', 'rc4']), __metadata("design:type", Object)], Options.prototype, "stringArrayEncoding", void 0);
-__decorate([class_validator_1.IsNumber(), class_validator_1.Min(0), class_validator_1.Max(1), __metadata("design:type", Number)], Options.prototype, "stringArrayThreshold", void 0);
-__decorate([class_validator_1.IsBoolean(), __metadata("design:type", Boolean)], Options.prototype, "unicodeEscapeSequence", void 0);
-Options = Options_1 = __decorate([inversify_1.injectable(), __metadata("design:paramtypes", [Object])], Options);
+}), __metadata('design:type', String)], Options.prototype, "sourceMapBaseUrl", void 0);
+__decorate([class_validator_1.IsString(), __metadata('design:type', String)], Options.prototype, "sourceMapFileName", void 0);
+__decorate([class_validator_1.IsIn(['inline', 'separate']), __metadata('design:type', String)], Options.prototype, "sourceMapMode", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "stringArray", void 0);
+__decorate([class_validator_1.IsIn([true, false, 'base64', 'rc4']), __metadata('design:type', Object)], Options.prototype, "stringArrayEncoding", void 0);
+__decorate([class_validator_1.IsNumber(), class_validator_1.Min(0), class_validator_1.Max(1), __metadata('design:type', Number)], Options.prototype, "stringArrayThreshold", void 0);
+__decorate([class_validator_1.IsBoolean(), __metadata('design:type', Boolean)], Options.prototype, "unicodeEscapeSequence", void 0);
+Options = Options_1 = __decorate([inversify_1.injectable(), __metadata('design:paramtypes', [typeof (_a = typeof TInputOptions_1.TInputOptions !== 'undefined' && TInputOptions_1.TInputOptions) === 'function' && _a || Object])], Options);
 exports.Options = Options;
-var Options_1;
+var _a;
 
 /***/ },
 /* 85 */
@@ -5956,7 +5953,7 @@ var __param = undefined && undefined.__param || function (paramIndex, decorator)
 var inversify_1 = __webpack_require__(0);
 var ServiceIdentifiers_1 = __webpack_require__(1);
 var estraverse = __webpack_require__(5);
-var CalleeDataExtractors_1 = __webpack_require__(28);
+var CalleeDataExtractors_1 = __webpack_require__(29);
 var Node_1 = __webpack_require__(4);
 var NodeUtils_1 = __webpack_require__(9);
 var StackTraceAnalyzer = StackTraceAnalyzer_1 = function () {
@@ -6070,7 +6067,7 @@ var __metadata = undefined && undefined.__metadata || function (k, v) {
 };
 var inversify_1 = __webpack_require__(0);
 var estraverse = __webpack_require__(5);
-var AbstractCalleeDataExtractor_1 = __webpack_require__(24);
+var AbstractCalleeDataExtractor_1 = __webpack_require__(25);
 var Node_1 = __webpack_require__(4);
 var NodeUtils_1 = __webpack_require__(9);
 var FunctionDeclarationCalleeDataExtractor = function (_AbstractCalleeDataEx) {
@@ -6148,7 +6145,7 @@ var __metadata = undefined && undefined.__metadata || function (k, v) {
 };
 var inversify_1 = __webpack_require__(0);
 var estraverse = __webpack_require__(5);
-var AbstractCalleeDataExtractor_1 = __webpack_require__(24);
+var AbstractCalleeDataExtractor_1 = __webpack_require__(25);
 var Node_1 = __webpack_require__(4);
 var NodeUtils_1 = __webpack_require__(9);
 var FunctionExpressionCalleeDataExtractor = function (_AbstractCalleeDataEx) {
@@ -6231,7 +6228,7 @@ var inversify_1 = __webpack_require__(0);
 var estraverse = __webpack_require__(5);
 var Node_1 = __webpack_require__(4);
 var NodeUtils_1 = __webpack_require__(9);
-var AbstractCalleeDataExtractor_1 = __webpack_require__(24);
+var AbstractCalleeDataExtractor_1 = __webpack_require__(25);
 var ObjectExpressionCalleeDataExtractor = function (_AbstractCalleeDataEx) {
     _inherits(ObjectExpressionCalleeDataExtractor, _AbstractCalleeDataEx);
 
@@ -6378,6 +6375,7 @@ var __metadata = undefined && undefined.__metadata || function (k, v) {
 };
 var inversify_1 = __webpack_require__(0);
 var Initializable_1 = __webpack_require__(3);
+var RandomGeneratorUtils_1 = __webpack_require__(2);
 var ArrayStorage = function () {
     function ArrayStorage() {
         _classCallCheck(this, ArrayStorage);
@@ -6407,15 +6405,26 @@ var ArrayStorage = function () {
         value: function getStorage() {
             return this.storage;
         }
+    }, {
+        key: "getStorageId",
+        value: function getStorageId() {
+            return this.storageId;
+        }
     }, {
         key: "initialize",
         value: function initialize() {
             this.storage = [];
+            this.storageId = RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomString(6);
         }
     }, {
         key: "mergeWith",
         value: function mergeWith(storage) {
+            var mergeId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+
             this.storage = [].concat(_toConsumableArray(this.storage), _toConsumableArray(storage.getStorage()));
+            if (mergeId) {
+                this.storageId = storage.getStorageId();
+            }
         }
     }, {
         key: "set",
@@ -6426,6 +6435,7 @@ var ArrayStorage = function () {
 
     return ArrayStorage;
 }();
+__decorate([Initializable_1.initializable(), __metadata("design:type", String)], ArrayStorage.prototype, "storageId", void 0);
 __decorate([Initializable_1.initializable(), __metadata("design:type", Array)], ArrayStorage.prototype, "storage", void 0);
 ArrayStorage = __decorate([inversify_1.injectable(), __metadata("design:paramtypes", [])], ArrayStorage);
 exports.ArrayStorage = ArrayStorage;
@@ -6447,7 +6457,7 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen
 
 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
 
-var MapStorage_1 = __webpack_require__(32);
+var MapStorage_1 = __webpack_require__(33);
 
 var ControlFlowStorage = function (_MapStorage_1$MapStor) {
     _inherits(ControlFlowStorage, _MapStorage_1$MapStor);
@@ -6515,9 +6525,10 @@ var __param = undefined && undefined.__param || function (paramIndex, decorator)
 };
 var inversify_1 = __webpack_require__(0);
 var ServiceIdentifiers_1 = __webpack_require__(1);
-var CustomNodeGroups_1 = __webpack_require__(23);
-var MapStorage_1 = __webpack_require__(32);
-var CustomNodeGroupStorage_1 = function (_MapStorage_1$MapStor) {
+var CustomNodeGroups_1 = __webpack_require__(24);
+var MapStorage_1 = __webpack_require__(33);
+var RandomGeneratorUtils_1 = __webpack_require__(2);
+var CustomNodeGroupStorage = CustomNodeGroupStorage_1 = function (_MapStorage_1$MapStor) {
     _inherits(CustomNodeGroupStorage, _MapStorage_1$MapStor);
 
     function CustomNodeGroupStorage(customNodeGroupFactory, options) {
@@ -6537,6 +6548,7 @@ var CustomNodeGroupStorage_1 = function (_MapStorage_1$MapStor) {
             var _this2 = this;
 
             this.storage = new Map();
+            this.storageId = RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomString(6);
             CustomNodeGroupStorage_1.customNodeGroupsList.forEach(function (customNodeGroupName) {
                 var customNodeGroup = _this2.customNodeGroupFactory(customNodeGroupName);
                 if (!customNodeGroup) {
@@ -6549,10 +6561,10 @@ var CustomNodeGroupStorage_1 = function (_MapStorage_1$MapStor) {
 
     return CustomNodeGroupStorage;
 }(MapStorage_1.MapStorage);
-var CustomNodeGroupStorage = CustomNodeGroupStorage_1;
 CustomNodeGroupStorage.customNodeGroupsList = [CustomNodeGroups_1.CustomNodeGroups.ConsoleOutputCustomNodeGroup, CustomNodeGroups_1.CustomNodeGroups.DebugProtectionCustomNodeGroup, CustomNodeGroups_1.CustomNodeGroups.DomainLockCustomNodeGroup, CustomNodeGroups_1.CustomNodeGroups.SelfDefendingCustomNodeGroup, CustomNodeGroups_1.CustomNodeGroups.StringArrayCustomNodeGroup];
-CustomNodeGroupStorage = CustomNodeGroupStorage_1 = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers['Factory<ICustomNodeGroup>'])), __param(1, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata('design:paramtypes', [Function, Object])], CustomNodeGroupStorage);
+CustomNodeGroupStorage = CustomNodeGroupStorage_1 = __decorate([inversify_1.injectable(), __param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers['Factory<ICustomNodeGroup>'])), __param(1, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), __metadata("design:paramtypes", [Function, Object])], CustomNodeGroupStorage);
 exports.CustomNodeGroupStorage = CustomNodeGroupStorage;
+var CustomNodeGroupStorage_1;
 
 /***/ },
 /* 94 */
@@ -6563,6 +6575,8 @@ exports.CustomNodeGroupStorage = CustomNodeGroupStorage;
 
 var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
 
+var _get = (function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } });
+
 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
 
 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@@ -6584,6 +6598,7 @@ var __metadata = undefined && undefined.__metadata || function (k, v) {
 };
 var inversify_1 = __webpack_require__(0);
 var ArrayStorage_1 = __webpack_require__(91);
+var RandomGeneratorUtils_1 = __webpack_require__(2);
 var Utils_1 = __webpack_require__(6);
 var StringArrayStorage = function (_ArrayStorage_1$Array) {
     _inherits(StringArrayStorage, _ArrayStorage_1$Array);
@@ -6598,6 +6613,16 @@ var StringArrayStorage = function (_ArrayStorage_1$Array) {
     }
 
     _createClass(StringArrayStorage, [{
+        key: "initialize",
+        value: function initialize() {
+            for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+                args[_key] = arguments[_key];
+            }
+
+            _get(StringArrayStorage.prototype.__proto__ || Object.getPrototypeOf(StringArrayStorage.prototype), "initialize", this).call(this, args);
+            this.storageId = RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomVariableName(4, false);
+        }
+    }, {
         key: "rotateArray",
         value: function rotateArray(rotationValue) {
             this.storage = Utils_1.Utils.arrayRotate(this.storage, rotationValue);

+ 1 - 1
package.json

@@ -51,7 +51,7 @@
     "@types/string-template": "1.0.2",
     "awesome-typescript-loader": "3.0.0-beta.17",
     "babel-cli": "6.18.0",
-    "babel-loader": "6.2.9",
+    "babel-loader": "6.2.10",
     "babel-preset-es2015": "6.18.0",
     "chai": "3.5.0",
     "coveralls": "2.11.15",

+ 2 - 10
src/custom-nodes/control-flow-storage-nodes/ControlFlowStorageNode.ts

@@ -21,12 +21,6 @@ export class ControlFlowStorageNode extends AbstractCustomNode {
     @initializable()
     private controlFlowStorage: IStorage <ICustomNode>;
 
-    /**
-     * @type {string}
-     */
-    @initializable()
-    private controlFlowStorageName: string;
-
     /**
      * @param options
      */
@@ -38,11 +32,9 @@ export class ControlFlowStorageNode extends AbstractCustomNode {
 
     /**
      * @param controlFlowStorage
-     * @param controlFlowStorageName
      */
-    public initialize (controlFlowStorage: IStorage <ICustomNode>, controlFlowStorageName: string): void {
+    public initialize (controlFlowStorage: IStorage <ICustomNode>): void {
         this.controlFlowStorage = controlFlowStorage;
-        this.controlFlowStorageName = controlFlowStorageName;
     }
 
     /**
@@ -51,7 +43,7 @@ export class ControlFlowStorageNode extends AbstractCustomNode {
     protected getTemplate (): string {
         return format(ControlFlowStorageTemplate(), {
             controlFlowStorage: this.controlFlowStorage.toString(),
-            controlFlowStorageName: this.controlFlowStorageName
+            controlFlowStorageName: this.controlFlowStorage.getStorageId()
         });
     }
 }

+ 7 - 15
src/custom-nodes/string-array-nodes/StringArrayCallsWrapper.ts

@@ -3,7 +3,6 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 import * as format from 'string-template';
 
-import { ICustomNodeWithIdentifier } from '../../interfaces/custom-nodes/ICustomNodeWithIdentifier';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IStorage } from '../../interfaces/storages/IStorage';
 
@@ -24,24 +23,24 @@ import { AbstractCustomNode } from '../AbstractCustomNode';
 import { JavaScriptObfuscator } from '../../JavaScriptObfuscator';
 
 @injectable()
-export class StringArrayCallsWrapper extends AbstractCustomNode implements ICustomNodeWithIdentifier {
+export class StringArrayCallsWrapper extends AbstractCustomNode {
     /**
      * @type {IStorage <string>}
      */
     @initializable()
-    private stringArray: IStorage <string>;
+    private stringArrayStorage: IStorage <string>;
 
     /**
      * @type {string}
      */
     @initializable()
-    private stringArrayCallsWrapperName: string;
+    private stringArrayName: string;
 
     /**
      * @type {string}
      */
     @initializable()
-    private stringArrayName: string;
+    private stringArrayCallsWrapperName: string;
 
     /**
      * @param options
@@ -53,27 +52,20 @@ export class StringArrayCallsWrapper extends AbstractCustomNode implements ICust
     }
 
     /**
-     * @param stringArray
+     * @param stringArrayStorage
      * @param stringArrayName
      * @param stringArrayCallsWrapperName
      */
     public initialize (
-        stringArray: IStorage <string>,
+        stringArrayStorage: IStorage <string>,
         stringArrayName: string,
         stringArrayCallsWrapperName: string
     ): void {
-        this.stringArray = stringArray;
+        this.stringArrayStorage = stringArrayStorage;
         this.stringArrayName = stringArrayName;
         this.stringArrayCallsWrapperName = stringArrayCallsWrapperName;
     }
 
-    /**
-     * @returns {string}
-     */
-    public getNodeIdentifier (): string {
-        return this.stringArrayCallsWrapperName;
-    };
-
     /**
      * @returns {string}
      */

+ 6 - 11
src/custom-nodes/string-array-nodes/StringArrayNode.ts

@@ -17,16 +17,11 @@ import { StringArrayStorage } from '../../storages/string-array/StringArrayStora
 
 @injectable()
 export class StringArrayNode extends AbstractCustomNode {
-    /**
-     * @type {number}
-     */
-    public static ARRAY_RANDOM_LENGTH: number = 4;
-
     /**
      * @type {IStorage <string>}
      */
     @initializable()
-    private stringArray: IStorage <string>;
+    private stringArrayStorage: IStorage <string>;
 
     /**
      * @type {string}
@@ -50,16 +45,16 @@ export class StringArrayNode extends AbstractCustomNode {
     }
 
     /**
-     * @param stringArray
+     * @param stringArrayStorage
      * @param stringArrayName
      * @param stringArrayRotateValue
      */
     public initialize (
-        stringArray: IStorage <string>,
+        stringArrayStorage: IStorage <string>,
         stringArrayName: string,
         stringArrayRotateValue: number
     ): void {
-        this.stringArray = stringArray;
+        this.stringArrayStorage = stringArrayStorage;
         this.stringArrayName = stringArrayName;
         this.stringArrayRotateValue = stringArrayRotateValue;
     }
@@ -68,7 +63,7 @@ export class StringArrayNode extends AbstractCustomNode {
      * @returns {TStatement[]}
      */
     public getNode (): TStatement[] {
-        (<StringArrayStorage>this.stringArray).rotateArray(this.stringArrayRotateValue);
+        (<StringArrayStorage>this.stringArrayStorage).rotateArray(this.stringArrayRotateValue);
 
         return super.getNode();
     }
@@ -79,7 +74,7 @@ export class StringArrayNode extends AbstractCustomNode {
     protected getTemplate (): string {
         return format(StringArrayTemplate(), {
             stringArrayName: this.stringArrayName,
-            stringArray: this.stringArray.toString()
+            stringArray: this.stringArrayStorage.toString()
         });
     }
 }

+ 4 - 4
src/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.ts

@@ -24,7 +24,7 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
      * @type {IStorage <string>}
      */
     @initializable()
-    private stringArray: IStorage <string>;
+    private stringArrayStorage: IStorage <string>;
 
     /**
      * @type {string}
@@ -48,16 +48,16 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
     }
 
     /**
-     * @param stringArray
+     * @param stringArrayStorage
      * @param stringArrayName
      * @param stringArrayRotateValue
      */
     public initialize (
-        stringArray: IStorage <string>,
+        stringArrayStorage: IStorage <string>,
         stringArrayName: string,
         stringArrayRotateValue: number
     ): void {
-        this.stringArray = stringArray;
+        this.stringArrayStorage = stringArrayStorage;
         this.stringArrayName = stringArrayName;
         this.stringArrayRotateValue = stringArrayRotateValue;
     }

+ 6 - 4
src/custom-nodes/string-array-nodes/group/StringArrayCustomNodeGroup.ts

@@ -16,11 +16,10 @@ import { initializable } from '../../../decorators/Initializable';
 import { CustomNodes } from '../../../enums/container/CustomNodes';
 import { ObfuscationEvents } from '../../../enums/ObfuscationEvents';
 
-import { StringArrayNode } from '../StringArrayNode';
-
 import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
 import { NodeAppender } from '../../../node/NodeAppender';
 import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
+import { Utils } from '../../../utils/Utils';
 
 @injectable()
 export class StringArrayCustomNodeGroup extends AbstractCustomNodeGroup {
@@ -106,8 +105,11 @@ export class StringArrayCustomNodeGroup extends AbstractCustomNodeGroup {
         const stringArrayCallsWrapper: ICustomNode = this.customNodeFactory(CustomNodes.StringArrayCallsWrapper);
         const stringArrayRotateFunctionNode: ICustomNode = this.customNodeFactory(CustomNodes.StringArrayRotateFunctionNode);
 
-        const stringArrayName: string = RandomGeneratorUtils.getRandomVariableName(StringArrayNode.ARRAY_RANDOM_LENGTH);
-        const stringArrayCallsWrapperName: string = RandomGeneratorUtils.getRandomVariableName(StringArrayNode.ARRAY_RANDOM_LENGTH);
+        const reversedStorageId = Array.from(this.stringArrayStorage.getStorageId()).reverse().join('');
+        const stringArrayName: string = `_${Utils.hexadecimalPrefix}${this.stringArrayStorage.getStorageId()}`;
+        const stringArrayCallsWrapperName: string = `_${Utils.hexadecimalPrefix}${reversedStorageId}`;
+
+        console.log(stringArrayCallsWrapperName);
 
         let stringArrayRotateValue: number;
 

+ 0 - 8
src/interfaces/custom-nodes/ICustomNodeWithIdentifier.d.ts

@@ -1,8 +0,0 @@
-import { ICustomNode } from './ICustomNode';
-
-export interface ICustomNodeWithIdentifier extends ICustomNode {
-    /**
-     * @returns string
-     */
-    getNodeIdentifier (): string;
-}

+ 0 - 7
src/interfaces/node-transformers/IControlFlowNodeMetadata.d.ts

@@ -1,7 +0,0 @@
-import { ICustomNode } from '../custom-nodes/ICustomNode';
-import { IStorage } from '../storages/IStorage';
-
-export interface IControlFlowNodeMetadata {
-    controlFlowStorage: IStorage<ICustomNode>;
-    controlFlowStorageNodeName: string;
-}

+ 1 - 3
src/interfaces/node-transformers/IControlFlowReplacer.d.ts

@@ -8,13 +8,11 @@ export interface IControlFlowReplacer {
      * @param node
      * @param parentNode
      * @param controlFlowStorage
-     * @param controlFlowStorageCustomNodeName
      * @returns ESTree.Node
      */
     replace (
         node: ESTree.Node,
         parentNode: ESTree.Node,
-        controlFlowStorage: IStorage <ICustomNode>,
-        controlFlowStorageCustomNodeName: string
+        controlFlowStorage: IStorage <ICustomNode>
     ): ESTree.Node;
 }

+ 7 - 1
src/interfaces/storages/IStorage.d.ts

@@ -23,6 +23,11 @@ export interface IStorage <T> extends IInitializable {
      */
     getStorage (): any;
 
+    /**
+     * @returns string
+     */
+    getStorageId (): string;
+
     /**
      * @param args
      */
@@ -30,8 +35,9 @@ export interface IStorage <T> extends IInitializable {
 
     /**
      * @param storage
+     * @param mergeId
      */
-    mergeWith (storage: this): void;
+    mergeWith (storage: this, mergeId: boolean): void;
 
     /**
      * @param key

+ 9 - 22
src/node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer.ts

@@ -11,7 +11,6 @@ import { TCustomNodeFactory } from '../../types/container/TCustomNodeFactory';
 import { TNodeWithBlockStatement } from '../../types/node/TNodeWithBlockStatement';
 import { TStatement } from '../../types/node/TStatement';
 
-import { IControlFlowNodeMetadata } from '../../interfaces/node-transformers/IControlFlowNodeMetadata';
 import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IStorage } from '../../interfaces/storages/IStorage';
@@ -51,9 +50,9 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
     private static readonly hostNodeSearchMaxDepth: number = 10;
 
     /**
-     * @type {Map<ESTree.Node, IControlFlowNodeMetadata>}
+     * @type {Map<ESTree.Node, IStorage<ICustomNode>>}
      */
-    private controlFlowData: Map <ESTree.Node, IControlFlowNodeMetadata> = new Map <ESTree.Node, IControlFlowNodeMetadata> ();
+    private controlFlowData: Map <ESTree.Node, IStorage<ICustomNode>> = new Map <ESTree.Node, IStorage<ICustomNode>> ();
 
     /**
      * @type {TStatement[][]}
@@ -151,34 +150,22 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
         const controlFlowStorage: IStorage <ICustomNode> = this.controlFlowStorageFactory();
         const hostNode: TNodeWithBlockStatement = FunctionControlFlowTransformer.getHostNode(functionNode);
 
-        let controlFlowStorageNodeName: string = RandomGeneratorUtils.getRandomVariableName(6);
-
         if (!this.controlFlowData.has(hostNode)) {
-            this.controlFlowData.set(hostNode, {
-                controlFlowStorage,
-                controlFlowStorageNodeName
-            });
+            this.controlFlowData.set(hostNode, controlFlowStorage);
         } else {
             hostNode.body = <ESTree.Statement[]>FunctionControlFlowTransformer
                 .removeOldControlFlowNodeFromHostNodeBody(hostNode.body, this.controlFlowNodesList);
 
-            const {
-                controlFlowStorage: hostControlFlowStorage,
-                controlFlowStorageNodeName: hostControlFlowStorageNodeName
-            } = <IControlFlowNodeMetadata>this.controlFlowData.get(hostNode);
+            const hostControlFlowStorage: IStorage<ICustomNode> = <IStorage<ICustomNode>>this.controlFlowData.get(hostNode);
 
-            controlFlowStorage.mergeWith(hostControlFlowStorage);
-            controlFlowStorageNodeName = hostControlFlowStorageNodeName;
+            controlFlowStorage.mergeWith(hostControlFlowStorage, true);
 
-            this.controlFlowData.set(hostNode, {
-                controlFlowStorage,
-                controlFlowStorageNodeName: hostControlFlowStorageNodeName
-            });
+            this.controlFlowData.set(hostNode, controlFlowStorage);
         }
 
         estraverse.replace(functionNode.body, {
             enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
-                if (Math.random() > FunctionControlFlowTransformer.controlFlowReplacersThreshold) {
+                if (RandomGeneratorUtils.getRandomFloat(0, 1) > FunctionControlFlowTransformer.controlFlowReplacersThreshold) {
                     return;
                 }
 
@@ -191,7 +178,7 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
 
                 return {
                     ...this.controlFlowReplacerFactory(controlFlowReplacerName)
-                        .replace(node, parentNode, controlFlowStorage, controlFlowStorageNodeName),
+                        .replace(node, parentNode, controlFlowStorage),
                     parentNode
                 };
             }
@@ -203,7 +190,7 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
 
         const controlFlowStorageCustomNode: ICustomNode = this.customNodeFactory(CustomNodes.ControlFlowStorageNode);
 
-        controlFlowStorageCustomNode.initialize(controlFlowStorage, controlFlowStorageNodeName);
+        controlFlowStorageCustomNode.initialize(controlFlowStorage);
 
         const controlFlowStorageNode: TStatement[] = controlFlowStorageCustomNode.getNode();
 

+ 1 - 3
src/node-transformers/node-control-flow-transformers/control-flow-replacers/AbstractControlFlowReplacer.ts

@@ -40,13 +40,11 @@ export abstract class AbstractControlFlowReplacer implements IControlFlowReplace
      * @param node
      * @param parentNode
      * @param controlFlowStorage
-     * @param controlFlowStorageCustomNodeName
      * @returns {ESTree.Node}
      */
     public abstract replace (
         node: ESTree.Node,
         parentNode: ESTree.Node,
-        controlFlowStorage: IStorage <ICustomNode>,
-        controlFlowStorageCustomNodeName: string
+        controlFlowStorage: IStorage <ICustomNode>
     ): ESTree.Node;
 }

+ 6 - 5
src/node-transformers/node-control-flow-transformers/control-flow-replacers/BinaryExpressionControlFlowReplacer.ts

@@ -3,7 +3,6 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 import * as escodegen from 'escodegen';
 import * as ESTree from 'estree';
-import * as _ from 'lodash';
 
 import { TCustomNodeFactory } from '../../../types/container/TCustomNodeFactory';
 import { TStatement } from '../../../types/node/TStatement';
@@ -16,6 +15,7 @@ import { CustomNodes } from '../../../enums/container/CustomNodes';
 
 import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
 import { Node } from '../../../node/Node';
+import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
 
 @injectable()
 export class BinaryExpressionControlFlowReplacer extends AbstractControlFlowReplacer {
@@ -67,9 +67,9 @@ export class BinaryExpressionControlFlowReplacer extends AbstractControlFlowRepl
     public replace (
         binaryExpressionNode: ESTree.BinaryExpression,
         parentNode: ESTree.Node,
-        controlFlowStorage: IStorage <ICustomNode>,
-        controlFlowStorageCustomNodeName: string
+        controlFlowStorage: IStorage <ICustomNode>
     ): ESTree.Node {
+        const controlFlowStorageCustomNodeName: string = controlFlowStorage.getStorageId();
         const binaryExpressionFunctionNode: ICustomNode = this.customNodeFactory(CustomNodes.BinaryExpressionFunctionNode);
         const binaryExpressionOperatorKeys: {
             [key: string]: string[]
@@ -85,10 +85,11 @@ export class BinaryExpressionControlFlowReplacer extends AbstractControlFlowRepl
         binaryExpressionFunctionNode.initialize(binaryExpressionNode.operator);
 
         if (
-            Math.random() > BinaryExpressionControlFlowReplacer.useExistingOperatorKeyThreshold &&
+            RandomGeneratorUtils.getRandomFloat(0, 1) > BinaryExpressionControlFlowReplacer.useExistingOperatorKeyThreshold &&
             binaryExpressionOperatorKeys[binaryExpressionNode.operator].length
         ) {
-            key = _.sample(binaryExpressionOperatorKeys[binaryExpressionNode.operator]);
+            key = RandomGeneratorUtils.getRandomGenerator()
+                .pickone(binaryExpressionOperatorKeys[binaryExpressionNode.operator]);
         } else {
             binaryExpressionOperatorKeys[binaryExpressionNode.operator].push(key);
             this.existingBinaryExpressionKeys.set(controlFlowStorageCustomNodeName, binaryExpressionOperatorKeys);

+ 4 - 12
src/node-transformers/node-obfuscators/replacers/StringLiteralReplacer.ts

@@ -1,9 +1,7 @@
 import { injectable, inject } from 'inversify';
 import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
-import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { ICustomNodeGroup } from '../../../interfaces/custom-nodes/ICustomNodeGroup';
-import { ICustomNodeWithIdentifier } from '../../../interfaces/custom-nodes/ICustomNodeWithIdentifier';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IStorage } from '../../../interfaces/storages/IStorage';
 
@@ -11,8 +9,6 @@ import { StringArrayEncoding } from '../../../enums/StringArrayEncoding';
 
 import { AbstractReplacer } from './AbstractReplacer';
 import { CryptUtils } from '../../../utils/CryptUtils';
-import { CustomNodes } from '../../../enums/container/CustomNodes';
-import { CustomNodeGroups } from '../../../enums/container/CustomNodeGroups';
 import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
 import { Utils } from '../../../utils/Utils';
 
@@ -77,10 +73,6 @@ export class StringLiteralReplacer extends AbstractReplacer {
      * @returns {string}
      */
     private replaceStringLiteralWithStringArrayCall (value: string): string {
-        const stringArrayCustomNodeGroupNodes: Map <CustomNodes, ICustomNode> = this.customNodeGroupStorage
-            .get(CustomNodeGroups.StringArrayCustomNodeGroup)
-            .getCustomNodes();
-
         let rc4Key: string = '';
 
         switch (this.options.stringArrayEncoding) {
@@ -111,14 +103,14 @@ export class StringLiteralReplacer extends AbstractReplacer {
             this.stringArrayStorage.set(null, value);
         }
 
-        const stringArrayCallsWrapper: ICustomNodeWithIdentifier = <ICustomNodeWithIdentifier>stringArrayCustomNodeGroupNodes
-            .get(CustomNodes.StringArrayCallsWrapper);
+        const reversedStringArrayId: string = Array.from(this.stringArrayStorage.getStorageId()).reverse().join('');
+        const stringArrayStorageCallsWrapperName: string = `_${Utils.hexadecimalPrefix}${reversedStringArrayId}`;
         const hexadecimalIndex: string = `${Utils.hexadecimalPrefix}${Utils.decToHex(indexOfValue)}`;
 
         if (this.options.stringArrayEncoding === StringArrayEncoding.rc4) {
-            return `${stringArrayCallsWrapper.getNodeIdentifier()}('${hexadecimalIndex}', '${Utils.stringToUnicodeEscapeSequence(rc4Key)}')`;
+            return `${stringArrayStorageCallsWrapperName}('${hexadecimalIndex}', '${Utils.stringToUnicodeEscapeSequence(rc4Key)}')`;
         }
 
-        return `${stringArrayCallsWrapper.getNodeIdentifier()}('${hexadecimalIndex}')`;
+        return `${stringArrayStorageCallsWrapperName}('${hexadecimalIndex}')`;
     }
 }

+ 22 - 1
src/storages/ArrayStorage.ts

@@ -4,8 +4,16 @@ import { IStorage } from '../interfaces/storages/IStorage';
 
 import { initializable } from '../decorators/Initializable';
 
+import { RandomGeneratorUtils } from '../utils/RandomGeneratorUtils';
+
 @injectable()
 export abstract class ArrayStorage <T> implements IStorage <T> {
+    /**
+     * @type {string}
+     */
+    @initializable()
+    protected storageId: string;
+
     /**
      * @type {T[]}
      */
@@ -48,18 +56,31 @@ export abstract class ArrayStorage <T> implements IStorage <T> {
         return this.storage;
     }
 
+    /**
+     * @returns {string}
+     */
+    public getStorageId (): string {
+        return this.storageId;
+    }
+
     /**
      * @param args
      */
     public initialize (...args: any[]): void {
         this.storage = [];
+        this.storageId = RandomGeneratorUtils.getRandomString(6);
     }
 
     /**
      * @param storage
+     * @param mergeId
      */
-    public mergeWith (storage: this): void {
+    public mergeWith (storage: this, mergeId: boolean = false): void {
         this.storage = [...this.storage, ...storage.getStorage()];
+
+        if (mergeId) {
+            this.storageId = storage.getStorageId();
+        }
     }
 
     /**

+ 21 - 1
src/storages/MapStorage.ts

@@ -4,10 +4,17 @@ import { IStorage } from '../interfaces/storages/IStorage';
 
 import { initializable } from '../decorators/Initializable';
 
+import { RandomGeneratorUtils } from '../utils/RandomGeneratorUtils';
 import { Utils } from '../utils/Utils';
 
 @injectable()
 export abstract class MapStorage <T> implements IStorage <T> {
+    /**
+     * @type {string}
+     */
+    @initializable()
+    protected storageId: string;
+
     /**
      * @type {Map <string | number, T>}
      */
@@ -50,18 +57,31 @@ export abstract class MapStorage <T> implements IStorage <T> {
         return this.storage;
     }
 
+    /**
+     * @returns {string}
+     */
+    public getStorageId (): string {
+        return this.storageId;
+    }
+
     /**
      * @param args
      */
     public initialize (...args: any[]): void {
         this.storage = new Map <string | number, T> ();
+        this.storageId = RandomGeneratorUtils.getRandomString(6);
     }
 
     /**
      * @param storage
+     * @param mergeId
      */
-    public mergeWith (storage: this): void {
+    public mergeWith (storage: this, mergeId: boolean = false): void {
         this.storage = new Map <string | number, T> ([...this.storage, ...storage.getStorage()]);
+
+        if (mergeId) {
+            this.storageId = storage.getStorageId();
+        }
     }
 
     /**

+ 2 - 0
src/storages/custom-node-group/CustomNodeGroupStorage.ts

@@ -9,6 +9,7 @@ import { IOptions } from '../../interfaces/options/IOptions';
 import { CustomNodeGroups } from '../../enums/container/CustomNodeGroups';
 
 import { MapStorage } from '../MapStorage';
+import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
 
 @injectable()
 export class CustomNodeGroupStorage extends MapStorage <ICustomNodeGroup> {
@@ -51,6 +52,7 @@ export class CustomNodeGroupStorage extends MapStorage <ICustomNodeGroup> {
 
     public initialize (): void {
         this.storage = new Map <string, ICustomNodeGroup> ();
+        this.storageId = RandomGeneratorUtils.getRandomString(6);
 
         CustomNodeGroupStorage.customNodeGroupsList.forEach((customNodeGroupName: CustomNodeGroups) => {
             const customNodeGroup: ICustomNodeGroup = this.customNodeGroupFactory(

+ 10 - 0
src/storages/string-array/StringArrayStorage.ts

@@ -1,6 +1,7 @@
 import { injectable } from 'inversify';
 
 import { ArrayStorage } from '../ArrayStorage';
+import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
 import { Utils } from '../../utils/Utils';
 
 @injectable()
@@ -11,6 +12,15 @@ export class StringArrayStorage extends ArrayStorage <string> {
         this.initialize();
     }
 
+    /**
+     * @param args
+     */
+    public initialize (...args: any[]): void {
+        super.initialize(args);
+
+        this.storageId = RandomGeneratorUtils.getRandomVariableName(4, false);
+    }
+
     /**
      * @param rotationValue
      */

+ 6 - 4
src/utils/RandomGeneratorUtils.ts

@@ -67,13 +67,15 @@ export class RandomGeneratorUtils {
 
     /**
      * @param length
+     * @param withPrefix
      * @returns {string}
      */
-    public static getRandomVariableName (length: number = 6): string {
-        const rangeMinInteger: number = 10000,
-            rangeMaxInteger: number = 99999999;
+    public static getRandomVariableName (length: number = 6, withPrefix: boolean = true): string {
+        const prefix: string = withPrefix ? `_${Utils.hexadecimalPrefix}` : '';
+        const rangeMinInteger: number = 10000;
+        const rangeMaxInteger: number = 99999999;
 
-        return `_${Utils.hexadecimalPrefix}${(
+        return `${prefix}${(
             Utils.decToHex(
                 RandomGeneratorUtils.getRandomInteger(rangeMinInteger, rangeMaxInteger)
             )