Explorar o código

added BlockStatementControlFlowReplacerNode and fixes of incorrect parentizing of control flow transformed nodes

sanex3339 %!s(int64=8) %!d(string=hai) anos
pai
achega
105ad55c06

+ 120 - 40
dist/index.js

@@ -989,21 +989,22 @@ module.exports = require("estraverse");
 var CustomNodes;
 (function (CustomNodes) {
     CustomNodes[CustomNodes["BinaryExpressionFunctionNode"] = 0] = "BinaryExpressionFunctionNode";
-    CustomNodes[CustomNodes["CallExpressionControlFlowStorageCallNode"] = 1] = "CallExpressionControlFlowStorageCallNode";
-    CustomNodes[CustomNodes["CallExpressionFunctionNode"] = 2] = "CallExpressionFunctionNode";
-    CustomNodes[CustomNodes["ControlFlowStorageNode"] = 3] = "ControlFlowStorageNode";
-    CustomNodes[CustomNodes["ConsoleOutputDisableExpressionNode"] = 4] = "ConsoleOutputDisableExpressionNode";
-    CustomNodes[CustomNodes["DebugProtectionFunctionCallNode"] = 5] = "DebugProtectionFunctionCallNode";
-    CustomNodes[CustomNodes["DebugProtectionFunctionIntervalNode"] = 6] = "DebugProtectionFunctionIntervalNode";
-    CustomNodes[CustomNodes["DebugProtectionFunctionNode"] = 7] = "DebugProtectionFunctionNode";
-    CustomNodes[CustomNodes["DomainLockNode"] = 8] = "DomainLockNode";
-    CustomNodes[CustomNodes["ExpressionWithOperatorControlFlowStorageCallNode"] = 9] = "ExpressionWithOperatorControlFlowStorageCallNode";
-    CustomNodes[CustomNodes["LogicalExpressionFunctionNode"] = 10] = "LogicalExpressionFunctionNode";
-    CustomNodes[CustomNodes["NodeCallsControllerFunctionNode"] = 11] = "NodeCallsControllerFunctionNode";
-    CustomNodes[CustomNodes["SelfDefendingUnicodeNode"] = 12] = "SelfDefendingUnicodeNode";
-    CustomNodes[CustomNodes["StringArrayCallsWrapper"] = 13] = "StringArrayCallsWrapper";
-    CustomNodes[CustomNodes["StringArrayNode"] = 14] = "StringArrayNode";
-    CustomNodes[CustomNodes["StringArrayRotateFunctionNode"] = 15] = "StringArrayRotateFunctionNode";
+    CustomNodes[CustomNodes["BlockStatementControlFlowReplacerNode"] = 1] = "BlockStatementControlFlowReplacerNode";
+    CustomNodes[CustomNodes["CallExpressionControlFlowStorageCallNode"] = 2] = "CallExpressionControlFlowStorageCallNode";
+    CustomNodes[CustomNodes["CallExpressionFunctionNode"] = 3] = "CallExpressionFunctionNode";
+    CustomNodes[CustomNodes["ControlFlowStorageNode"] = 4] = "ControlFlowStorageNode";
+    CustomNodes[CustomNodes["ConsoleOutputDisableExpressionNode"] = 5] = "ConsoleOutputDisableExpressionNode";
+    CustomNodes[CustomNodes["DebugProtectionFunctionCallNode"] = 6] = "DebugProtectionFunctionCallNode";
+    CustomNodes[CustomNodes["DebugProtectionFunctionIntervalNode"] = 7] = "DebugProtectionFunctionIntervalNode";
+    CustomNodes[CustomNodes["DebugProtectionFunctionNode"] = 8] = "DebugProtectionFunctionNode";
+    CustomNodes[CustomNodes["DomainLockNode"] = 9] = "DomainLockNode";
+    CustomNodes[CustomNodes["ExpressionWithOperatorControlFlowStorageCallNode"] = 10] = "ExpressionWithOperatorControlFlowStorageCallNode";
+    CustomNodes[CustomNodes["LogicalExpressionFunctionNode"] = 11] = "LogicalExpressionFunctionNode";
+    CustomNodes[CustomNodes["NodeCallsControllerFunctionNode"] = 12] = "NodeCallsControllerFunctionNode";
+    CustomNodes[CustomNodes["SelfDefendingUnicodeNode"] = 13] = "SelfDefendingUnicodeNode";
+    CustomNodes[CustomNodes["StringArrayCallsWrapper"] = 14] = "StringArrayCallsWrapper";
+    CustomNodes[CustomNodes["StringArrayNode"] = 15] = "StringArrayNode";
+    CustomNodes[CustomNodes["StringArrayRotateFunctionNode"] = 16] = "StringArrayRotateFunctionNode";
 })(CustomNodes = exports.CustomNodes || (exports.CustomNodes = {}));
 
 /***/ },
@@ -2953,6 +2954,7 @@ var DomainLockCustomNodeGroup_1 = __webpack_require__(79);
 var SelfDefendingCustomNodeGroup_1 = __webpack_require__(82);
 var StringArrayCustomNodeGroup_1 = __webpack_require__(86);
 var BinaryExpressionFunctionNode_1 = __webpack_require__(68);
+var BlockStatementControlFlowReplacerNode_1 = __webpack_require__(150);
 var CallExpressionControlFlowStorageCallNode_1 = __webpack_require__(71);
 var CallExpressionFunctionNode_1 = __webpack_require__(69);
 var ControlFlowStorageNode_1 = __webpack_require__(72);
@@ -2970,6 +2972,7 @@ var StringArrayNode_1 = __webpack_require__(84);
 var StringArrayRotateFunctionNode_1 = __webpack_require__(85);
 exports.customNodesModule = new inversify_1.ContainerModule(function (bind) {
     bind(ServiceIdentifiers_1.ServiceIdentifiers.Newable__ICustomNode).toConstructor(BinaryExpressionFunctionNode_1.BinaryExpressionFunctionNode).whenTargetNamed(CustomNodes_1.CustomNodes.BinaryExpressionFunctionNode);
+    bind(ServiceIdentifiers_1.ServiceIdentifiers.Newable__ICustomNode).toConstructor(BlockStatementControlFlowReplacerNode_1.BlockStatementControlFlowReplacerNode).whenTargetNamed(CustomNodes_1.CustomNodes.BlockStatementControlFlowReplacerNode);
     bind(ServiceIdentifiers_1.ServiceIdentifiers.Newable__ICustomNode).toConstructor(CallExpressionControlFlowStorageCallNode_1.CallExpressionControlFlowStorageCallNode).whenTargetNamed(CustomNodes_1.CustomNodes.CallExpressionControlFlowStorageCallNode);
     bind(ServiceIdentifiers_1.ServiceIdentifiers.Newable__ICustomNode).toConstructor(CallExpressionFunctionNode_1.CallExpressionFunctionNode).whenTargetNamed(CustomNodes_1.CustomNodes.CallExpressionFunctionNode);
     bind(ServiceIdentifiers_1.ServiceIdentifiers.Newable__ICustomNode).toConstructor(ControlFlowStorageNode_1.ControlFlowStorageNode).whenTargetNamed(CustomNodes_1.CustomNodes.ControlFlowStorageNode);
@@ -3410,6 +3413,7 @@ var ServiceIdentifiers_1 = __webpack_require__(4);
 var Initializable_1 = __webpack_require__(10);
 var AbstractCustomNode_1 = __webpack_require__(13);
 var Nodes_1 = __webpack_require__(23);
+var NodeUtils_1 = __webpack_require__(9);
 var RandomGeneratorUtils_1 = __webpack_require__(8);
 var BinaryExpressionFunctionNode = function (_AbstractCustomNode_) {
     (0, _inherits3.default)(BinaryExpressionFunctionNode, _AbstractCustomNode_);
@@ -3427,7 +3431,9 @@ var BinaryExpressionFunctionNode = function (_AbstractCustomNode_) {
     }, {
         key: "getNodeStructure",
         value: function getNodeStructure() {
-            return [Nodes_1.Nodes.getFunctionDeclarationNode(RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomVariableName(1, true, false), [Nodes_1.Nodes.getIdentifierNode('x'), Nodes_1.Nodes.getIdentifierNode('y')], Nodes_1.Nodes.getBlockStatementNode([Nodes_1.Nodes.getReturnStatementNode(Nodes_1.Nodes.getBinaryExpressionNode(this.operator, Nodes_1.Nodes.getIdentifierNode('x'), Nodes_1.Nodes.getIdentifierNode('y')))]))];
+            var structure = Nodes_1.Nodes.getFunctionDeclarationNode(RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomVariableName(1, true, false), [Nodes_1.Nodes.getIdentifierNode('x'), Nodes_1.Nodes.getIdentifierNode('y')], Nodes_1.Nodes.getBlockStatementNode([Nodes_1.Nodes.getReturnStatementNode(Nodes_1.Nodes.getBinaryExpressionNode(this.operator, Nodes_1.Nodes.getIdentifierNode('x'), Nodes_1.Nodes.getIdentifierNode('y')))]));
+            NodeUtils_1.NodeUtils.parentize(structure);
+            return [structure];
         }
     }]);
     return BinaryExpressionFunctionNode;
@@ -3471,6 +3477,7 @@ var ServiceIdentifiers_1 = __webpack_require__(4);
 var Initializable_1 = __webpack_require__(10);
 var AbstractCustomNode_1 = __webpack_require__(13);
 var Nodes_1 = __webpack_require__(23);
+var NodeUtils_1 = __webpack_require__(9);
 var RandomGeneratorUtils_1 = __webpack_require__(8);
 var CallExpressionFunctionNode = function (_AbstractCustomNode_) {
     (0, _inherits3.default)(CallExpressionFunctionNode, _AbstractCustomNode_);
@@ -3494,7 +3501,9 @@ var CallExpressionFunctionNode = function (_AbstractCustomNode_) {
             for (var i = 0; i < argumentsLength; i++) {
                 params.push(Nodes_1.Nodes.getIdentifierNode("param" + (i + 1)));
             }
-            return [Nodes_1.Nodes.getFunctionDeclarationNode(RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomVariableName(1, true, false), [calleeIdentifier].concat(params), Nodes_1.Nodes.getBlockStatementNode([Nodes_1.Nodes.getReturnStatementNode(Nodes_1.Nodes.getCallExpressionNode(calleeIdentifier, params))]))];
+            var structure = Nodes_1.Nodes.getFunctionDeclarationNode(RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomVariableName(1, true, false), [calleeIdentifier].concat(params), Nodes_1.Nodes.getBlockStatementNode([Nodes_1.Nodes.getReturnStatementNode(Nodes_1.Nodes.getCallExpressionNode(calleeIdentifier, params))]));
+            NodeUtils_1.NodeUtils.parentize(structure);
+            return [structure];
         }
     }]);
     return CallExpressionFunctionNode;
@@ -3539,6 +3548,7 @@ var Initializable_1 = __webpack_require__(10);
 var AbstractCustomNode_1 = __webpack_require__(13);
 var Nodes_1 = __webpack_require__(23);
 var RandomGeneratorUtils_1 = __webpack_require__(8);
+var NodeUtils_1 = __webpack_require__(9);
 var LogicalExpressionFunctionNode = function (_AbstractCustomNode_) {
     (0, _inherits3.default)(LogicalExpressionFunctionNode, _AbstractCustomNode_);
 
@@ -3555,7 +3565,9 @@ var LogicalExpressionFunctionNode = function (_AbstractCustomNode_) {
     }, {
         key: "getNodeStructure",
         value: function getNodeStructure() {
-            return [Nodes_1.Nodes.getFunctionDeclarationNode(RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomVariableName(1, true, false), [Nodes_1.Nodes.getIdentifierNode('x'), Nodes_1.Nodes.getIdentifierNode('y')], Nodes_1.Nodes.getBlockStatementNode([Nodes_1.Nodes.getReturnStatementNode(Nodes_1.Nodes.getLogicalExpressionNode(this.operator, Nodes_1.Nodes.getIdentifierNode('x'), Nodes_1.Nodes.getIdentifierNode('y')))]))];
+            var structure = Nodes_1.Nodes.getFunctionDeclarationNode(RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomVariableName(1, true, false), [Nodes_1.Nodes.getIdentifierNode('x'), Nodes_1.Nodes.getIdentifierNode('y')], Nodes_1.Nodes.getBlockStatementNode([Nodes_1.Nodes.getReturnStatementNode(Nodes_1.Nodes.getLogicalExpressionNode(this.operator, Nodes_1.Nodes.getIdentifierNode('x'), Nodes_1.Nodes.getIdentifierNode('y')))]));
+            NodeUtils_1.NodeUtils.parentize(structure);
+            return [structure];
         }
     }]);
     return LogicalExpressionFunctionNode;
@@ -3603,6 +3615,7 @@ var ServiceIdentifiers_1 = __webpack_require__(4);
 var Initializable_1 = __webpack_require__(10);
 var AbstractCustomNode_1 = __webpack_require__(13);
 var Nodes_1 = __webpack_require__(23);
+var NodeUtils_1 = __webpack_require__(9);
 var CallExpressionControlFlowStorageCallNode = function (_AbstractCustomNode_) {
     (0, _inherits3.default)(CallExpressionControlFlowStorageCallNode, _AbstractCustomNode_);
 
@@ -3622,7 +3635,9 @@ var CallExpressionControlFlowStorageCallNode = function (_AbstractCustomNode_) {
     }, {
         key: "getNodeStructure",
         value: function getNodeStructure() {
-            return [Nodes_1.Nodes.getExpressionStatementNode(Nodes_1.Nodes.getCallExpressionNode(Nodes_1.Nodes.getMemberExpressionNode(Nodes_1.Nodes.getIdentifierNode(this.controlFlowStorageName), Nodes_1.Nodes.getIdentifierNode(this.controlFlowStorageKey)), [this.callee].concat((0, _toConsumableArray3.default)(this.expressionArguments))))];
+            var structure = Nodes_1.Nodes.getExpressionStatementNode(Nodes_1.Nodes.getCallExpressionNode(Nodes_1.Nodes.getMemberExpressionNode(Nodes_1.Nodes.getIdentifierNode(this.controlFlowStorageName), Nodes_1.Nodes.getIdentifierNode(this.controlFlowStorageKey)), [this.callee].concat((0, _toConsumableArray3.default)(this.expressionArguments))));
+            NodeUtils_1.NodeUtils.parentize(structure);
+            return [structure];
         }
     }]);
     return CallExpressionControlFlowStorageCallNode;
@@ -3746,6 +3761,7 @@ var ServiceIdentifiers_1 = __webpack_require__(4);
 var Initializable_1 = __webpack_require__(10);
 var AbstractCustomNode_1 = __webpack_require__(13);
 var Nodes_1 = __webpack_require__(23);
+var NodeUtils_1 = __webpack_require__(9);
 var ExpressionWithOperatorControlFlowStorageCallNode = function (_AbstractCustomNode_) {
     (0, _inherits3.default)(ExpressionWithOperatorControlFlowStorageCallNode, _AbstractCustomNode_);
 
@@ -3765,7 +3781,9 @@ var ExpressionWithOperatorControlFlowStorageCallNode = function (_AbstractCustom
     }, {
         key: "getNodeStructure",
         value: function getNodeStructure() {
-            return [Nodes_1.Nodes.getExpressionStatementNode(Nodes_1.Nodes.getCallExpressionNode(Nodes_1.Nodes.getMemberExpressionNode(Nodes_1.Nodes.getIdentifierNode(this.controlFlowStorageName), Nodes_1.Nodes.getIdentifierNode(this.controlFlowStorageKey)), [this.leftValue, this.rightValue]))];
+            var structure = Nodes_1.Nodes.getExpressionStatementNode(Nodes_1.Nodes.getCallExpressionNode(Nodes_1.Nodes.getMemberExpressionNode(Nodes_1.Nodes.getIdentifierNode(this.controlFlowStorageName), Nodes_1.Nodes.getIdentifierNode(this.controlFlowStorageKey)), [this.leftValue, this.rightValue]));
+            NodeUtils_1.NodeUtils.parentize(structure);
+            return [structure];
         }
     }]);
     return ExpressionWithOperatorControlFlowStorageCallNode;
@@ -5036,6 +5054,7 @@ var FunctionControlFlowTransformer = FunctionControlFlowTransformer_1 = function
             var controlFlowStorage = this.getControlFlowStorage(hostNode);
             this.controlFlowData.set(hostNode, controlFlowStorage);
             this.transformFunctionBody(functionNode.body, controlFlowStorage);
+            NodeUtils_1.NodeUtils.parentize(functionNode);
             if (!controlFlowStorage.getLength()) {
                 return functionNode;
             }
@@ -5173,10 +5192,6 @@ var _keys = __webpack_require__(36);
 
 var _keys2 = _interopRequireDefault(_keys);
 
-var _assign = __webpack_require__(47);
-
-var _assign2 = _interopRequireDefault(_assign);
-
 var _getPrototypeOf = __webpack_require__(5);
 
 var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
@@ -5203,10 +5218,8 @@ var tslib_1 = __webpack_require__(3);
 var inversify_1 = __webpack_require__(2);
 var ServiceIdentifiers_1 = __webpack_require__(4);
 var AbstractControlFlowReplacer_1 = __webpack_require__(33);
+var CustomNodes_1 = __webpack_require__(17);
 var Node_1 = __webpack_require__(12);
-var Nodes_1 = __webpack_require__(23);
-var NodeUtils_1 = __webpack_require__(9);
-var RandomGeneratorUtils_1 = __webpack_require__(8);
 var Utils_1 = __webpack_require__(14);
 var BlockStatementControlFlowReplacer = BlockStatementControlFlowReplacer_1 = function (_AbstractControlFlowR) {
     (0, _inherits3.default)(BlockStatementControlFlowReplacer, _AbstractControlFlowR);
@@ -5222,27 +5235,20 @@ var BlockStatementControlFlowReplacer = BlockStatementControlFlowReplacer_1 = fu
             if (BlockStatementControlFlowReplacer_1.blockStatementHasProhibitedStatements(blockStatementNode)) {
                 return blockStatementNode;
             }
-            var blockStatementStatements = blockStatementNode.body;
-            var blockStatementStatementsAsObject = (0, _assign2.default)({}, blockStatementStatements);
-            var originalKeys = (0, _keys2.default)(blockStatementStatementsAsObject).map(function (key) {
+            var blockStatementBody = blockStatementNode.body;
+            var originalKeys = (0, _keys2.default)(blockStatementBody).map(function (key) {
                 return parseInt(key, 10);
             });
             var shuffledKeys = Utils_1.Utils.arrayShuffle(originalKeys);
             var originalKeysIndexesInShuffledArray = originalKeys.map(function (key) {
                 return shuffledKeys.indexOf(key);
             });
-            if (blockStatementStatements.length <= 4) {
+            if (blockStatementBody.length <= 4) {
                 return blockStatementNode;
-            } else if (!blockStatementStatements.length) {
-                blockStatementStatements.push(Nodes_1.Nodes.getReturnStatementNode(Nodes_1.Nodes.getLiteralNode(true)));
             }
-            var controllerIdentifierName = RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomString(3);
-            var indexIdentifierName = RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomString(3);
-            blockStatementNode.body = [Nodes_1.Nodes.getVariableDeclarationNode([Nodes_1.Nodes.getVariableDeclaratorNode(Nodes_1.Nodes.getIdentifierNode(controllerIdentifierName), Nodes_1.Nodes.getCallExpressionNode(Nodes_1.Nodes.getMemberExpressionNode(Nodes_1.Nodes.getLiteralNode(originalKeysIndexesInShuffledArray.join('|')), Nodes_1.Nodes.getIdentifierNode('split')), [Nodes_1.Nodes.getLiteralNode('|')])), Nodes_1.Nodes.getVariableDeclaratorNode(Nodes_1.Nodes.getIdentifierNode(indexIdentifierName), Nodes_1.Nodes.getLiteralNode(0))]), Nodes_1.Nodes.getWhileStatementNode(Nodes_1.Nodes.getLiteralNode(true), Nodes_1.Nodes.getBlockStatementNode([Nodes_1.Nodes.getSwitchStatementNode(Nodes_1.Nodes.getMemberExpressionNode(Nodes_1.Nodes.getIdentifierNode(controllerIdentifierName), Nodes_1.Nodes.getUpdateExpressionNode('++', Nodes_1.Nodes.getIdentifierNode(indexIdentifierName)), true), shuffledKeys.map(function (key, index) {
-                return Nodes_1.Nodes.getSwitchCaseNode(Nodes_1.Nodes.getLiteralNode(String(index)), [blockStatementStatementsAsObject[key], Nodes_1.Nodes.getContinueStatement()]);
-            })), Nodes_1.Nodes.getBreakStatement()]))];
-            NodeUtils_1.NodeUtils.parentize(blockStatementNode);
-            return blockStatementNode;
+            var blockStatementControlFlowReplacerCustomNode = this.customNodeFactory(CustomNodes_1.CustomNodes.BlockStatementControlFlowReplacerNode);
+            blockStatementControlFlowReplacerCustomNode.initialize(blockStatementBody, shuffledKeys, originalKeysIndexesInShuffledArray);
+            return blockStatementControlFlowReplacerCustomNode.getNode()[0];
         }
     }], [{
         key: "blockStatementHasProhibitedStatements",
@@ -7951,6 +7957,80 @@ module.exports = require("reflect-metadata");
 var JavaScriptObfuscator_1 = __webpack_require__(24);
 module.exports = JavaScriptObfuscator_1.JavaScriptObfuscator;
 
+/***/ },
+/* 150 */
+/***/ function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var _getPrototypeOf = __webpack_require__(5);
+
+var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
+
+var _classCallCheck2 = __webpack_require__(0);
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _createClass2 = __webpack_require__(1);
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _possibleConstructorReturn2 = __webpack_require__(7);
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _inherits2 = __webpack_require__(6);
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var tslib_1 = __webpack_require__(3);
+var inversify_1 = __webpack_require__(2);
+var ServiceIdentifiers_1 = __webpack_require__(4);
+var Initializable_1 = __webpack_require__(10);
+var AbstractCustomNode_1 = __webpack_require__(13);
+var Nodes_1 = __webpack_require__(23);
+var NodeUtils_1 = __webpack_require__(9);
+var RandomGeneratorUtils_1 = __webpack_require__(8);
+var BlockStatementControlFlowReplacerNode = function (_AbstractCustomNode_) {
+    (0, _inherits3.default)(BlockStatementControlFlowReplacerNode, _AbstractCustomNode_);
+
+    function BlockStatementControlFlowReplacerNode(options) {
+        (0, _classCallCheck3.default)(this, BlockStatementControlFlowReplacerNode);
+        return (0, _possibleConstructorReturn3.default)(this, (BlockStatementControlFlowReplacerNode.__proto__ || (0, _getPrototypeOf2.default)(BlockStatementControlFlowReplacerNode)).call(this, options));
+    }
+
+    (0, _createClass3.default)(BlockStatementControlFlowReplacerNode, [{
+        key: "initialize",
+        value: function initialize(blockStatementBody, shuffledKeys, originalKeysIndexesInShuffledArray) {
+            this.blockStatementBody = blockStatementBody;
+            this.shuffledKeys = shuffledKeys;
+            this.originalKeysIndexesInShuffledArray = originalKeysIndexesInShuffledArray;
+        }
+    }, {
+        key: "getNodeStructure",
+        value: function getNodeStructure() {
+            var _this2 = this;
+
+            var controllerIdentifierName = RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomString(3);
+            var indexIdentifierName = RandomGeneratorUtils_1.RandomGeneratorUtils.getRandomString(3);
+            var structure = Nodes_1.Nodes.getBlockStatementNode([Nodes_1.Nodes.getVariableDeclarationNode([Nodes_1.Nodes.getVariableDeclaratorNode(Nodes_1.Nodes.getIdentifierNode(controllerIdentifierName), Nodes_1.Nodes.getCallExpressionNode(Nodes_1.Nodes.getMemberExpressionNode(Nodes_1.Nodes.getLiteralNode(this.originalKeysIndexesInShuffledArray.join('|')), Nodes_1.Nodes.getIdentifierNode('split')), [Nodes_1.Nodes.getLiteralNode('|')])), Nodes_1.Nodes.getVariableDeclaratorNode(Nodes_1.Nodes.getIdentifierNode(indexIdentifierName), Nodes_1.Nodes.getLiteralNode(0))]), Nodes_1.Nodes.getWhileStatementNode(Nodes_1.Nodes.getLiteralNode(true), Nodes_1.Nodes.getBlockStatementNode([Nodes_1.Nodes.getSwitchStatementNode(Nodes_1.Nodes.getMemberExpressionNode(Nodes_1.Nodes.getIdentifierNode(controllerIdentifierName), Nodes_1.Nodes.getUpdateExpressionNode('++', Nodes_1.Nodes.getIdentifierNode(indexIdentifierName)), true), this.shuffledKeys.map(function (key, index) {
+                return Nodes_1.Nodes.getSwitchCaseNode(Nodes_1.Nodes.getLiteralNode(String(index)), [_this2.blockStatementBody[key], Nodes_1.Nodes.getContinueStatement()]);
+            })), Nodes_1.Nodes.getBreakStatement()]))]);
+            NodeUtils_1.NodeUtils.parentize(structure);
+            return [structure];
+        }
+    }]);
+    return BlockStatementControlFlowReplacerNode;
+}(AbstractCustomNode_1.AbstractCustomNode);
+tslib_1.__decorate([Initializable_1.initializable(), tslib_1.__metadata("design:type", Array)], BlockStatementControlFlowReplacerNode.prototype, "blockStatementBody", void 0);
+tslib_1.__decorate([Initializable_1.initializable(), tslib_1.__metadata("design:type", Array)], BlockStatementControlFlowReplacerNode.prototype, "originalKeysIndexesInShuffledArray", void 0);
+tslib_1.__decorate([Initializable_1.initializable(), tslib_1.__metadata("design:type", Array)], BlockStatementControlFlowReplacerNode.prototype, "shuffledKeys", void 0);
+BlockStatementControlFlowReplacerNode = tslib_1.__decorate([inversify_1.injectable(), tslib_1.__param(0, inversify_1.inject(ServiceIdentifiers_1.ServiceIdentifiers.IOptions)), tslib_1.__metadata("design:paramtypes", [Object])], BlockStatementControlFlowReplacerNode);
+exports.BlockStatementControlFlowReplacerNode = BlockStatementControlFlowReplacerNode;
+
 /***/ }
 /******/ ]);
 //# sourceMappingURL=index.js.map

+ 5 - 0
src/container/modules/custom-nodes/CustomNodesModule.ts

@@ -15,6 +15,7 @@ import { SelfDefendingCustomNodeGroup } from '../../../custom-nodes/self-defendi
 import { StringArrayCustomNodeGroup } from '../../../custom-nodes/string-array-nodes/group/StringArrayCustomNodeGroup';
 
 import { BinaryExpressionFunctionNode } from '../../../custom-nodes/control-flow-replacers-nodes/binary-expression-control-flow-replacer-nodes/BinaryExpressionFunctionNode';
+import { BlockStatementControlFlowReplacerNode } from '../../../custom-nodes/control-flow-replacers-nodes/block-statement-control-flow-replacer-nodes/BlockStatementControlFlowReplacerNode';
 import { CallExpressionControlFlowStorageCallNode } from '../../../custom-nodes/control-flow-storage-nodes/CallExpressionControlFlowStorageCallNode';
 import { CallExpressionFunctionNode } from '../../../custom-nodes/control-flow-replacers-nodes/call-expression-control-flow-replacer-nodes/CallExpressionFunctionNode';
 import { ControlFlowStorageNode } from '../../../custom-nodes/control-flow-storage-nodes/ControlFlowStorageNode';
@@ -37,6 +38,10 @@ export const customNodesModule: interfaces.ContainerModule = new ContainerModule
         .toConstructor(BinaryExpressionFunctionNode)
         .whenTargetNamed(CustomNodes.BinaryExpressionFunctionNode);
 
+    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
+        .toConstructor(BlockStatementControlFlowReplacerNode)
+        .whenTargetNamed(CustomNodes.BlockStatementControlFlowReplacerNode);
+
     bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
         .toConstructor(CallExpressionControlFlowStorageCallNode)
         .whenTargetNamed(CustomNodes.CallExpressionControlFlowStorageCallNode);

+ 20 - 17
src/custom-nodes/control-flow-replacers-nodes/binary-expression-control-flow-replacer-nodes/BinaryExpressionFunctionNode.ts

@@ -11,6 +11,7 @@ import { initializable } from '../../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../../AbstractCustomNode';
 import { Nodes } from '../../../node/Nodes';
+import { NodeUtils } from '../../../node/NodeUtils';
 import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
 
 @injectable()
@@ -41,23 +42,25 @@ export class BinaryExpressionFunctionNode extends AbstractCustomNode {
      * @returns {TStatement[]}
      */
     protected getNodeStructure (): TStatement[] {
-        return [
-            Nodes.getFunctionDeclarationNode(
-                RandomGeneratorUtils.getRandomVariableName(1, true, false),
-                [
-                    Nodes.getIdentifierNode('x'),
-                    Nodes.getIdentifierNode('y')
-                ],
-                Nodes.getBlockStatementNode([
-                    Nodes.getReturnStatementNode(
-                        Nodes.getBinaryExpressionNode(
-                            this.operator,
-                            Nodes.getIdentifierNode('x'),
-                            Nodes.getIdentifierNode('y')
-                        )
+        const structure: TStatement = Nodes.getFunctionDeclarationNode(
+            RandomGeneratorUtils.getRandomVariableName(1, true, false),
+            [
+                Nodes.getIdentifierNode('x'),
+                Nodes.getIdentifierNode('y')
+            ],
+            Nodes.getBlockStatementNode([
+                Nodes.getReturnStatementNode(
+                    Nodes.getBinaryExpressionNode(
+                        this.operator,
+                        Nodes.getIdentifierNode('x'),
+                        Nodes.getIdentifierNode('y')
                     )
-                ])
-            )
-        ];
+                )
+            ])
+        );
+
+        NodeUtils.parentize(structure);
+
+        return [structure];
     }
 }

+ 119 - 0
src/custom-nodes/control-flow-replacers-nodes/block-statement-control-flow-replacer-nodes/BlockStatementControlFlowReplacerNode.ts

@@ -0,0 +1,119 @@
+import { injectable, inject } from 'inversify';
+import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
+
+import * as ESTree from 'estree';
+
+import { TStatement } from '../../../types/node/TStatement';
+
+import { IOptions } from '../../../interfaces/options/IOptions';
+
+import { initializable } from '../../../decorators/Initializable';
+
+import { AbstractCustomNode } from '../../AbstractCustomNode';
+import { Nodes } from '../../../node/Nodes';
+import { NodeUtils } from '../../../node/NodeUtils';
+import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
+
+@injectable()
+export class BlockStatementControlFlowReplacerNode extends AbstractCustomNode {
+    /**
+     * @type {ESTree.Statement[]}
+     */
+    @initializable()
+    private blockStatementBody: ESTree.Statement[];
+
+    /**
+     * @type {number[]}
+     */
+    @initializable()
+    private originalKeysIndexesInShuffledArray: number[];
+
+    /**
+     * @type {number[]}
+     */
+    @initializable()
+    private shuffledKeys: number[];
+
+    /**
+     * @param options
+     */
+    constructor (
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(options);
+    }
+
+    /***
+     * @param blockStatementBody
+     * @param shuffledKeys
+     * @param originalKeysIndexesInShuffledArray
+     */
+    public initialize (
+        blockStatementBody: ESTree.Statement[],
+        shuffledKeys: number[],
+        originalKeysIndexesInShuffledArray: number[]
+    ): void {
+        this.blockStatementBody = blockStatementBody;
+        this.shuffledKeys = shuffledKeys;
+        this.originalKeysIndexesInShuffledArray = originalKeysIndexesInShuffledArray;
+    }
+
+    /**
+     * @returns {TStatement[]}
+     */
+    protected getNodeStructure (): TStatement[] {
+        const controllerIdentifierName: string = RandomGeneratorUtils.getRandomString(3);
+        const indexIdentifierName: string = RandomGeneratorUtils.getRandomString(3);
+        const structure: ESTree.BlockStatement = Nodes.getBlockStatementNode([
+            Nodes.getVariableDeclarationNode([
+                Nodes.getVariableDeclaratorNode(
+                    Nodes.getIdentifierNode(controllerIdentifierName),
+                    Nodes.getCallExpressionNode(
+                        Nodes.getMemberExpressionNode(
+                            Nodes.getLiteralNode(
+                                this.originalKeysIndexesInShuffledArray.join('|')
+                            ),
+                            Nodes.getIdentifierNode('split')
+                        ),
+                        [
+                            Nodes.getLiteralNode('|')
+                        ]
+                    )
+                ),
+                Nodes.getVariableDeclaratorNode(
+                    Nodes.getIdentifierNode(indexIdentifierName),
+                    Nodes.getLiteralNode(0)
+                )
+            ]),
+            Nodes.getWhileStatementNode(
+                Nodes.getLiteralNode(true),
+                Nodes.getBlockStatementNode([
+                    Nodes.getSwitchStatementNode(
+                        Nodes.getMemberExpressionNode(
+                            Nodes.getIdentifierNode(controllerIdentifierName),
+                            Nodes.getUpdateExpressionNode(
+                                '++',
+                                Nodes.getIdentifierNode(indexIdentifierName)
+                            ),
+                            true
+                        ),
+                        this.shuffledKeys.map((key: number, index: number) => {
+                            return Nodes.getSwitchCaseNode(
+                                Nodes.getLiteralNode(String(index)),
+                                [
+                                    this.blockStatementBody[key],
+                                    Nodes.getContinueStatement()
+                                ]
+                            );
+                        })
+                    ),
+                    Nodes.getBreakStatement()
+                ])
+            )
+        ]);
+
+        NodeUtils.parentize(structure);
+
+        return [structure];
+    }
+}

+ 19 - 16
src/custom-nodes/control-flow-replacers-nodes/call-expression-control-flow-replacer-nodes/CallExpressionFunctionNode.ts

@@ -11,6 +11,7 @@ import { initializable } from '../../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../../AbstractCustomNode';
 import { Nodes } from '../../../node/Nodes';
+import { NodeUtils } from '../../../node/NodeUtils';
 import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
 
 @injectable()
@@ -49,22 +50,24 @@ export class CallExpressionFunctionNode extends AbstractCustomNode {
             params.push(Nodes.getIdentifierNode(`param${i + 1}`));
         }
 
-        return [
-            Nodes.getFunctionDeclarationNode(
-                RandomGeneratorUtils.getRandomVariableName(1, true, false),
-                [
-                    calleeIdentifier,
-                    ...params
-                ],
-                Nodes.getBlockStatementNode([
-                    Nodes.getReturnStatementNode(
-                        Nodes.getCallExpressionNode(
-                            calleeIdentifier,
-                            params
-                        )
+        const structure: TStatement = Nodes.getFunctionDeclarationNode(
+            RandomGeneratorUtils.getRandomVariableName(1, true, false),
+            [
+                calleeIdentifier,
+                ...params
+            ],
+            Nodes.getBlockStatementNode([
+                Nodes.getReturnStatementNode(
+                    Nodes.getCallExpressionNode(
+                        calleeIdentifier,
+                        params
                     )
-                ])
-            )
-        ];
+                )
+            ])
+        );
+
+        NodeUtils.parentize(structure);
+
+        return [structure];
     }
 }

+ 20 - 17
src/custom-nodes/control-flow-replacers-nodes/logical-expression-control-flow-replacer-nodes/LogicalExpressionFunctionNode.ts

@@ -12,6 +12,7 @@ import { initializable } from '../../../decorators/Initializable';
 import { AbstractCustomNode } from '../../AbstractCustomNode';
 import { Nodes } from '../../../node/Nodes';
 import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
+import { NodeUtils } from '../../../node/NodeUtils';
 
 @injectable()
 export class LogicalExpressionFunctionNode extends AbstractCustomNode {
@@ -41,23 +42,25 @@ export class LogicalExpressionFunctionNode extends AbstractCustomNode {
      * @returns {TStatement[]}
      */
     protected getNodeStructure (): TStatement[] {
-        return [
-            Nodes.getFunctionDeclarationNode(
-                RandomGeneratorUtils.getRandomVariableName(1, true, false),
-                [
-                    Nodes.getIdentifierNode('x'),
-                    Nodes.getIdentifierNode('y')
-                ],
-                Nodes.getBlockStatementNode([
-                    Nodes.getReturnStatementNode(
-                        Nodes.getLogicalExpressionNode(
-                            this.operator,
-                            Nodes.getIdentifierNode('x'),
-                            Nodes.getIdentifierNode('y')
-                        )
+        const structure: TStatement = Nodes.getFunctionDeclarationNode(
+            RandomGeneratorUtils.getRandomVariableName(1, true, false),
+            [
+                Nodes.getIdentifierNode('x'),
+                Nodes.getIdentifierNode('y')
+            ],
+            Nodes.getBlockStatementNode([
+                Nodes.getReturnStatementNode(
+                    Nodes.getLogicalExpressionNode(
+                        this.operator,
+                        Nodes.getIdentifierNode('x'),
+                        Nodes.getIdentifierNode('y')
                     )
-                ])
-            )
-        ];
+                )
+            ])
+        );
+
+        NodeUtils.parentize(structure);
+
+        return [structure];
     }
 }

+ 16 - 13
src/custom-nodes/control-flow-storage-nodes/CallExpressionControlFlowStorageCallNode.ts

@@ -12,6 +12,7 @@ import { initializable } from '../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { Nodes } from '../../node/Nodes';
+import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
 export class CallExpressionControlFlowStorageCallNode extends AbstractCustomNode {
@@ -67,19 +68,21 @@ export class CallExpressionControlFlowStorageCallNode extends AbstractCustomNode
     }
 
     protected getNodeStructure (): TStatement[] {
-        return [
-            Nodes.getExpressionStatementNode(
-                Nodes.getCallExpressionNode(
-                    Nodes.getMemberExpressionNode(
-                        Nodes.getIdentifierNode(this.controlFlowStorageName),
-                        Nodes.getIdentifierNode(this.controlFlowStorageKey)
-                    ),
-                    [
-                        this.callee,
-                        ...this.expressionArguments
-                    ]
-                )
+        const structure: TStatement = Nodes.getExpressionStatementNode(
+            Nodes.getCallExpressionNode(
+                Nodes.getMemberExpressionNode(
+                    Nodes.getIdentifierNode(this.controlFlowStorageName),
+                    Nodes.getIdentifierNode(this.controlFlowStorageKey)
+                ),
+                [
+                    this.callee,
+                    ...this.expressionArguments
+                ]
             )
-        ];
+        );
+
+        NodeUtils.parentize(structure);
+
+        return [structure];
     }
 }

+ 16 - 13
src/custom-nodes/control-flow-storage-nodes/ExpressionWithOperatorControlFlowStorageCallNode.ts

@@ -11,6 +11,7 @@ import { initializable } from '../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { Nodes } from '../../node/Nodes';
+import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
 export class ExpressionWithOperatorControlFlowStorageCallNode extends AbstractCustomNode {
@@ -66,19 +67,21 @@ export class ExpressionWithOperatorControlFlowStorageCallNode extends AbstractCu
     }
 
     protected getNodeStructure (): TStatement[] {
-        return [
-            Nodes.getExpressionStatementNode(
-                Nodes.getCallExpressionNode(
-                    Nodes.getMemberExpressionNode(
-                        Nodes.getIdentifierNode(this.controlFlowStorageName),
-                        Nodes.getIdentifierNode(this.controlFlowStorageKey)
-                    ),
-                    [
-                        this.leftValue,
-                        this.rightValue
-                    ]
-                )
+        const structure: TStatement = Nodes.getExpressionStatementNode(
+            Nodes.getCallExpressionNode(
+                Nodes.getMemberExpressionNode(
+                    Nodes.getIdentifierNode(this.controlFlowStorageName),
+                    Nodes.getIdentifierNode(this.controlFlowStorageKey)
+                ),
+                [
+                    this.leftValue,
+                    this.rightValue
+                ]
             )
-        ];
+        );
+
+        NodeUtils.parentize(structure);
+
+        return [structure];
     }
 }

+ 1 - 0
src/enums/container/CustomNodes.ts

@@ -1,5 +1,6 @@
 export enum CustomNodes {
     BinaryExpressionFunctionNode,
+    BlockStatementControlFlowReplacerNode,
     CallExpressionControlFlowStorageCallNode,
     CallExpressionFunctionNode,
     ControlFlowStorageNode,

+ 1 - 0
src/node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer.ts

@@ -127,6 +127,7 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
 
         this.controlFlowData.set(hostNode, controlFlowStorage);
         this.transformFunctionBody(functionNode.body, controlFlowStorage);
+        NodeUtils.parentize(functionNode);
 
         if (!controlFlowStorage.getLength()) {
             return functionNode;

+ 15 - 67
src/node-transformers/node-control-flow-transformers/control-flow-replacers/BlockStatementControlFlowReplacer.ts

@@ -10,10 +10,8 @@ import { IOptions } from '../../../interfaces/options/IOptions';
 import { IStorage } from '../../../interfaces/storages/IStorage';
 
 import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
+import { CustomNodes } from '../../../enums/container/CustomNodes';
 import { Node } from '../../../node/Node';
-import { Nodes } from '../../../node/Nodes';
-import { NodeUtils } from '../../../node/NodeUtils';
-import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
 import { Utils } from '../../../utils/Utils';
 
 @injectable()
@@ -53,80 +51,30 @@ export class BlockStatementControlFlowReplacer extends AbstractControlFlowReplac
         blockStatementNode: ESTree.BlockStatement,
         parentNode: ESTree.Node,
         controlFlowStorage: IStorage <ICustomNode>
-    ): ESTree.BlockStatement {
+    ): ESTree.Node {
         if (BlockStatementControlFlowReplacer.blockStatementHasProhibitedStatements(blockStatementNode)) {
             return blockStatementNode;
         }
 
-        const blockStatementStatements: ESTree.Statement[] = blockStatementNode.body;
-        const blockStatementStatementsAsObject: any = Object.assign({}, blockStatementStatements);
-        const originalKeys: number[] = Object.keys(blockStatementStatementsAsObject).map((key: string) => parseInt(key, 10));
+        const blockStatementBody: ESTree.Statement[] = blockStatementNode.body;
+        const originalKeys: number[] = Object.keys(blockStatementBody).map((key: string) => parseInt(key, 10));
         const shuffledKeys: number[] = Utils.arrayShuffle(originalKeys);
         const originalKeysIndexesInShuffledArray: number[] = originalKeys.map((key: number) => shuffledKeys.indexOf(key));
 
-        if (blockStatementStatements.length <= 4) {
+        if (blockStatementBody.length <= 4) {
             return blockStatementNode;
-        } else if (!blockStatementStatements.length) {
-            blockStatementStatements.push(
-                Nodes.getReturnStatementNode(
-                    Nodes.getLiteralNode(true)
-                )
-            );
         }
 
-        const controllerIdentifierName: string = RandomGeneratorUtils.getRandomString(3);
-        const indexIdentifierName: string = RandomGeneratorUtils.getRandomString(3);
+        const blockStatementControlFlowReplacerCustomNode: ICustomNode = this.customNodeFactory(
+            CustomNodes.BlockStatementControlFlowReplacerNode
+        );
+        
+        blockStatementControlFlowReplacerCustomNode.initialize(
+            blockStatementBody,
+            shuffledKeys,
+            originalKeysIndexesInShuffledArray
+        );
 
-        blockStatementNode.body = [
-            Nodes.getVariableDeclarationNode([
-                Nodes.getVariableDeclaratorNode(
-                    Nodes.getIdentifierNode(controllerIdentifierName),
-                    Nodes.getCallExpressionNode(
-                        Nodes.getMemberExpressionNode(
-                            Nodes.getLiteralNode(
-                                originalKeysIndexesInShuffledArray.join('|')
-                            ),
-                            Nodes.getIdentifierNode('split')
-                        ),
-                        [
-                            Nodes.getLiteralNode('|')
-                        ]
-                    )
-                ),
-                Nodes.getVariableDeclaratorNode(
-                    Nodes.getIdentifierNode(indexIdentifierName),
-                    Nodes.getLiteralNode(0)
-                )
-            ]),
-            Nodes.getWhileStatementNode(
-                Nodes.getLiteralNode(true),
-                Nodes.getBlockStatementNode([
-                    Nodes.getSwitchStatementNode(
-                        Nodes.getMemberExpressionNode(
-                            Nodes.getIdentifierNode(controllerIdentifierName),
-                            Nodes.getUpdateExpressionNode(
-                                '++',
-                                Nodes.getIdentifierNode(indexIdentifierName)
-                            ),
-                            true
-                        ),
-                        shuffledKeys.map((key: number, index: number) => {
-                            return Nodes.getSwitchCaseNode(
-                                Nodes.getLiteralNode(String(index)),
-                                [
-                                    blockStatementStatementsAsObject[key],
-                                    Nodes.getContinueStatement()
-                                ]
-                            );
-                        })
-                    ),
-                    Nodes.getBreakStatement()
-                ])
-            )
-        ];
-
-        NodeUtils.parentize(blockStatementNode);
-
-        return blockStatementNode;
+        return blockStatementControlFlowReplacerCustomNode.getNode()[0];
     }
 }