Просмотр исходного кода

Added getBlockScopeOfNode method

sanex3339 7 лет назад
Родитель
Сommit
5fdf26b941

+ 27 - 16
dist/index.cli.js

@@ -289,7 +289,7 @@ function () {
     key: "obfuscate",
     value: function obfuscate(sourceCode) {
       var timeStart = Date.now();
-      this.logger.info(LoggingMessage_1.LoggingMessage.Version, '0.16.0');
+      this.logger.info(LoggingMessage_1.LoggingMessage.Version, "0.17.0-dev.1");
       this.logger.info(LoggingMessage_1.LoggingMessage.ObfuscationStarted);
       this.logger.info(LoggingMessage_1.LoggingMessage.RandomGeneratorSeed, this.randomGenerator.getSeed());
       var astTree = this.parseCode(sourceCode);
@@ -663,7 +663,7 @@ function () {
               return;
             }
 
-            if (blockScopeBodyNode.parentNode !== NodeUtils_1.NodeUtils.getBlockScopesOfNode(node)[0]) {
+            if (blockScopeBodyNode.parentNode !== NodeUtils_1.NodeUtils.getBlockScopeOfNode(node)) {
               return estraverse.VisitorOption.Skip;
             }
 
@@ -812,7 +812,7 @@ function (_AbstractCalleeDataEx) {
         return null;
       }
 
-      var calleeBlockStatement = this.getCalleeBlockStatement(NodeUtils_1.NodeUtils.getBlockScopesOfNode(blockScopeBody[0])[0], callee.name);
+      var calleeBlockStatement = this.getCalleeBlockStatement(NodeUtils_1.NodeUtils.getBlockScopeOfNode(blockScopeBody[0]), callee.name);
 
       if (!calleeBlockStatement) {
         return null;
@@ -900,7 +900,7 @@ function (_AbstractCalleeDataEx) {
       var calleeBlockStatement = null;
 
       if (NodeGuards_1.NodeGuards.isIdentifierNode(callee)) {
-        calleeBlockStatement = this.getCalleeBlockStatement(NodeUtils_1.NodeUtils.getBlockScopesOfNode(blockScopeBody[0])[0], callee.name);
+        calleeBlockStatement = this.getCalleeBlockStatement(NodeUtils_1.NodeUtils.getBlockScopeOfNode(blockScopeBody[0]), callee.name);
       }
 
       if (NodeGuards_1.NodeGuards.isFunctionExpressionNode(callee)) {
@@ -1006,7 +1006,7 @@ function (_AbstractCalleeDataEx) {
       }
 
       var functionExpressionName = objectMembersCallsChain[objectMembersCallsChain.length - 1];
-      var calleeBlockStatement = this.getCalleeBlockStatement(NodeUtils_1.NodeUtils.getBlockScopesOfNode(blockScopeBody[0])[0], objectMembersCallsChain);
+      var calleeBlockStatement = this.getCalleeBlockStatement(NodeUtils_1.NodeUtils.getBlockScopeOfNode(blockScopeBody[0]), objectMembersCallsChain);
 
       if (!calleeBlockStatement) {
         return null;
@@ -8357,7 +8357,7 @@ function (_AbstractNodeTransfor) {
         return false;
       }
 
-      var blockScopeOfBlockStatementNode = NodeUtils_1.NodeUtils.getBlockScopesOfNode(blockStatementNode)[0];
+      var blockScopeOfBlockStatementNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(blockStatementNode);
       return blockScopeOfBlockStatementNode.type !== NodeType_1.NodeType.Program;
     }
   }]);
@@ -8455,7 +8455,7 @@ function (_AbstractNodeTransfor) {
   }, {
     key: "transformNode",
     value: function transformNode(catchClauseNode, parentNode) {
-      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopesOfNode(catchClauseNode)[0];
+      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(catchClauseNode);
       this.storeCatchClauseParam(catchClauseNode, blockScopeNode);
       this.replaceCatchClauseParam(catchClauseNode, blockScopeNode);
       return catchClauseNode;
@@ -8585,7 +8585,7 @@ function (_AbstractNodeTransfor) {
   }, {
     key: "transformNode",
     value: function transformNode(classDeclarationNode, parentNode) {
-      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopesOfNode(classDeclarationNode)[0];
+      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(classDeclarationNode);
       var isGlobalDeclaration = blockScopeNode.type === NodeType_1.NodeType.Program;
 
       if (!this.options.renameGlobals && isGlobalDeclaration) {
@@ -8748,7 +8748,7 @@ function (_AbstractNodeTransfor) {
   }, {
     key: "transformNode",
     value: function transformNode(functionDeclarationNode, parentNode) {
-      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopesOfNode(functionDeclarationNode)[0];
+      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(functionDeclarationNode);
       var isGlobalDeclaration = blockScopeNode.type === NodeType_1.NodeType.Program;
 
       if (!this.options.renameGlobals && isGlobalDeclaration) {
@@ -8921,7 +8921,7 @@ function (_AbstractNodeTransfor) {
   }, {
     key: "transformNode",
     value: function transformNode(functionNode, parentNode) {
-      var blockScopeNode = NodeGuards_1.NodeGuards.isBlockStatementNode(functionNode.body) ? functionNode.body : NodeUtils_1.NodeUtils.getBlockScopesOfNode(functionNode.body)[0];
+      var blockScopeNode = NodeGuards_1.NodeGuards.isBlockStatementNode(functionNode.body) ? functionNode.body : NodeUtils_1.NodeUtils.getBlockScopeOfNode(functionNode.body);
       this.storeFunctionParams(functionNode, blockScopeNode);
       this.replaceFunctionParams(functionNode, blockScopeNode);
       return functionNode;
@@ -9090,7 +9090,7 @@ function (_AbstractNodeTransfor) {
   }, {
     key: "transformNode",
     value: function transformNode(importDeclarationNode, parentNode) {
-      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopesOfNode(importDeclarationNode)[0];
+      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(importDeclarationNode);
       this.storeImportSpecifierNames(importDeclarationNode, blockScopeNode);
 
       if (this.replaceableIdentifiers.has(blockScopeNode)) {
@@ -9249,7 +9249,7 @@ function (_AbstractNodeTransfor) {
   }, {
     key: "transformNode",
     value: function transformNode(labeledStatementNode, parentNode) {
-      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopesOfNode(labeledStatementNode)[0];
+      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(labeledStatementNode);
       this.storeLabeledStatementName(labeledStatementNode, blockScopeNode);
       this.replaceLabeledStatementName(labeledStatementNode, blockScopeNode);
       return labeledStatementNode;
@@ -9490,7 +9490,7 @@ function (_AbstractNodeTransfor) {
   }, {
     key: "transformNode",
     value: function transformNode(variableDeclarationNode, parentNode) {
-      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopesOfNode(variableDeclarationNode)[0];
+      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(variableDeclarationNode);
       var isGlobalDeclaration = blockScopeNode.type === NodeType_1.NodeType.Program;
 
       if (!this.options.renameGlobals && isGlobalDeclaration) {
@@ -11890,6 +11890,11 @@ function () {
         }).code;
       }, '');
     }
+  }, {
+    key: "getBlockScopeOfNode",
+    value: function getBlockScopeOfNode(node) {
+      return NodeUtils.getBlockScopesOfNodeRecursive(node, 1)[0];
+    }
   }, {
     key: "getBlockScopesOfNode",
     value: function getBlockScopesOfNode(node) {
@@ -11995,8 +12000,14 @@ function () {
   }, {
     key: "getBlockScopesOfNodeRecursive",
     value: function getBlockScopesOfNodeRecursive(node) {
-      var blockScopes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
-      var depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
+      var maxSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Infinity;
+      var blockScopes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
+      var depth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
+
+      if (blockScopes.length >= maxSize) {
+        return blockScopes;
+      }
+
       var parentNode = node.parentNode;
 
       if (!parentNode) {
@@ -12012,7 +12023,7 @@ function () {
       }
 
       if (node !== parentNode) {
-        return NodeUtils.getBlockScopesOfNodeRecursive(parentNode, blockScopes, ++depth);
+        return NodeUtils.getBlockScopesOfNodeRecursive(parentNode, maxSize, blockScopes, ++depth);
       }
 
       return blockScopes;

+ 27 - 16
dist/index.js

@@ -289,7 +289,7 @@ function () {
     key: "obfuscate",
     value: function obfuscate(sourceCode) {
       var timeStart = Date.now();
-      this.logger.info(LoggingMessage_1.LoggingMessage.Version, '0.16.0');
+      this.logger.info(LoggingMessage_1.LoggingMessage.Version, "0.17.0-dev.1");
       this.logger.info(LoggingMessage_1.LoggingMessage.ObfuscationStarted);
       this.logger.info(LoggingMessage_1.LoggingMessage.RandomGeneratorSeed, this.randomGenerator.getSeed());
       var astTree = this.parseCode(sourceCode);
@@ -617,7 +617,7 @@ function () {
               return;
             }
 
-            if (blockScopeBodyNode.parentNode !== NodeUtils_1.NodeUtils.getBlockScopesOfNode(node)[0]) {
+            if (blockScopeBodyNode.parentNode !== NodeUtils_1.NodeUtils.getBlockScopeOfNode(node)) {
               return estraverse.VisitorOption.Skip;
             }
 
@@ -766,7 +766,7 @@ function (_AbstractCalleeDataEx) {
         return null;
       }
 
-      var calleeBlockStatement = this.getCalleeBlockStatement(NodeUtils_1.NodeUtils.getBlockScopesOfNode(blockScopeBody[0])[0], callee.name);
+      var calleeBlockStatement = this.getCalleeBlockStatement(NodeUtils_1.NodeUtils.getBlockScopeOfNode(blockScopeBody[0]), callee.name);
 
       if (!calleeBlockStatement) {
         return null;
@@ -854,7 +854,7 @@ function (_AbstractCalleeDataEx) {
       var calleeBlockStatement = null;
 
       if (NodeGuards_1.NodeGuards.isIdentifierNode(callee)) {
-        calleeBlockStatement = this.getCalleeBlockStatement(NodeUtils_1.NodeUtils.getBlockScopesOfNode(blockScopeBody[0])[0], callee.name);
+        calleeBlockStatement = this.getCalleeBlockStatement(NodeUtils_1.NodeUtils.getBlockScopeOfNode(blockScopeBody[0]), callee.name);
       }
 
       if (NodeGuards_1.NodeGuards.isFunctionExpressionNode(callee)) {
@@ -960,7 +960,7 @@ function (_AbstractCalleeDataEx) {
       }
 
       var functionExpressionName = objectMembersCallsChain[objectMembersCallsChain.length - 1];
-      var calleeBlockStatement = this.getCalleeBlockStatement(NodeUtils_1.NodeUtils.getBlockScopesOfNode(blockScopeBody[0])[0], objectMembersCallsChain);
+      var calleeBlockStatement = this.getCalleeBlockStatement(NodeUtils_1.NodeUtils.getBlockScopeOfNode(blockScopeBody[0]), objectMembersCallsChain);
 
       if (!calleeBlockStatement) {
         return null;
@@ -7672,7 +7672,7 @@ function (_AbstractNodeTransfor) {
         return false;
       }
 
-      var blockScopeOfBlockStatementNode = NodeUtils_1.NodeUtils.getBlockScopesOfNode(blockStatementNode)[0];
+      var blockScopeOfBlockStatementNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(blockStatementNode);
       return blockScopeOfBlockStatementNode.type !== NodeType_1.NodeType.Program;
     }
   }]);
@@ -7770,7 +7770,7 @@ function (_AbstractNodeTransfor) {
   }, {
     key: "transformNode",
     value: function transformNode(catchClauseNode, parentNode) {
-      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopesOfNode(catchClauseNode)[0];
+      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(catchClauseNode);
       this.storeCatchClauseParam(catchClauseNode, blockScopeNode);
       this.replaceCatchClauseParam(catchClauseNode, blockScopeNode);
       return catchClauseNode;
@@ -7900,7 +7900,7 @@ function (_AbstractNodeTransfor) {
   }, {
     key: "transformNode",
     value: function transformNode(classDeclarationNode, parentNode) {
-      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopesOfNode(classDeclarationNode)[0];
+      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(classDeclarationNode);
       var isGlobalDeclaration = blockScopeNode.type === NodeType_1.NodeType.Program;
 
       if (!this.options.renameGlobals && isGlobalDeclaration) {
@@ -8063,7 +8063,7 @@ function (_AbstractNodeTransfor) {
   }, {
     key: "transformNode",
     value: function transformNode(functionDeclarationNode, parentNode) {
-      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopesOfNode(functionDeclarationNode)[0];
+      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(functionDeclarationNode);
       var isGlobalDeclaration = blockScopeNode.type === NodeType_1.NodeType.Program;
 
       if (!this.options.renameGlobals && isGlobalDeclaration) {
@@ -8236,7 +8236,7 @@ function (_AbstractNodeTransfor) {
   }, {
     key: "transformNode",
     value: function transformNode(functionNode, parentNode) {
-      var blockScopeNode = NodeGuards_1.NodeGuards.isBlockStatementNode(functionNode.body) ? functionNode.body : NodeUtils_1.NodeUtils.getBlockScopesOfNode(functionNode.body)[0];
+      var blockScopeNode = NodeGuards_1.NodeGuards.isBlockStatementNode(functionNode.body) ? functionNode.body : NodeUtils_1.NodeUtils.getBlockScopeOfNode(functionNode.body);
       this.storeFunctionParams(functionNode, blockScopeNode);
       this.replaceFunctionParams(functionNode, blockScopeNode);
       return functionNode;
@@ -8405,7 +8405,7 @@ function (_AbstractNodeTransfor) {
   }, {
     key: "transformNode",
     value: function transformNode(importDeclarationNode, parentNode) {
-      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopesOfNode(importDeclarationNode)[0];
+      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(importDeclarationNode);
       this.storeImportSpecifierNames(importDeclarationNode, blockScopeNode);
 
       if (this.replaceableIdentifiers.has(blockScopeNode)) {
@@ -8564,7 +8564,7 @@ function (_AbstractNodeTransfor) {
   }, {
     key: "transformNode",
     value: function transformNode(labeledStatementNode, parentNode) {
-      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopesOfNode(labeledStatementNode)[0];
+      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(labeledStatementNode);
       this.storeLabeledStatementName(labeledStatementNode, blockScopeNode);
       this.replaceLabeledStatementName(labeledStatementNode, blockScopeNode);
       return labeledStatementNode;
@@ -8805,7 +8805,7 @@ function (_AbstractNodeTransfor) {
   }, {
     key: "transformNode",
     value: function transformNode(variableDeclarationNode, parentNode) {
-      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopesOfNode(variableDeclarationNode)[0];
+      var blockScopeNode = NodeUtils_1.NodeUtils.getBlockScopeOfNode(variableDeclarationNode);
       var isGlobalDeclaration = blockScopeNode.type === NodeType_1.NodeType.Program;
 
       if (!this.options.renameGlobals && isGlobalDeclaration) {
@@ -11205,6 +11205,11 @@ function () {
         }).code;
       }, '');
     }
+  }, {
+    key: "getBlockScopeOfNode",
+    value: function getBlockScopeOfNode(node) {
+      return NodeUtils.getBlockScopesOfNodeRecursive(node, 1)[0];
+    }
   }, {
     key: "getBlockScopesOfNode",
     value: function getBlockScopesOfNode(node) {
@@ -11310,8 +11315,14 @@ function () {
   }, {
     key: "getBlockScopesOfNodeRecursive",
     value: function getBlockScopesOfNodeRecursive(node) {
-      var blockScopes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
-      var depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
+      var maxSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Infinity;
+      var blockScopes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
+      var depth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
+
+      if (blockScopes.length >= maxSize) {
+        return blockScopes;
+      }
+
       var parentNode = node.parentNode;
 
       if (!parentNode) {
@@ -11327,7 +11338,7 @@ function () {
       }
 
       if (node !== parentNode) {
-        return NodeUtils.getBlockScopesOfNodeRecursive(parentNode, blockScopes, ++depth);
+        return NodeUtils.getBlockScopesOfNodeRecursive(parentNode, maxSize, blockScopes, ++depth);
       }
 
       return blockScopes;

+ 1 - 1
src/JavaScriptObfuscator.ts

@@ -126,7 +126,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
      */
     public obfuscate (sourceCode: string): IObfuscationResult {
         const timeStart: number = Date.now();
-        this.logger.info(LoggingMessage.Version, '0.16.0');
+        this.logger.info(LoggingMessage.Version, process.env.VERSION);
         this.logger.info(LoggingMessage.ObfuscationStarted);
         this.logger.info(LoggingMessage.RandomGeneratorSeed, this.randomGenerator.getSeed());
 

+ 1 - 1
src/analyzers/stack-trace-analyzer/StackTraceAnalyzer.ts

@@ -131,7 +131,7 @@ export class StackTraceAnalyzer implements IStackTraceAnalyzer {
                         return;
                     }
 
-                    if (blockScopeBodyNode.parentNode !== NodeUtils.getBlockScopesOfNode(node)[0]) {
+                    if (blockScopeBodyNode.parentNode !== NodeUtils.getBlockScopeOfNode(node)) {
                         return estraverse.VisitorOption.Skip;
                     }
 

+ 1 - 1
src/analyzers/stack-trace-analyzer/callee-data-extractors/FunctionDeclarationCalleeDataExtractor.ts

@@ -22,7 +22,7 @@ export class FunctionDeclarationCalleeDataExtractor extends AbstractCalleeDataEx
         }
 
         const calleeBlockStatement: ESTree.BlockStatement | null = this.getCalleeBlockStatement(
-            NodeUtils.getBlockScopesOfNode(blockScopeBody[0])[0],
+            NodeUtils.getBlockScopeOfNode(blockScopeBody[0]),
             callee.name
         );
 

+ 1 - 1
src/analyzers/stack-trace-analyzer/callee-data-extractors/FunctionExpressionCalleeDataExtractor.ts

@@ -21,7 +21,7 @@ export class FunctionExpressionCalleeDataExtractor extends AbstractCalleeDataExt
 
         if (NodeGuards.isIdentifierNode(callee)) {
             calleeBlockStatement = this.getCalleeBlockStatement(
-                NodeUtils.getBlockScopesOfNode(blockScopeBody[0])[0],
+                NodeUtils.getBlockScopeOfNode(blockScopeBody[0]),
                 callee.name
             );
         }

+ 1 - 1
src/analyzers/stack-trace-analyzer/callee-data-extractors/ObjectExpressionCalleeDataExtractor.ts

@@ -51,7 +51,7 @@ export class ObjectExpressionCalleeDataExtractor extends AbstractCalleeDataExtra
 
         const functionExpressionName: string | number | null = objectMembersCallsChain[objectMembersCallsChain.length - 1];
         const calleeBlockStatement: ESTree.BlockStatement | null = this.getCalleeBlockStatement(
-            NodeUtils.getBlockScopesOfNode(blockScopeBody[0])[0],
+            NodeUtils.getBlockScopeOfNode(blockScopeBody[0]),
             objectMembersCallsChain
         );
 

+ 1 - 1
src/node-transformers/dead-code-injection-transformers/DeadCodeInjectionTransformer.ts

@@ -205,7 +205,7 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
         }
 
         const blockScopeOfBlockStatementNode: TNodeWithBlockScope = NodeUtils
-            .getBlockScopesOfNode(blockStatementNode)[0];
+            .getBlockScopeOfNode(blockStatementNode);
 
         return blockScopeOfBlockStatementNode.type !== NodeType.Program;
     }

+ 1 - 1
src/node-transformers/obfuscating-transformers/CatchClauseTransformer.ts

@@ -79,7 +79,7 @@ export class CatchClauseTransformer extends AbstractNodeTransformer {
      * @returns {NodeGuards}
      */
     public transformNode (catchClauseNode: ESTree.CatchClause, parentNode: ESTree.Node): ESTree.Node {
-        const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopesOfNode(catchClauseNode)[0];
+        const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopeOfNode(catchClauseNode);
 
         this.storeCatchClauseParam(catchClauseNode, blockScopeNode);
         this.replaceCatchClauseParam(catchClauseNode, blockScopeNode);

+ 1 - 1
src/node-transformers/obfuscating-transformers/ClassDeclarationTransformer.ts

@@ -90,7 +90,7 @@ export class ClassDeclarationTransformer extends AbstractNodeTransformer {
      * @returns {NodeGuards}
      */
     public transformNode (classDeclarationNode: ESTree.ClassDeclaration, parentNode: ESTree.Node): ESTree.Node {
-        const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopesOfNode(classDeclarationNode)[0];
+        const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopeOfNode(classDeclarationNode);
         const isGlobalDeclaration: boolean = blockScopeNode.type === NodeType.Program;
 
         if (!this.options.renameGlobals && isGlobalDeclaration) {

+ 1 - 1
src/node-transformers/obfuscating-transformers/FunctionDeclarationTransformer.ts

@@ -92,7 +92,7 @@ export class FunctionDeclarationTransformer extends AbstractNodeTransformer {
      * @returns {NodeGuards}
      */
     public transformNode (functionDeclarationNode: ESTree.FunctionDeclaration, parentNode: ESTree.Node): ESTree.Node {
-        const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopesOfNode(functionDeclarationNode)[0];
+        const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopeOfNode(functionDeclarationNode);
         const isGlobalDeclaration: boolean = blockScopeNode.type === NodeType.Program;
 
         if (!this.options.renameGlobals && isGlobalDeclaration) {

+ 1 - 1
src/node-transformers/obfuscating-transformers/FunctionTransformer.ts

@@ -87,7 +87,7 @@ export class FunctionTransformer extends AbstractNodeTransformer {
     public transformNode (functionNode: ESTree.Function, parentNode: ESTree.Node): ESTree.Node {
         const blockScopeNode: TNodeWithBlockScope = NodeGuards.isBlockStatementNode(functionNode.body)
             ? functionNode.body
-            : NodeUtils.getBlockScopesOfNode(functionNode.body)[0];
+            : NodeUtils.getBlockScopeOfNode(functionNode.body);
 
         this.storeFunctionParams(functionNode, blockScopeNode);
         this.replaceFunctionParams(functionNode, blockScopeNode);

+ 1 - 1
src/node-transformers/obfuscating-transformers/ImportDeclarationTransformer.ts

@@ -95,7 +95,7 @@ export class ImportDeclarationTransformer extends AbstractNodeTransformer {
      * @returns {Node}
      */
     public transformNode (importDeclarationNode: ESTree.ImportDeclaration, parentNode: ESTree.Node): ESTree.Node {
-        const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopesOfNode(importDeclarationNode)[0];
+        const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopeOfNode(importDeclarationNode);
 
         this.storeImportSpecifierNames(importDeclarationNode, blockScopeNode);
 

+ 1 - 1
src/node-transformers/obfuscating-transformers/LabeledStatementTransformer.ts

@@ -86,7 +86,7 @@ export class LabeledStatementTransformer extends AbstractNodeTransformer {
      * @returns {NodeGuards}
      */
     public transformNode (labeledStatementNode: ESTree.LabeledStatement, parentNode: ESTree.Node): ESTree.Node {
-        const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopesOfNode(labeledStatementNode)[0];
+        const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopeOfNode(labeledStatementNode);
 
         this.storeLabeledStatementName(labeledStatementNode, blockScopeNode);
         this.replaceLabeledStatementName(labeledStatementNode, blockScopeNode);

+ 1 - 1
src/node-transformers/obfuscating-transformers/VariableDeclarationTransformer.ts

@@ -93,7 +93,7 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
      * @returns {NodeGuards}
      */
     public transformNode (variableDeclarationNode: ESTree.VariableDeclaration, parentNode: ESTree.Node): ESTree.Node {
-        const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopesOfNode(variableDeclarationNode)[0];
+        const blockScopeNode: TNodeWithBlockScope = NodeUtils.getBlockScopeOfNode(variableDeclarationNode);
         const isGlobalDeclaration: boolean = blockScopeNode.type === NodeType.Program;
 
         if (!this.options.renameGlobals && isGlobalDeclaration) {

+ 16 - 2
src/node/NodeUtils.ts

@@ -69,6 +69,14 @@ export class NodeUtils {
         }, '');
     }
 
+    /**
+     * @param {Node} node
+     * @returns {TNodeWithBlockScope}
+     */
+    public static getBlockScopeOfNode (node: ESTree.Node): TNodeWithBlockScope {
+        return NodeUtils.getBlockScopesOfNodeRecursive(node, 1)[0];
+    }
+
     /**
      * @param {Node} node
      * @returns {TNodeWithBlockScope[]}
@@ -206,17 +214,23 @@ export class NodeUtils {
         return <T>copy;
     }
 
-    /**
+    /***
      * @param {Node} node
+     * @param {number} maxSize
      * @param {TNodeWithBlockScope[]} blockScopes
      * @param {number} depth
      * @returns {TNodeWithBlockScope[]}
      */
     private static getBlockScopesOfNodeRecursive (
         node: ESTree.Node,
+        maxSize: number = Infinity,
         blockScopes: TNodeWithBlockScope[] = [],
         depth: number = 0
     ): TNodeWithBlockScope[] {
+        if (blockScopes.length >= maxSize) {
+            return blockScopes;
+        }
+
         const parentNode: ESTree.Node | undefined = node.parentNode;
 
         if (!parentNode) {
@@ -248,7 +262,7 @@ export class NodeUtils {
         }
 
         if (node !== parentNode) {
-            return NodeUtils.getBlockScopesOfNodeRecursive(parentNode, blockScopes, ++depth);
+            return NodeUtils.getBlockScopesOfNodeRecursive(parentNode, maxSize, blockScopes, ++depth);
         }
 
         return blockScopes;

+ 96 - 1
test/unit-tests/node/node-utils/NodeUtils.spec.ts

@@ -181,6 +181,101 @@ describe('NodeUtils', () => {
         });
     });
 
+    describe('getBlockScopeOfNode', () => {
+        let functionDeclarationBlockStatementNode: ESTree.BlockStatement,
+            ifStatementBlockStatementNode1: ESTree.BlockStatement,
+            ifStatementBlockStatementNode2: ESTree.BlockStatement,
+            ifStatementNode1: ESTree.IfStatement,
+            ifStatementNode2: ESTree.IfStatement,
+            expressionStatementNode3: ESTree.ExpressionStatement,
+            expressionStatementNode2: ESTree.ExpressionStatement,
+            expressionStatementNode1: ESTree.ExpressionStatement,
+            functionDeclarationNode: ESTree.FunctionDeclaration,
+            programNode: ESTree.Program;
+
+        before(() => {
+            expressionStatementNode1 = NodeFactory.expressionStatementNode(NodeFactory.identifierNode('identifier'));
+            expressionStatementNode2 = NodeFactory.expressionStatementNode(NodeFactory.identifierNode('identifier'));
+            expressionStatementNode3 = NodeFactory.expressionStatementNode(NodeFactory.identifierNode('identifier'));
+
+            ifStatementBlockStatementNode2 = NodeFactory.blockStatementNode([
+                expressionStatementNode2,
+                expressionStatementNode3
+            ]);
+
+            ifStatementNode2 = NodeFactory.ifStatementNode(
+                NodeFactory.literalNode(true),
+                ifStatementBlockStatementNode2
+            );
+
+            ifStatementBlockStatementNode1 = NodeFactory.blockStatementNode([
+                ifStatementNode2
+            ]);
+
+            ifStatementNode1 = NodeFactory.ifStatementNode(
+                NodeFactory.literalNode(true),
+                ifStatementBlockStatementNode1
+            );
+
+            functionDeclarationBlockStatementNode = NodeFactory.blockStatementNode([
+                expressionStatementNode1,
+                ifStatementNode1
+            ]);
+
+            functionDeclarationNode = NodeFactory.functionDeclarationNode('test', [], functionDeclarationBlockStatementNode);
+
+            programNode = NodeFactory.programNode([
+                functionDeclarationNode
+            ]);
+
+            programNode.parentNode = programNode;
+            functionDeclarationNode.parentNode = programNode;
+            functionDeclarationBlockStatementNode.parentNode = functionDeclarationNode;
+            expressionStatementNode1.parentNode = functionDeclarationBlockStatementNode;
+            ifStatementNode1.parentNode = functionDeclarationBlockStatementNode;
+            ifStatementBlockStatementNode1.parentNode = ifStatementNode1;
+            ifStatementNode2.parentNode = ifStatementBlockStatementNode1;
+            ifStatementBlockStatementNode2.parentNode = ifStatementNode2;
+            expressionStatementNode3.parentNode = ifStatementBlockStatementNode2;
+        });
+
+        it('should return block-scope node for `program` node child node', () => {
+            assert.deepEqual(NodeUtils.getBlockScopeOfNode(programNode), programNode);
+        });
+
+        it('should return block-scope node for `functionDeclaration` node child node', () => {
+            assert.deepEqual(NodeUtils.getBlockScopeOfNode(functionDeclarationNode), programNode);
+        });
+
+        it('should return block-scope node for `functionDeclaration blockStatement` node child node', () => {
+            assert.deepEqual(NodeUtils.getBlockScopeOfNode(functionDeclarationBlockStatementNode), programNode);
+        });
+
+        it('should return block-scope node for `expressionStatement` node #1 child node', () => {
+            assert.deepEqual(NodeUtils.getBlockScopeOfNode(expressionStatementNode1), functionDeclarationBlockStatementNode);
+        });
+
+        it('should return block-scope node for `ifStatement` node child node', () => {
+            assert.deepEqual(NodeUtils.getBlockScopeOfNode(ifStatementNode1), functionDeclarationBlockStatementNode);
+        });
+
+        it('should return block-scope node for `ifStatement blockStatement` node #1 child node', () => {
+            assert.deepEqual(NodeUtils.getBlockScopeOfNode(ifStatementBlockStatementNode1), functionDeclarationBlockStatementNode);
+        });
+
+        it('should return block-scope node for `ifStatement blockStatement` node #2 child node', () => {
+            assert.deepEqual(NodeUtils.getBlockScopeOfNode(ifStatementBlockStatementNode2), functionDeclarationBlockStatementNode);
+        });
+
+        it('should return block-scope node for `expressionStatement` node #3 child node', () => {
+            assert.deepEqual(NodeUtils.getBlockScopeOfNode(expressionStatementNode3), functionDeclarationBlockStatementNode);
+        });
+
+        it('should throw a `ReferenceError` if node has no `parentNode` property', () => {
+            assert.throws(() => NodeUtils.getBlockScopeOfNode(expressionStatementNode2), ReferenceError);
+        });
+    });
+
     describe('getBlockScopesOfNode', () => {
         let functionDeclarationBlockStatementNode: ESTree.BlockStatement,
             ifStatementBlockStatementNode1: ESTree.BlockStatement,
@@ -239,7 +334,7 @@ describe('NodeUtils', () => {
             expressionStatementNode3.parentNode = ifStatementBlockStatementNode2;
         });
 
-        it('should return block-scope node for `program` node child', () => {
+        it('should return block-scope node for `program` node child node', () => {
             assert.deepEqual(NodeUtils.getBlockScopesOfNode(programNode)[0], programNode);
         });