Przeglądaj źródła

Merge pull request #552 from javascript-obfuscator/variable-preserve-improvements

Variables preserve transformer improvements
Timofey Kachalov 5 lat temu
rodzic
commit
fbab8149f7
100 zmienionych plików z 2021 dodań i 1259 usunięć
  1. 1 0
      .ncurc
  2. 8 0
      CHANGELOG.md
  3. 0 0
      dist/index.browser.js
  4. 0 0
      dist/index.cli.js
  5. 0 0
      dist/index.js
  6. 14 14
      package.json
  7. 9 18
      src/ASTParserFacade.ts
  8. 4 9
      src/JavaScriptObfuscator.ts
  9. 30 6
      src/cli/JavaScriptObfuscatorCLI.ts
  10. 5 1
      src/cli/utils/ObfuscatedCodeWriter.ts
  11. 3 28
      src/cli/utils/SourceCodeReader.ts
  12. 4 0
      src/container/InversifyContainerFacade.ts
  13. 7 6
      src/container/ServiceIdentifiers.ts
  14. 114 0
      src/container/modules/custom-code-helpers/CustomCodeHelpersModule.ts
  15. 3 101
      src/container/modules/custom-nodes/CustomNodesModule.ts
  16. 3 3
      src/container/modules/node-transformers/PreparingTransformersModule.ts
  17. 13 0
      src/container/modules/node/NodeModule.ts
  18. 5 5
      src/container/modules/storages/StoragesModule.ts
  19. 121 0
      src/custom-code-helpers/AbstractCustomCodeHelper.ts
  20. 17 16
      src/custom-code-helpers/AbstractCustomCodeHelperGroup.ts
  21. 2 2
      src/custom-code-helpers/CustomCodeHelperFormatter.ts
  22. 55 0
      src/custom-code-helpers/CustomCodeHelperObfuscator.ts
  23. 27 27
      src/custom-code-helpers/calls-controller/CallsControllerFunctionCodeHelper.ts
  24. 0 0
      src/custom-code-helpers/common/templates/GlobalVariableNoEvalTemplate.ts
  25. 0 0
      src/custom-code-helpers/common/templates/GlobalVariableTemplate1.ts
  26. 0 0
      src/custom-code-helpers/common/templates/GlobalVariableTemplate2.ts
  27. 2 2
      src/custom-code-helpers/common/templates/SingleCallControllerTemplate.ts
  28. 91 0
      src/custom-code-helpers/console-output/ConsoleOutputDisableCodeHelper.ts
  29. 129 0
      src/custom-code-helpers/console-output/group/ConsoleOutputCodeHelperGroup.ts
  30. 1 1
      src/custom-code-helpers/console-output/templates/ConsoleOutputDisableExpressionTemplate.ts
  31. 22 13
      src/custom-code-helpers/debug-protection/DebugProtectionFunctionCallCodeHelper.ts
  32. 23 14
      src/custom-code-helpers/debug-protection/DebugProtectionFunctionCodeHelper.ts
  33. 21 12
      src/custom-code-helpers/debug-protection/DebugProtectionFunctionIntervalCodeHelper.ts
  34. 166 0
      src/custom-code-helpers/debug-protection/group/DebugProtectionCodeHelperGroup.ts
  35. 1 1
      src/custom-code-helpers/debug-protection/templates/debug-protection-function-call/DebugProtectionFunctionCallTemplate.ts
  36. 0 0
      src/custom-code-helpers/debug-protection/templates/debug-protection-function-interval/DebugProtectionFunctionIntervalTemplate.ts
  37. 0 0
      src/custom-code-helpers/debug-protection/templates/debug-protection-function/DebugProtectionFunctionTemplate.ts
  38. 0 0
      src/custom-code-helpers/debug-protection/templates/debug-protection-function/DebuggerTemplate.ts
  39. 0 0
      src/custom-code-helpers/debug-protection/templates/debug-protection-function/DebuggerTemplateNoEval.ts
  40. 35 18
      src/custom-code-helpers/domain-lock/DomainLockCodeHelper.ts
  41. 129 0
      src/custom-code-helpers/domain-lock/group/DomainLockCustomCodeHelperGroup.ts
  42. 2 2
      src/custom-code-helpers/domain-lock/templates/DomainLockTemplate.ts
  43. 33 28
      src/custom-code-helpers/self-defending/SelfDefendingUnicodeCodeHelper.ts
  44. 126 0
      src/custom-code-helpers/self-defending/group/SelfDefendingCodeHelperGroup.ts
  45. 26 0
      src/custom-code-helpers/self-defending/templates/SelfDefendingTemplate.ts
  46. 41 36
      src/custom-code-helpers/string-array/StringArrayCallsWrapperCodeHelper.ts
  47. 21 12
      src/custom-code-helpers/string-array/StringArrayCodeHelper.ts
  48. 31 27
      src/custom-code-helpers/string-array/StringArrayRotateFunctionCodeHelper.ts
  49. 133 0
      src/custom-code-helpers/string-array/group/StringArrayCodeHelperGroup.ts
  50. 0 0
      src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/AtobTemplate.ts
  51. 0 0
      src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/Rc4Template.ts
  52. 2 2
      src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/SelfDefendingTemplate.ts
  53. 2 2
      src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/StringArrayBase64DecodeTemplate.ts
  54. 1 1
      src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/StringArrayCallsWrapperTemplate.ts
  55. 2 2
      src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/StringArrayRC4DecodeTemplate.ts
  56. 1 1
      src/custom-code-helpers/string-array/templates/string-array-rotate-function/SelfDefendingTemplate.ts
  57. 0 0
      src/custom-code-helpers/string-array/templates/string-array-rotate-function/StringArrayRotateFunctionTemplate.ts
  58. 0 0
      src/custom-code-helpers/string-array/templates/string-array/StringArrayTemplate.ts
  59. 11 40
      src/custom-nodes/AbstractCustomNode.ts
  60. 0 74
      src/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.ts
  61. 0 107
      src/custom-nodes/console-output-nodes/group/ConsoleOutputCustomNodeGroup.ts
  62. 10 6
      src/custom-nodes/control-flow-flattening-nodes/BinaryExpressionFunctionNode.ts
  63. 10 6
      src/custom-nodes/control-flow-flattening-nodes/BlockStatementControlFlowFlatteningNode.ts
  64. 10 6
      src/custom-nodes/control-flow-flattening-nodes/CallExpressionFunctionNode.ts
  65. 10 6
      src/custom-nodes/control-flow-flattening-nodes/LogicalExpressionFunctionNode.ts
  66. 10 6
      src/custom-nodes/control-flow-flattening-nodes/StringLiteralNode.ts
  67. 12 4
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/CallExpressionControlFlowStorageCallNode.ts
  68. 10 6
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ControlFlowStorageNode.ts
  69. 12 4
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ExpressionWithOperatorControlFlowStorageCallNode.ts
  70. 12 4
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/StringLiteralControlFlowStorageCallNode.ts
  71. 10 6
      src/custom-nodes/dead-code-injection-nodes/BlockStatementDeadCodeInjectionNode.ts
  72. 0 138
      src/custom-nodes/debug-protection-nodes/group/DebugProtectionCustomNodeGroup.ts
  73. 0 107
      src/custom-nodes/domain-lock-nodes/group/DomainLockCustomNodeGroup.ts
  74. 23 10
      src/custom-nodes/object-expression-keys-transformer-nodes/ObjectExpressionVariableDeclarationHostNode.ts
  75. 0 107
      src/custom-nodes/self-defending-nodes/group/SelfDefendingCustomNodeGroup.ts
  76. 0 124
      src/custom-nodes/string-array-nodes/group/StringArrayCustomNodeGroup.ts
  77. 8 0
      src/declarations/environment.d.ts
  78. 12 0
      src/enums/custom-code-helpers/CustomCodeHelper.ts
  79. 7 0
      src/enums/custom-code-helpers/CustomCodeHelperGroup.ts
  80. 0 12
      src/enums/custom-nodes/CustomNode.ts
  81. 0 7
      src/enums/custom-nodes/CustomNodeGroup.ts
  82. 1 1
      src/enums/node-transformers/NodeTransformer.ts
  83. 67 2
      src/generators/identifier-names-generators/AbstractIdentifierNamesGenerator.ts
  84. 59 13
      src/generators/identifier-names-generators/DictionaryIdentifierNamesGenerator.ts
  85. 16 10
      src/generators/identifier-names-generators/HexadecimalIdentifierNamesGenerator.ts
  86. 67 4
      src/generators/identifier-names-generators/MangledIdentifierNamesGenerator.ts
  87. 0 11
      src/interfaces/IASTParserFacadeInputData.ts
  88. 12 0
      src/interfaces/custom-code-helpers/ICustomCodeHelper.ts
  89. 1 1
      src/interfaces/custom-code-helpers/ICustomCodeHelperFormatter.ts
  90. 6 6
      src/interfaces/custom-code-helpers/ICustomCodeHelperGroup.ts
  91. 10 0
      src/interfaces/custom-code-helpers/ICustomCodeHelperObfuscator.ts
  92. 33 3
      src/interfaces/generators/identifier-names-generators/IIdentifierNamesGenerator.ts
  93. 8 2
      src/interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/IIdentifierObfuscatingReplacer.ts
  94. 17 0
      src/interfaces/node/IScopeIdentifiersTraverser.ts
  95. 11 0
      src/interfaces/node/IScopeIdentifiersTraverserCallbackData.ts
  96. 0 1
      src/interfaces/options/IOptions.ts
  97. 2 0
      src/interfaces/utils/IRandomGenerator.ts
  98. 24 3
      src/node-transformers/converting-transformers/ObjectExpressionKeysTransformer.ts
  99. 24 7
      src/node-transformers/converting-transformers/object-expression-extractors/ObjectExpressionToVariableDeclarationExtractor.ts
  100. 10 5
      src/node-transformers/dead-code-injection-transformers/DeadCodeInjectionTransformer.ts

+ 1 - 0
.ncurc

@@ -1,5 +1,6 @@
 {
   "reject": [
+    "@types/node",
     "ts-node"
   ]
 }

+ 8 - 0
CHANGELOG.md

@@ -1,5 +1,13 @@
 Change Log
 
+v0.25.0
+---
+* Improved `mangled` identifier names generator logic
+* Improved `selfDefending` helper logic
+* Fixed a bunch of conflicts between generated identifier names. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/550. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/549
+* Prevented transformation of object keys in sequence expression that has `super` call
+* Support of output directory paths with a dot symbol
+
 v0.24.6
 ---
 * Fixed support of exponentiation operator. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/534

Plik diff jest za duży
+ 0 - 0
dist/index.browser.js


Plik diff jest za duży
+ 0 - 0
dist/index.cli.js


Plik diff jest za duży
+ 0 - 0
dist/index.js


+ 14 - 14
package.json

@@ -1,6 +1,6 @@
 {
   "name": "javascript-obfuscator",
-  "version": "0.24.6",
+  "version": "0.25.0",
   "description": "JavaScript obfuscator",
   "keywords": [
     "obfuscator",
@@ -42,17 +42,17 @@
     "reflect-metadata": "0.1.13",
     "source-map-support": "0.5.16",
     "string-template": "1.0.0",
-    "tslib": "1.10.0"
+    "tslib": "1.11.0"
   },
   "devDependencies": {
-    "@types/chai": "4.2.8",
+    "@types/chai": "4.2.9",
     "@types/chance": "1.0.8",
     "@types/escodegen": "0.0.6",
     "@types/eslint-scope": "3.7.0",
     "@types/estraverse": "0.0.6",
     "@types/estree": "0.0.42",
     "@types/md5": "2.1.33",
-    "@types/mkdirp": "0.5.2",
+    "@types/mkdirp": "1.0.0",
     "@types/mocha": "7.0.1",
     "@types/multimatch": "4.0.0",
     "@types/node": "12.12.14",
@@ -60,8 +60,8 @@
     "@types/sinon": "7.5.1",
     "@types/string-template": "1.0.2",
     "@types/webpack-env": "1.15.1",
-    "@typescript-eslint/eslint-plugin": "2.19.0",
-    "@typescript-eslint/parser": "2.19.0",
+    "@typescript-eslint/eslint-plugin": "2.20.0",
+    "@typescript-eslint/parser": "2.20.0",
     "chai": "4.2.0",
     "coveralls": "3.0.9",
     "eslint": "6.8.0",
@@ -69,21 +69,21 @@
     "eslint-plugin-jsdoc": "21.0.0",
     "eslint-plugin-no-null": "1.0.2",
     "eslint-plugin-prefer-arrow": "1.1.7",
-    "eslint-plugin-unicorn": "16.0.0",
+    "eslint-plugin-unicorn": "16.1.1",
     "fork-ts-checker-notifier-webpack-plugin": "2.0.0",
-    "fork-ts-checker-webpack-plugin": "4.0.3",
+    "fork-ts-checker-webpack-plugin": "4.0.4",
     "mocha": "7.0.1",
     "nyc": "15.0.0",
     "pjson": "1.0.9",
     "pre-commit": "1.2.2",
-    "rimraf": "3.0.1",
-    "sinon": "8.1.1",
-    "threads": "1.0.2",
+    "rimraf": "3.0.2",
+    "sinon": "9.0.0",
+    "threads": "1.2.0",
     "ts-loader": "6.2.1",
     "ts-node": "6.1.0",
-    "typescript": "3.8.0-beta",
-    "webpack": "4.41.5",
-    "webpack-cli": "3.3.10",
+    "typescript": "3.8.2",
+    "webpack": "4.41.6",
+    "webpack-cli": "3.3.11",
     "webpack-node-externals": "1.7.2"
   },
   "repository": {

+ 9 - 18
src/ASTParserFacade.ts

@@ -3,8 +3,6 @@ import acornImportMeta from 'acorn-import-meta';
 import * as ESTree from 'estree';
 import chalk, { Chalk } from 'chalk';
 
-import { IASTParserFacadeInputData } from './interfaces/IASTParserFacadeInputData';
-
 /**
  * Facade over AST parser `acorn`
  */
@@ -28,23 +26,23 @@ export class ASTParserFacade {
     ];
 
     /**
-     * @param {string} inputData
+     * @param {string} sourceCode
      * @param {Options} config
      * @returns {Program}
      */
-    public static parse (inputData: IASTParserFacadeInputData, config: acorn.Options): ESTree.Program | never {
+    public static parse (sourceCode: string, config: acorn.Options): ESTree.Program | never {
         const sourceTypeLength: number = ASTParserFacade.sourceTypes.length;
 
         for (let i: number = 0; i < sourceTypeLength; i++) {
             try {
-                return ASTParserFacade.parseType(inputData, config, ASTParserFacade.sourceTypes[i]);
+                return ASTParserFacade.parseType(sourceCode, config, ASTParserFacade.sourceTypes[i]);
             } catch (error) {
                 if (i < sourceTypeLength - 1) {
                     continue;
                 }
 
                 throw new Error(ASTParserFacade.processParsingError(
-                    inputData,
+                    sourceCode,
                     error.message,
                     error.loc
                 ));
@@ -55,17 +53,16 @@ export class ASTParserFacade {
     }
 
     /**
-     * @param {IASTParserFacadeInputData} inputData
+     * @param {string} sourceCode
      * @param {acorn.Options} inputConfig
      * @param {acorn.Options["sourceType"]} sourceType
      * @returns {Program}
      */
     private static parseType (
-        inputData: IASTParserFacadeInputData,
+        sourceCode: string,
         inputConfig: acorn.Options,
         sourceType: acorn.Options['sourceType']
     ): ESTree.Program {
-        const { sourceCode } = inputData;
         const comments: ESTree.Comment[] = [];
         const config: acorn.Options = {
             ...inputConfig,
@@ -85,13 +82,13 @@ export class ASTParserFacade {
     }
 
     /**
-     * @param {IASTParserFacadeInputData} inputData
+     * @param {string} sourceCode
      * @param {string} errorMessage
      * @param {Position | null} position
      * @returns {never}
      */
     private static processParsingError (
-        inputData: IASTParserFacadeInputData,
+        sourceCode: string,
         errorMessage: string,
         position: ESTree.Position | null
     ): never {
@@ -99,8 +96,6 @@ export class ASTParserFacade {
             throw new Error(errorMessage);
         }
 
-        const { sourceCode, inputFilePath } = inputData;
-
         const sourceCodeLines: string[] = sourceCode.split(/\r?\n/);
         const errorLine: string | undefined = sourceCodeLines[position.line - 1];
 
@@ -108,10 +103,6 @@ export class ASTParserFacade {
             throw new Error(errorMessage);
         }
 
-        const formattedInputFilePath: string = inputFilePath
-            ? `${inputFilePath}, `
-            : '';
-
         const startErrorIndex: number = Math.max(0, position.column - ASTParserFacade.nearestSymbolsCount);
         const endErrorIndex: number = Math.min(errorLine.length, position.column + ASTParserFacade.nearestSymbolsCount);
 
@@ -121,7 +112,7 @@ export class ASTParserFacade {
         }...`;
 
         throw new Error(
-            `ERROR in ${formattedInputFilePath}line ${position.line}: ${errorMessage}\n${formattedPointer} ${formattedCodeSlice}`
+            `ERROR at line ${position.line}: ${errorMessage}\n${formattedPointer} ${formattedCodeSlice}`
         );
     }
 }

+ 4 - 9
src/JavaScriptObfuscator.ts

@@ -7,7 +7,6 @@ import * as ESTree from 'estree';
 
 import { TObfuscatedCodeFactory } from './types/container/source-code/TObfuscatedCodeFactory';
 
-import { IASTParserFacadeInputData } from './interfaces/IASTParserFacadeInputData';
 import { IGeneratorOutput } from './interfaces/IGeneratorOutput';
 import { IJavaScriptObfuscator } from './interfaces/IJavaScriptObfsucator';
 import { ILogger } from './interfaces/logger/ILogger';
@@ -24,6 +23,7 @@ import { ecmaVersion } from './constants/EcmaVersion';
 
 import { ASTParserFacade } from './ASTParserFacade';
 import { NodeGuards } from './node/NodeGuards';
+import { Utils } from './utils/Utils';
 
 @injectable()
 export class JavaScriptObfuscator implements IJavaScriptObfuscator {
@@ -54,7 +54,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
     private static readonly transformersList: NodeTransformer[] = [
         NodeTransformer.BlockStatementControlFlowTransformer,
         NodeTransformer.CommentsTransformer,
-        NodeTransformer.CustomNodesTransformer,
+        NodeTransformer.CustomCodeHelpersTransformer,
         NodeTransformer.DeadCodeInjectionTransformer,
         NodeTransformer.EvalCallExpressionTransformer,
         NodeTransformer.FunctionControlFlowTransformer,
@@ -125,7 +125,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
      */
     public obfuscate (sourceCode: string): IObfuscatedCode {
         const timeStart: number = Date.now();
-        this.logger.info(LoggingMessage.Version, process.env.VERSION);
+        this.logger.info(LoggingMessage.Version, Utils.buildVersionMessage(process.env.VERSION, process.env.BUILD_TIMESTAMP));
         this.logger.info(LoggingMessage.ObfuscationStarted);
         this.logger.info(LoggingMessage.RandomGeneratorSeed, this.randomGenerator.getInputSeed());
 
@@ -149,12 +149,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
      * @returns {Program}
      */
     private parseCode (sourceCode: string): ESTree.Program {
-        const inputData: IASTParserFacadeInputData = {
-            sourceCode,
-            inputFilePath: this.options.inputFilePath
-        };
-
-        return ASTParserFacade.parse(inputData, JavaScriptObfuscator.parseOptions);
+        return ASTParserFacade.parse(sourceCode, JavaScriptObfuscator.parseOptions);
     }
 
     /**

+ 30 - 6
src/cli/JavaScriptObfuscatorCLI.ts

@@ -21,10 +21,20 @@ import { StringArrayEncodingSanitizer } from './sanitizers/StringArrayEncodingSa
 
 import { CLIUtils } from './utils/CLIUtils';
 import { JavaScriptObfuscator } from '../JavaScriptObfuscatorFacade';
+import { Logger } from '../logger/Logger';
 import { ObfuscatedCodeWriter } from './utils/ObfuscatedCodeWriter';
 import { SourceCodeReader } from './utils/SourceCodeReader';
+import { Utils } from '../utils/Utils';
+import { LoggingPrefix } from '../enums/logger/LoggingPrefix';
 
 export class JavaScriptObfuscatorCLI implements IInitializable {
+    /**
+     * @type {string[]}
+     */
+    public static readonly availableInputExtensions: string[] = [
+        '.js'
+    ];
+
     /**
      * @type {BufferEncoding}
      */
@@ -33,7 +43,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
     /**
      * @type {string}
      */
-    public static obfuscatedFilePrefix: string = '-obfuscated';
+    public static readonly obfuscatedFilePrefix: string = '-obfuscated';
 
     /**
      * @type {string}
@@ -102,14 +112,12 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
         const configFileLocation: string = configFilePath ? path.resolve(configFilePath, '.') : '';
         const configFileOptions: TInputOptions = configFileLocation ? CLIUtils.getUserConfig(configFileLocation) : {};
         const inputFileName: string = path.basename(inputCodePath);
-        const inputFilePath: string = inputCodePath;
 
         return {
             ...DEFAULT_PRESET,
             ...configFileOptions,
             ...inputCLIOptions,
-            inputFileName,
-            inputFilePath
+            inputFileName
         };
     }
 
@@ -169,7 +177,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
         this.commands
             .usage('<inputPath> [options]')
             .version(
-                process.env.VERSION ?? 'unknown',
+                Utils.buildVersionMessage(process.env.VERSION, process.env.BUILD_TIMESTAMP),
                 '-v, --version'
             )
             .option(
@@ -366,7 +374,23 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
         sourceCodeData.forEach(({ filePath, content }: IFileData, index: number) => {
             const outputCodePath: string = this.obfuscatedCodeWriter.getOutputCodePath(filePath);
 
-            this.processSourceCode(content, filePath, outputCodePath, index);
+            try {
+                Logger.log(
+                    Logger.colorInfo,
+                    LoggingPrefix.CLI,
+                    `Obfuscating file: ${filePath}...`
+                );
+
+                this.processSourceCode(content, filePath, outputCodePath, index);
+            } catch (error) {
+                Logger.log(
+                    Logger.colorInfo,
+                    LoggingPrefix.CLI,
+                    `Error in file: ${filePath}...`
+                );
+
+                throw error;
+            }
         });
     }
 

+ 5 - 1
src/cli/utils/ObfuscatedCodeWriter.ts

@@ -51,8 +51,12 @@ export class ObfuscatedCodeWriter {
         }
 
         const rawInputPathStats: fs.Stats = fs.lstatSync(this.inputPath);
+        const outputPathExtName: string = path.extname(normalizedRawOutputPath);
+
         const isDirectoryRawInputPath: boolean = rawInputPathStats.isDirectory();
-        const isDirectoryRawOutputPath: boolean = path.extname(normalizedRawOutputPath) === '';
+        const isDirectoryRawOutputPath: boolean = !JavaScriptObfuscatorCLI
+            .availableInputExtensions
+            .includes(outputPathExtName);
 
         if (isDirectoryRawInputPath) {
             if (isDirectoryRawOutputPath) {

+ 3 - 28
src/cli/utils/SourceCodeReader.ts

@@ -6,19 +6,9 @@ import { TInputCLIOptions } from '../../types/options/TInputCLIOptions';
 
 import { IFileData } from '../../interfaces/cli/IFileData';
 
-import { LoggingPrefix } from '../../enums/logger/LoggingPrefix';
-
 import { JavaScriptObfuscatorCLI } from '../JavaScriptObfuscatorCLI';
-import { Logger } from '../../logger/Logger';
 
 export class SourceCodeReader {
-    /**
-     * @type {string[]}
-     */
-    public static readonly availableInputExtensions: string[] = [
-        '.js'
-    ];
-
     /**
      * @type {string}
      */
@@ -99,33 +89,18 @@ export class SourceCodeReader {
      * @returns {boolean}
      */
     private static isValidFile (filePath: string, excludePatterns: string[] = []): boolean {
-        return SourceCodeReader.availableInputExtensions.includes(path.extname(filePath))
+        return JavaScriptObfuscatorCLI.availableInputExtensions.includes(path.extname(filePath))
             && !filePath.includes(JavaScriptObfuscatorCLI.obfuscatedFilePrefix)
             && !SourceCodeReader.isExcludedPath(filePath, excludePatterns);
     }
 
-    /**
-     * @param {string} filePath
-     */
-    private static logFilePath (filePath: string): void {
-        const normalizedFilePath: string = path.normalize(filePath);
-
-        Logger.log(
-            Logger.colorInfo,
-            LoggingPrefix.CLI,
-            `Obfuscating file: ${normalizedFilePath}...`
-        );
-    }
-
     /**
      * @param {string} filePath
      * @returns {string}
      */
     private static readFile (filePath: string): IFileData {
-        SourceCodeReader.logFilePath(filePath);
-
         return {
-            filePath,
+            filePath: path.normalize(filePath),
             content: fs.readFileSync(filePath, JavaScriptObfuscatorCLI.encoding)
         };
     }
@@ -148,7 +123,7 @@ export class SourceCodeReader {
             return this.readDirectoryRecursive(this.inputPath);
         }
 
-        const availableFilePaths: string = SourceCodeReader
+        const availableFilePaths: string = JavaScriptObfuscatorCLI
             .availableInputExtensions
             .map((extension: string) => `\`${extension}\``)
             .join(', ');

+ 4 - 0
src/container/InversifyContainerFacade.ts

@@ -4,9 +4,11 @@ import { ServiceIdentifiers } from './ServiceIdentifiers';
 import { analyzersModule } from './modules/analyzers/AnalyzersModule';
 import { controlFlowTransformersModule } from './modules/node-transformers/ControlFlowTransformersModule';
 import { convertingTransformersModule } from './modules/node-transformers/ConvertingTransformersModule';
+import { customCodeHelpersModule } from './modules/custom-code-helpers/CustomCodeHelpersModule';
 import { customNodesModule } from './modules/custom-nodes/CustomNodesModule';
 import { finalizingTransformersModule } from './modules/node-transformers/FinalizingTransformersModule';
 import { generatorsModule } from './modules/generators/GeneratorsModule';
+import { nodeModule } from './modules/node/NodeModule';
 import { nodeTransformersModule } from './modules/node-transformers/NodeTransformersModule';
 import { obfuscatingTransformersModule } from './modules/node-transformers/ObfuscatingTransformersModule';
 import { optionsModule } from './modules/options/OptionsModule';
@@ -193,9 +195,11 @@ export class InversifyContainerFacade implements IInversifyContainerFacade {
         this.container.load(analyzersModule);
         this.container.load(controlFlowTransformersModule);
         this.container.load(convertingTransformersModule);
+        this.container.load(customCodeHelpersModule);
         this.container.load(customNodesModule);
         this.container.load(finalizingTransformersModule);
         this.container.load(generatorsModule);
+        this.container.load(nodeModule);
         this.container.load(nodeTransformersModule);
         this.container.load(obfuscatingTransformersModule);
         this.container.load(optionsModule);

+ 7 - 6
src/container/ServiceIdentifiers.ts

@@ -2,8 +2,8 @@ export enum ServiceIdentifiers {
     Factory__ICalleeDataExtractor = 'Factory<ICalleeDataExtractor>',
     Factory__IControlFlowCustomNode = 'Factory<IControlFlowCustomNode>',
     Factory__IControlFlowReplacer = 'Factory<IControlFlowReplacer>',
-    Factory__ICustomNode = 'Factory<ICustomNode>',
-    Factory__ICustomNodeGroup = 'Factory<ICustomNodeGroup>',
+    Factory__ICustomCodeHelper = 'Factory<ICustomCodeHelper>',
+    Factory__ICustomCodeHelperGroup = 'Factory<ICustomCodeHelperGroup>',
     Factory__IDeadCodeInjectionCustomNode = 'Factory<IDeadCodeInjectionCustomNode>',
     Factory__IIdentifierNamesGenerator = 'Factory<IIdentifierNamesGenerator>',
     Factory__IIdentifierObfuscatingReplacer = 'Factory<IIdentifierObfuscatingReplacer>',
@@ -18,10 +18,11 @@ export enum ServiceIdentifiers {
     ICalleeDataExtractor = 'ICalleeDataExtractor',
     ICallsGraphAnalyzer = 'ICallsGraphAnalyzer',
     ICryptUtils = 'ICryptUtils',
-    ICustomNode = 'ICustomNode',
-    ICustomNodeGroup = 'ICustomNodeGroup',
+    ICustomCodeHelper = 'ICustomCodeHelper',
+    ICustomCodeHelperGroup = 'ICustomCodeHelperGroup',
     IControlFlowReplacer = 'IControlFlowReplacer',
-    ICustomNodeFormatter = 'ICustomNodeFormatter',
+    ICustomCodeHelperFormatter = 'ICustomCodeHelperFormatter',
+    ICustomCodeHelperObfuscator = 'ICustomCodeHelperObfuscator',
     IEscapeSequenceEncoder = 'IEscapeSequenceEncoder',
     IIdentifierNamesGenerator = 'IIdentifierNamesGenerator',
     IIdentifierObfuscatingReplacer = 'IIdentifierObfuscatingReplacer',
@@ -39,8 +40,8 @@ export enum ServiceIdentifiers {
     IPrevailingKindOfVariablesAnalyzer = 'IPrevailingKindOfVariablesAnalyzer',
     IObjectExpressionExtractor = 'IObjectExpressionExtractor',
     IRandomGenerator = 'IRandomGenerator',
+    IScopeIdentifiersTraverser = 'IScopeIdentifiersTraverser',
     ISourceCode = 'ISourceCode',
-    ISourceMapCorrector = 'ISourceMapCorrector',
     IScopeAnalyzer = 'IScopeAnalyzer',
     IStringArrayStorage = 'IStringArrayStorage',
     IStringArrayStorageAnalyzer = 'IStringArrayStorageAnalyzer',

+ 114 - 0
src/container/modules/custom-code-helpers/CustomCodeHelpersModule.ts

@@ -0,0 +1,114 @@
+import { InversifyContainerFacade } from '../../InversifyContainerFacade';
+import { ContainerModule, interfaces } from 'inversify';
+import { ServiceIdentifiers } from '../../ServiceIdentifiers';
+
+import { ICustomCodeHelper } from '../../../interfaces/custom-code-helpers/ICustomCodeHelper';
+import { ICustomCodeHelperFormatter } from '../../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
+import { ICustomCodeHelperGroup } from '../../../interfaces/custom-code-helpers/ICustomCodeHelperGroup';
+import { ICustomCodeHelperObfuscator } from '../../../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
+
+import { CustomCodeHelper } from '../../../enums/custom-code-helpers/CustomCodeHelper';
+import { CustomCodeHelperGroup } from '../../../enums/custom-code-helpers/CustomCodeHelperGroup';
+
+import { ConsoleOutputCodeHelperGroup } from '../../../custom-code-helpers/console-output/group/ConsoleOutputCodeHelperGroup';
+import { DebugProtectionCodeHelperGroup } from '../../../custom-code-helpers/debug-protection/group/DebugProtectionCodeHelperGroup';
+import { DomainLockCustomCodeHelperGroup } from '../../../custom-code-helpers/domain-lock/group/DomainLockCustomCodeHelperGroup';
+import { SelfDefendingCodeHelperGroup } from '../../../custom-code-helpers/self-defending/group/SelfDefendingCodeHelperGroup';
+import { StringArrayCodeHelperGroup } from '../../../custom-code-helpers/string-array/group/StringArrayCodeHelperGroup';
+
+import { ConsoleOutputDisableCodeHelper } from '../../../custom-code-helpers/console-output/ConsoleOutputDisableCodeHelper';
+import { CustomCodeHelperFormatter } from '../../../custom-code-helpers/CustomCodeHelperFormatter';
+import { CustomCodeHelperObfuscator } from '../../../custom-code-helpers/CustomCodeHelperObfuscator';
+import { DebugProtectionFunctionCallCodeHelper } from '../../../custom-code-helpers/debug-protection/DebugProtectionFunctionCallCodeHelper';
+import { DebugProtectionFunctionIntervalCodeHelper } from '../../../custom-code-helpers/debug-protection/DebugProtectionFunctionIntervalCodeHelper';
+import { DebugProtectionFunctionCodeHelper } from '../../../custom-code-helpers/debug-protection/DebugProtectionFunctionCodeHelper';
+import { DomainLockCodeHelper } from '../../../custom-code-helpers/domain-lock/DomainLockCodeHelper';
+import { CallsControllerFunctionCodeHelper } from '../../../custom-code-helpers/calls-controller/CallsControllerFunctionCodeHelper';
+import { SelfDefendingUnicodeCodeHelper } from '../../../custom-code-helpers/self-defending/SelfDefendingUnicodeCodeHelper';
+import { StringArrayCallsWrapperCodeHelper } from '../../../custom-code-helpers/string-array/StringArrayCallsWrapperCodeHelper';
+import { StringArrayCodeHelper } from '../../../custom-code-helpers/string-array/StringArrayCodeHelper';
+import { StringArrayRotateFunctionCodeHelper } from '../../../custom-code-helpers/string-array/StringArrayRotateFunctionCodeHelper';
+
+export const customCodeHelpersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
+    // custom code helpers
+    bind<ICustomCodeHelper>(ServiceIdentifiers.ICustomCodeHelper)
+        .to(ConsoleOutputDisableCodeHelper)
+        .whenTargetNamed(CustomCodeHelper.ConsoleOutputDisable);
+
+    bind<ICustomCodeHelper>(ServiceIdentifiers.ICustomCodeHelper)
+        .to(DebugProtectionFunctionCallCodeHelper)
+        .whenTargetNamed(CustomCodeHelper.DebugProtectionFunctionCall);
+
+    bind<ICustomCodeHelper>(ServiceIdentifiers.ICustomCodeHelper)
+        .to(DebugProtectionFunctionIntervalCodeHelper)
+        .whenTargetNamed(CustomCodeHelper.DebugProtectionFunctionInterval);
+
+    bind<ICustomCodeHelper>(ServiceIdentifiers.ICustomCodeHelper)
+        .to(DebugProtectionFunctionCodeHelper)
+        .whenTargetNamed(CustomCodeHelper.DebugProtectionFunction);
+
+    bind<ICustomCodeHelper>(ServiceIdentifiers.ICustomCodeHelper)
+        .to(DomainLockCodeHelper)
+        .whenTargetNamed(CustomCodeHelper.DomainLock);
+
+    bind<ICustomCodeHelper>(ServiceIdentifiers.ICustomCodeHelper)
+        .to(CallsControllerFunctionCodeHelper)
+        .whenTargetNamed(CustomCodeHelper.CallsControllerFunction);
+
+    bind<ICustomCodeHelper>(ServiceIdentifiers.ICustomCodeHelper)
+        .to(SelfDefendingUnicodeCodeHelper)
+        .whenTargetNamed(CustomCodeHelper.SelfDefendingUnicode);
+
+    bind<ICustomCodeHelper>(ServiceIdentifiers.ICustomCodeHelper)
+        .to(StringArrayCallsWrapperCodeHelper)
+        .whenTargetNamed(CustomCodeHelper.StringArrayCallsWrapper);
+
+    bind<ICustomCodeHelper>(ServiceIdentifiers.ICustomCodeHelper)
+        .to(StringArrayCodeHelper)
+        .whenTargetNamed(CustomCodeHelper.StringArray);
+
+    bind<ICustomCodeHelper>(ServiceIdentifiers.ICustomCodeHelper)
+        .to(StringArrayRotateFunctionCodeHelper)
+        .whenTargetNamed(CustomCodeHelper.StringArrayRotateFunction);
+
+    // code helper groups
+    bind<ICustomCodeHelperGroup>(ServiceIdentifiers.ICustomCodeHelperGroup)
+        .to(ConsoleOutputCodeHelperGroup)
+        .whenTargetNamed(CustomCodeHelperGroup.ConsoleOutput);
+
+    bind<ICustomCodeHelperGroup>(ServiceIdentifiers.ICustomCodeHelperGroup)
+        .to(DebugProtectionCodeHelperGroup)
+        .whenTargetNamed(CustomCodeHelperGroup.DebugProtection);
+
+    bind<ICustomCodeHelperGroup>(ServiceIdentifiers.ICustomCodeHelperGroup)
+        .to(DomainLockCustomCodeHelperGroup)
+        .whenTargetNamed(CustomCodeHelperGroup.DomainLock);
+
+    bind<ICustomCodeHelperGroup>(ServiceIdentifiers.ICustomCodeHelperGroup)
+        .to(SelfDefendingCodeHelperGroup)
+        .whenTargetNamed(CustomCodeHelperGroup.SelfDefending);
+
+    bind<ICustomCodeHelperGroup>(ServiceIdentifiers.ICustomCodeHelperGroup)
+        .to(StringArrayCodeHelperGroup)
+        .whenTargetNamed(CustomCodeHelperGroup.StringArray);
+
+    // customCodeHelper factory
+    bind<ICustomCodeHelper>(ServiceIdentifiers.Factory__ICustomCodeHelper)
+        .toFactory<ICustomCodeHelper>(InversifyContainerFacade
+            .getFactory<CustomCodeHelper, ICustomCodeHelper>(ServiceIdentifiers.ICustomCodeHelper));
+
+    // customCodeHelperGroup factory
+    bind<ICustomCodeHelperGroup>(ServiceIdentifiers.Factory__ICustomCodeHelperGroup)
+        .toFactory<ICustomCodeHelperGroup>(InversifyContainerFacade
+            .getFactory<CustomCodeHelperGroup, ICustomCodeHelperGroup>(ServiceIdentifiers.ICustomCodeHelperGroup));
+
+    // custom code helper formatter
+    bind<ICustomCodeHelperFormatter>(ServiceIdentifiers.ICustomCodeHelperFormatter)
+        .to(CustomCodeHelperFormatter)
+        .inSingletonScope();
+
+    // custom code helper obfuscator
+    bind<ICustomCodeHelperObfuscator>(ServiceIdentifiers.ICustomCodeHelperObfuscator)
+        .to(CustomCodeHelperObfuscator)
+        .inSingletonScope();
+});

+ 3 - 101
src/container/modules/custom-nodes/CustomNodesModule.ts

@@ -3,21 +3,11 @@ import { ContainerModule, interfaces } from 'inversify';
 import { ServiceIdentifiers } from '../../ServiceIdentifiers';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
-import { ICustomNodeFormatter } from '../../../interfaces/custom-nodes/ICustomNodeFormatter';
-import { ICustomNodeGroup } from '../../../interfaces/custom-nodes/ICustomNodeGroup';
 
 import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCustomNode';
-import { CustomNode } from '../../../enums/custom-nodes/CustomNode';
-import { CustomNodeGroup } from '../../../enums/custom-nodes/CustomNodeGroup';
 import { DeadCodeInjectionCustomNode } from '../../../enums/custom-nodes/DeadCodeInjectionCustomNode';
 import { ObjectExpressionKeysTransformerCustomNode } from '../../../enums/custom-nodes/ObjectExpressionKeysTransformerCustomNode';
 
-import { ConsoleOutputCustomNodeGroup } from '../../../custom-nodes/console-output-nodes/group/ConsoleOutputCustomNodeGroup';
-import { DebugProtectionCustomNodeGroup } from '../../../custom-nodes/debug-protection-nodes/group/DebugProtectionCustomNodeGroup';
-import { DomainLockCustomNodeGroup } from '../../../custom-nodes/domain-lock-nodes/group/DomainLockCustomNodeGroup';
-import { SelfDefendingCustomNodeGroup } from '../../../custom-nodes/self-defending-nodes/group/SelfDefendingCustomNodeGroup';
-import { StringArrayCustomNodeGroup } from '../../../custom-nodes/string-array-nodes/group/StringArrayCustomNodeGroup';
-
 import { ObjectExpressionVariableDeclarationHostNode } from '../../../custom-nodes/object-expression-keys-transformer-nodes/ObjectExpressionVariableDeclarationHostNode';
 import { BinaryExpressionFunctionNode } from '../../../custom-nodes/control-flow-flattening-nodes/BinaryExpressionFunctionNode';
 import { BlockStatementControlFlowFlatteningNode } from '../../../custom-nodes/control-flow-flattening-nodes/BlockStatementControlFlowFlatteningNode';
@@ -25,64 +15,12 @@ import { BlockStatementDeadCodeInjectionNode } from '../../../custom-nodes/dead-
 import { CallExpressionControlFlowStorageCallNode } from '../../../custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/CallExpressionControlFlowStorageCallNode';
 import { CallExpressionFunctionNode } from '../../../custom-nodes/control-flow-flattening-nodes/CallExpressionFunctionNode';
 import { ControlFlowStorageNode } from '../../../custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ControlFlowStorageNode';
-import { ConsoleOutputDisableExpressionNode } from '../../../custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode';
-import { CustomNodeFormatter } from '../../../custom-nodes/CustomNodeFormatter';
-import { DebugProtectionFunctionCallNode } from '../../../custom-nodes/debug-protection-nodes/DebugProtectionFunctionCallNode';
-import { DebugProtectionFunctionIntervalNode } from '../../../custom-nodes/debug-protection-nodes/DebugProtectionFunctionIntervalNode';
-import { DebugProtectionFunctionNode } from '../../../custom-nodes/debug-protection-nodes/DebugProtectionFunctionNode';
-import { DomainLockNode } from '../../../custom-nodes/domain-lock-nodes/DomainLockNode';
 import { ExpressionWithOperatorControlFlowStorageCallNode } from '../../../custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ExpressionWithOperatorControlFlowStorageCallNode';
 import { LogicalExpressionFunctionNode } from '../../../custom-nodes/control-flow-flattening-nodes/LogicalExpressionFunctionNode';
-import { NodeCallsControllerFunctionNode } from '../../../custom-nodes/node-calls-controller-nodes/NodeCallsControllerFunctionNode';
-import { SelfDefendingUnicodeNode } from '../../../custom-nodes/self-defending-nodes/SelfDefendingUnicodeNode';
-import { StringArrayCallsWrapper } from '../../../custom-nodes/string-array-nodes/StringArrayCallsWrapper';
-import { StringArrayNode } from '../../../custom-nodes/string-array-nodes/StringArrayNode';
-import { StringArrayRotateFunctionNode } from '../../../custom-nodes/string-array-nodes/StringArrayRotateFunctionNode';
 import { StringLiteralControlFlowStorageCallNode } from '../../../custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/StringLiteralControlFlowStorageCallNode';
 import { StringLiteralNode } from '../../../custom-nodes/control-flow-flattening-nodes/StringLiteralNode';
 
 export const customNodesModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
-    // custom nodes
-    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
-        .to(ConsoleOutputDisableExpressionNode)
-        .whenTargetNamed(CustomNode.ConsoleOutputDisableExpressionNode);
-
-    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
-        .to(DebugProtectionFunctionCallNode)
-        .whenTargetNamed(CustomNode.DebugProtectionFunctionCallNode);
-
-    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
-        .to(DebugProtectionFunctionIntervalNode)
-        .whenTargetNamed(CustomNode.DebugProtectionFunctionIntervalNode);
-
-    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
-        .to(DebugProtectionFunctionNode)
-        .whenTargetNamed(CustomNode.DebugProtectionFunctionNode);
-
-    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
-        .to(DomainLockNode)
-        .whenTargetNamed(CustomNode.DomainLockNode);
-
-    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
-        .to(NodeCallsControllerFunctionNode)
-        .whenTargetNamed(CustomNode.NodeCallsControllerFunctionNode);
-
-    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
-        .to(SelfDefendingUnicodeNode)
-        .whenTargetNamed(CustomNode.SelfDefendingUnicodeNode);
-
-    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
-        .to(StringArrayCallsWrapper)
-        .whenTargetNamed(CustomNode.StringArrayCallsWrapper);
-
-    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
-        .to(StringArrayNode)
-        .whenTargetNamed(CustomNode.StringArrayNode);
-
-    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
-        .to(StringArrayRotateFunctionNode)
-        .whenTargetNamed(CustomNode.StringArrayRotateFunctionNode);
-
     // control flow custom nodes
     bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
         .toConstructor(BinaryExpressionFunctionNode)
@@ -130,39 +68,13 @@ export const customNodesModule: interfaces.ContainerModule = new ContainerModule
         .toConstructor(ObjectExpressionVariableDeclarationHostNode)
         .whenTargetNamed(ObjectExpressionKeysTransformerCustomNode.ObjectExpressionVariableDeclarationHostNode);
 
-    // node groups
-    bind<ICustomNodeGroup>(ServiceIdentifiers.ICustomNodeGroup)
-        .to(ConsoleOutputCustomNodeGroup)
-        .whenTargetNamed(CustomNodeGroup.ConsoleOutputCustomNodeGroup);
-
-    bind<ICustomNodeGroup>(ServiceIdentifiers.ICustomNodeGroup)
-        .to(DebugProtectionCustomNodeGroup)
-        .whenTargetNamed(CustomNodeGroup.DebugProtectionCustomNodeGroup);
-
-    bind<ICustomNodeGroup>(ServiceIdentifiers.ICustomNodeGroup)
-        .to(DomainLockCustomNodeGroup)
-        .whenTargetNamed(CustomNodeGroup.DomainLockCustomNodeGroup);
-
-    bind<ICustomNodeGroup>(ServiceIdentifiers.ICustomNodeGroup)
-        .to(SelfDefendingCustomNodeGroup)
-        .whenTargetNamed(CustomNodeGroup.SelfDefendingCustomNodeGroup);
-
-    bind<ICustomNodeGroup>(ServiceIdentifiers.ICustomNodeGroup)
-        .to(StringArrayCustomNodeGroup)
-        .whenTargetNamed(CustomNodeGroup.StringArrayCustomNodeGroup);
-
-    // customNode factory
-    bind<ICustomNode>(ServiceIdentifiers.Factory__ICustomNode)
-        .toFactory<ICustomNode>(InversifyContainerFacade
-            .getFactory<CustomNode, ICustomNode>(ServiceIdentifiers.ICustomNode));
-
     // control flow customNode constructor factory
     bind<ICustomNode>(ServiceIdentifiers.Factory__IControlFlowCustomNode)
         .toFactory<ICustomNode>(InversifyContainerFacade
             .getConstructorFactory<ControlFlowCustomNode, ICustomNode>(
                 ServiceIdentifiers.Newable__ICustomNode,
                 ServiceIdentifiers.Factory__IIdentifierNamesGenerator,
-                ServiceIdentifiers.ICustomNodeFormatter,
+                ServiceIdentifiers.ICustomCodeHelperFormatter,
                 ServiceIdentifiers.IRandomGenerator,
                 ServiceIdentifiers.IOptions,
                 ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer
@@ -174,7 +86,7 @@ export const customNodesModule: interfaces.ContainerModule = new ContainerModule
             .getConstructorFactory<DeadCodeInjectionCustomNode, ICustomNode>(
                 ServiceIdentifiers.Newable__ICustomNode,
                 ServiceIdentifiers.Factory__IIdentifierNamesGenerator,
-                ServiceIdentifiers.ICustomNodeFormatter,
+                ServiceIdentifiers.ICustomCodeHelperFormatter,
                 ServiceIdentifiers.IRandomGenerator,
                 ServiceIdentifiers.IOptions
             ));
@@ -185,19 +97,9 @@ export const customNodesModule: interfaces.ContainerModule = new ContainerModule
             .getConstructorFactory<ObjectExpressionKeysTransformerCustomNode, ICustomNode>(
                 ServiceIdentifiers.Newable__ICustomNode,
                 ServiceIdentifiers.Factory__IIdentifierNamesGenerator,
-                ServiceIdentifiers.ICustomNodeFormatter,
+                ServiceIdentifiers.ICustomCodeHelperFormatter,
                 ServiceIdentifiers.IRandomGenerator,
                 ServiceIdentifiers.IOptions,
                 ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer
             ));
-
-    // customNodeGroup factory
-    bind<ICustomNodeGroup>(ServiceIdentifiers.Factory__ICustomNodeGroup)
-        .toFactory<ICustomNodeGroup>(InversifyContainerFacade
-            .getFactory<CustomNodeGroup, ICustomNodeGroup>(ServiceIdentifiers.ICustomNodeGroup));
-
-    // custom node formatter
-    bind<ICustomNodeFormatter>(ServiceIdentifiers.ICustomNodeFormatter)
-        .to(CustomNodeFormatter)
-        .inSingletonScope();
 });

+ 3 - 3
src/container/modules/node-transformers/PreparingTransformersModule.ts

@@ -11,7 +11,7 @@ import { ObfuscatingGuard } from '../../../enums/node-transformers/preparing-tra
 import { BlackListObfuscatingGuard } from '../../../node-transformers/preparing-transformers/obfuscating-guards/BlackListObfuscatingGuard';
 import { CommentsTransformer } from '../../../node-transformers/preparing-transformers/CommentsTransformer';
 import { ConditionalCommentObfuscatingGuard } from '../../../node-transformers/preparing-transformers/obfuscating-guards/ConditionalCommentObfuscatingGuard';
-import { CustomNodesTransformer } from '../../../node-transformers/preparing-transformers/CustomNodesTransformer';
+import { CustomCodeHelpersTransformer } from '../../../node-transformers/preparing-transformers/CustomCodeHelpersTransformer';
 import { EvalCallExpressionTransformer } from '../../../node-transformers/preparing-transformers/EvalCallExpressionTransformer';
 import { MetadataTransformer } from '../../../node-transformers/preparing-transformers/MetadataTransformer';
 import { ObfuscatingGuardsTransformer } from '../../../node-transformers/preparing-transformers/ObfuscatingGuardsTransformer';
@@ -26,8 +26,8 @@ export const preparingTransformersModule: interfaces.ContainerModule = new Conta
         .whenTargetNamed(NodeTransformer.CommentsTransformer);
 
     bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
-        .to(CustomNodesTransformer)
-        .whenTargetNamed(NodeTransformer.CustomNodesTransformer);
+        .to(CustomCodeHelpersTransformer)
+        .whenTargetNamed(NodeTransformer.CustomCodeHelpersTransformer);
 
     bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
         .to(EvalCallExpressionTransformer)

+ 13 - 0
src/container/modules/node/NodeModule.ts

@@ -0,0 +1,13 @@
+import { ContainerModule, interfaces } from 'inversify';
+import { ServiceIdentifiers } from '../../ServiceIdentifiers';
+
+import { IScopeIdentifiersTraverser } from '../../../interfaces/node/IScopeIdentifiersTraverser';
+
+import { ScopeIdentifiersTraverser } from '../../../node/ScopeIdentifiersTraverser';
+
+export const nodeModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
+    // scope identifiers traverser
+    bind<IScopeIdentifiersTraverser>(ServiceIdentifiers.IScopeIdentifiersTraverser)
+        .to(ScopeIdentifiersTraverser)
+        .inSingletonScope();
+});

+ 5 - 5
src/container/modules/storages/StoragesModule.ts

@@ -2,20 +2,20 @@ import { ContainerModule, interfaces } from 'inversify';
 import { ServiceIdentifiers } from '../../ServiceIdentifiers';
 
 import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
-import { TCustomNodeGroupStorage } from '../../../types/storages/TCustomNodeGroupStorage';
+import { TCustomCodeHelperGroupStorage } from '../../../types/storages/TCustomCodeHelperGroupStorage';
 
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IStringArrayStorage } from '../../../interfaces/storages/string-array-storage/IStringArrayStorage';
 
-import { ControlFlowStorage } from '../../../storages/control-flow/ControlFlowStorage';
-import { CustomNodeGroupStorage } from '../../../storages/custom-node-group/CustomNodeGroupStorage';
+import { ControlFlowStorage } from '../../../storages/custom-nodes/ControlFlowStorage';
+import { CustomCodeHelperGroupStorage } from '../../../storages/custom-code-helpers/CustomCodeHelperGroupStorage';
 import { StringArrayStorage } from '../../../storages/string-array/StringArrayStorage';
 
 export const storagesModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
     // storages
-    bind<TCustomNodeGroupStorage>(ServiceIdentifiers.TCustomNodeGroupStorage)
-        .to(CustomNodeGroupStorage)
+    bind<TCustomCodeHelperGroupStorage>(ServiceIdentifiers.TCustomNodeGroupStorage)
+        .to(CustomCodeHelperGroupStorage)
         .inSingletonScope();
 
     bind<IStringArrayStorage>(ServiceIdentifiers.IStringArrayStorage)

+ 121 - 0
src/custom-code-helpers/AbstractCustomCodeHelper.ts

@@ -0,0 +1,121 @@
+import { inject, injectable } from 'inversify';
+import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
+
+import { TIdentifierNamesGeneratorFactory } from '../types/container/generators/TIdentifierNamesGeneratorFactory';
+import { TStatement } from '../types/node/TStatement';
+
+import { ICustomCodeHelper } from '../interfaces/custom-code-helpers/ICustomCodeHelper';
+import { ICustomCodeHelperFormatter } from '../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
+import { ICustomCodeHelperObfuscator } from '../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
+import { IIdentifierNamesGenerator } from '../interfaces/generators/identifier-names-generators/IIdentifierNamesGenerator';
+import { IOptions } from '../interfaces/options/IOptions';
+import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
+
+import { GlobalVariableTemplate1 } from './common/templates/GlobalVariableTemplate1';
+import { GlobalVariableTemplate2 } from './common/templates/GlobalVariableTemplate2';
+
+@injectable()
+export abstract class AbstractCustomCodeHelper <
+    TInitialData extends any[] = any[]
+> implements ICustomCodeHelper <TInitialData> {
+    /**
+     * @type {string[]}
+     */
+    private static readonly globalVariableTemplateFunctions: string[] = [
+        GlobalVariableTemplate1(),
+        GlobalVariableTemplate2()
+    ];
+
+    /**
+     * @type {TStatement[] | null}
+     */
+    protected cachedNode: TStatement[] | null = null;
+
+    /**
+     * @type {ICustomCodeHelperFormatter}
+     */
+    protected readonly customCodeHelperFormatter: ICustomCodeHelperFormatter;
+
+    /**
+     * @type {ICustomCodeHelperObfuscator}
+     */
+    protected readonly customCodeHelperObfuscator: ICustomCodeHelperObfuscator;
+
+    /**
+     * @type {IIdentifierNamesGenerator}
+     */
+    protected readonly identifierNamesGenerator: IIdentifierNamesGenerator;
+
+    /**
+     * @type {IOptions}
+     */
+    protected readonly options: IOptions;
+
+    /**
+     * @type {IRandomGenerator}
+     */
+    protected readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
+     * @param {ICustomCodeHelperObfuscator} customCodeHelperObfuscator
+     * @param {IRandomGenerator} randomGenerator
+     * @param {IOptions} options
+     */
+    protected constructor (
+        @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
+            identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperObfuscator) customCodeHelperObfuscator: ICustomCodeHelperObfuscator,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        this.identifierNamesGenerator = identifierNamesGeneratorFactory(options);
+        this.customCodeHelperFormatter = customCodeHelperFormatter;
+        this.customCodeHelperObfuscator = customCodeHelperObfuscator;
+        this.randomGenerator = randomGenerator;
+        this.options = options;
+    }
+
+    /**
+     * @returns {TStatement[]}
+     */
+    public getNode (): TStatement[] {
+        if (!this.cachedNode) {
+            const codeHelperTemplate: string = this.getCodeHelperTemplate();
+
+            this.cachedNode = this.customCodeHelperFormatter.formatStructure(
+                this.getNodeStructure(codeHelperTemplate)
+            );
+        }
+
+        return this.cachedNode;
+    }
+
+    /**
+     * @returns {string}
+     */
+    protected getGlobalVariableTemplate (): string {
+        return this.randomGenerator
+            .getRandomGenerator()
+            .pickone(AbstractCustomCodeHelper.globalVariableTemplateFunctions);
+    }
+
+    /**
+     * @returns {string}
+     */
+    protected getCodeHelperTemplate (): string {
+        return '';
+    }
+
+    /**
+     * @param {TInitialData} args
+     */
+    public abstract initialize (...args: TInitialData): void;
+
+    /**
+     * @returns {TStatement[]}
+     */
+    protected abstract getNodeStructure (codeHelperTemplate: string): TStatement[];
+}

+ 17 - 16
src/custom-nodes/AbstractCustomNodeGroup.ts → src/custom-code-helpers/AbstractCustomCodeHelperGroup.ts

@@ -4,18 +4,18 @@ import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
 import { TIdentifierNamesGeneratorFactory } from '../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TNodeWithStatements } from '../types/node/TNodeWithStatements';
 
-import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
-import { ICustomNodeGroup } from '../interfaces/custom-nodes/ICustomNodeGroup';
+import { ICallsGraphData } from '../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
+import { ICustomCodeHelper } from '../interfaces/custom-code-helpers/ICustomCodeHelper';
+import { ICustomCodeHelperGroup } from '../interfaces/custom-code-helpers/ICustomCodeHelperGroup';
 import { IIdentifierNamesGenerator } from '../interfaces/generators/identifier-names-generators/IIdentifierNamesGenerator';
 import { IOptions } from '../interfaces/options/IOptions';
 import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
-import { ICallsGraphData } from '../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
 
-import { CustomNode } from '../enums/custom-nodes/CustomNode';
+import { CustomCodeHelper } from '../enums/custom-code-helpers/CustomCodeHelper';
 import { ObfuscationEvent } from '../enums/event-emitters/ObfuscationEvent';
 
 @injectable()
-export abstract class AbstractCustomNodeGroup implements ICustomNodeGroup {
+export abstract class AbstractCustomCodeHelperGroup implements ICustomCodeHelperGroup {
     /**
      * @type {IIdentifierNamesGenerator}
      */
@@ -37,9 +37,9 @@ export abstract class AbstractCustomNodeGroup implements ICustomNodeGroup {
     protected abstract readonly appendEvent: ObfuscationEvent;
 
     /**
-     * @type {Map<CustomNode, ICustomNode>}
+     * @type {Map<CustomCodeHelper, ICustomCodeHelper>}
      */
-    protected abstract customNodes: Map <CustomNode, ICustomNode>;
+    protected abstract customCodeHelpers: Map <CustomCodeHelper, ICustomCodeHelper>;
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
@@ -65,30 +65,31 @@ export abstract class AbstractCustomNodeGroup implements ICustomNodeGroup {
     }
 
     /**
-     * @returns {Map<CustomNode, ICustomNode>}
+     * @returns {Map<CustomCodeHelper, ICustomCodeHelper>}
      */
-    public getCustomNodes (): Map <CustomNode, ICustomNode> {
-        return this.customNodes;
+    public getCustomCodeHelpers (): Map <CustomCodeHelper, ICustomCodeHelper> {
+        return this.customCodeHelpers;
     }
 
     /**
-     * @param {CustomNode} customNodeName
+     * @param {CustomCodeHelper} customCodeHelperName
      * @param {callback} callback
      */
-    protected appendCustomNodeIfExist (customNodeName: CustomNode, callback: (customNode: ICustomNode) => void): void {
-        const customNode: ICustomNode | undefined = this.customNodes.get(customNodeName);
+    protected appendCustomNodeIfExist (customCodeHelperName: CustomCodeHelper, callback: (customCodeHelper: ICustomCodeHelper) => void): void {
+        const customCodeHelper: ICustomCodeHelper | undefined = this.customCodeHelpers.get(customCodeHelperName);
 
-        if (!customNode) {
+        if (!customCodeHelper) {
             return;
         }
 
-        callback(customNode);
+        callback(customCodeHelper);
     }
 
     /**
      * @param {number} callsGraphLength
      * @returns {number}
      */
+
     protected getRandomCallsGraphIndex (callsGraphLength: number): number {
         return this.randomGenerator.getRandomInteger(0, Math.max(0, Math.round(callsGraphLength - 1)));
     }
@@ -97,7 +98,7 @@ export abstract class AbstractCustomNodeGroup implements ICustomNodeGroup {
      * @param {TNodeWithStatements} nodeWithStatements
      * @param {ICallsGraphData[]} callsGraphData
      */
-    public abstract appendCustomNodes (nodeWithStatements: TNodeWithStatements, callsGraphData: ICallsGraphData[]): void;
+    public abstract appendNodes (nodeWithStatements: TNodeWithStatements, callsGraphData: ICallsGraphData[]): void;
 
     public abstract initialize (): void;
 }

+ 2 - 2
src/custom-nodes/CustomNodeFormatter.ts → src/custom-code-helpers/CustomCodeHelperFormatter.ts

@@ -8,13 +8,13 @@ import format from 'string-template';
 import { TObject } from '../types/TObject';
 import { TStatement } from '../types/node/TStatement';
 
-import { ICustomNodeFormatter } from '../interfaces/custom-nodes/ICustomNodeFormatter';
+import { ICustomCodeHelperFormatter } from '../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
 import { IPrevailingKindOfVariablesAnalyzer } from '../interfaces/analyzers/calls-graph-analyzer/IPrevailingKindOfVariablesAnalyzer';
 
 import { NodeGuards } from '../node/NodeGuards';
 
 @injectable()
-export class CustomNodeFormatter implements ICustomNodeFormatter {
+export class CustomCodeHelperFormatter implements ICustomCodeHelperFormatter {
     /**
      * @type {ESTree.VariableDeclaration['kind']}
      */

+ 55 - 0
src/custom-code-helpers/CustomCodeHelperObfuscator.ts

@@ -0,0 +1,55 @@
+import { inject, injectable } from 'inversify';
+import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
+
+import { TInputOptions } from '../types/options/TInputOptions';
+
+import { ICustomCodeHelperObfuscator } from '../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
+import { IOptions } from '../interfaces/options/IOptions';
+import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
+
+import { NO_ADDITIONAL_NODES_PRESET } from '../options/presets/NoCustomNodes';
+
+import { JavaScriptObfuscator } from '../JavaScriptObfuscatorFacade';
+
+@injectable()
+export class CustomCodeHelperObfuscator implements ICustomCodeHelperObfuscator {
+    /**
+     * @type {IOptions}
+     */
+    private readonly options: IOptions;
+
+    /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param {IRandomGenerator} randomGenerator
+     * @param {IOptions} options
+     */
+    public constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        this.randomGenerator = randomGenerator;
+        this.options = options;
+    }
+
+    /**
+     * @param {string} template
+     * @param {TInputOptions} additionalOptions
+     * @returns {string}
+     */
+    public obfuscateTemplate (template: string, additionalOptions: TInputOptions = {}): string {
+        return JavaScriptObfuscator.obfuscate(
+            template,
+            {
+                ...NO_ADDITIONAL_NODES_PRESET,
+                identifierNamesGenerator: this.options.identifierNamesGenerator,
+                identifiersDictionary: this.options.identifiersDictionary,
+                seed: this.randomGenerator.getRawSeed(),
+                ...additionalOptions
+            }
+        ).getObfuscatedCode();
+    }
+}

+ 27 - 27
src/custom-nodes/node-calls-controller-nodes/NodeCallsControllerFunctionNode.ts → src/custom-code-helpers/calls-controller/CallsControllerFunctionCodeHelper.ts

@@ -4,6 +4,8 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICustomCodeHelperObfuscator } from '../../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
@@ -11,17 +13,13 @@ import { ObfuscationEvent } from '../../enums/event-emitters/ObfuscationEvent';
 
 import { initializable } from '../../decorators/Initializable';
 
-import { SingleNodeCallControllerTemplate } from '../../templates/SingleNodeCallControllerTemplate';
+import { SingleCallControllerTemplate } from '../common/templates/SingleCallControllerTemplate';
 
-import { NO_ADDITIONAL_NODES_PRESET } from '../../options/presets/NoCustomNodes';
-
-import { AbstractCustomNode } from '../AbstractCustomNode';
-import { JavaScriptObfuscator } from '../../JavaScriptObfuscatorFacade';
+import { AbstractCustomCodeHelper } from '../AbstractCustomCodeHelper';
 import { NodeUtils } from '../../node/NodeUtils';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 @injectable()
-export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
+export class CallsControllerFunctionCodeHelper extends AbstractCustomCodeHelper {
     /**
      * @type {string}
      */
@@ -36,18 +34,26 @@ export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
+     * @param {ICustomCodeHelperObfuscator} customCodeHelperObfuscator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperObfuscator) customCodeHelperObfuscator: ICustomCodeHelperObfuscator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            customCodeHelperObfuscator,
+            randomGenerator,
+            options
+        );
     }
 
     /**
@@ -60,33 +66,27 @@ export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
     }
 
     /**
-     * @param {string} nodeTemplate
+     * @param {string} codeHelperTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
-        return NodeUtils.convertCodeToStructure(nodeTemplate);
+    protected getNodeStructure (codeHelperTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(codeHelperTemplate);
     }
 
     /**
      * @returns {string}
      */
-    protected getNodeTemplate (): string {
+    protected getCodeHelperTemplate (): string {
         if (this.appendEvent === ObfuscationEvent.AfterObfuscation) {
-            return JavaScriptObfuscator.obfuscate(
-                this.customNodeFormatter.formatTemplate(SingleNodeCallControllerTemplate(), {
-                    singleNodeCallControllerFunctionName: this.callsControllerFunctionName
-                }),
-                {
-                    ...NO_ADDITIONAL_NODES_PRESET,
-                    identifierNamesGenerator: this.options.identifierNamesGenerator,
-                    identifiersDictionary: this.options.identifiersDictionary,
-                    seed: this.options.seed
-                }
-            ).getObfuscatedCode();
+            return this.customCodeHelperObfuscator.obfuscateTemplate(
+                this.customCodeHelperFormatter.formatTemplate(SingleCallControllerTemplate(), {
+                    callControllerFunctionName: this.callsControllerFunctionName
+                })
+            );
         }
 
-        return this.customNodeFormatter.formatTemplate(SingleNodeCallControllerTemplate(), {
-            singleNodeCallControllerFunctionName: this.callsControllerFunctionName
+        return this.customCodeHelperFormatter.formatTemplate(SingleCallControllerTemplate(), {
+            callControllerFunctionName: this.callsControllerFunctionName
         });
     }
 }

+ 0 - 0
src/templates/GlobalVariableNoEvalTemplate.ts → src/custom-code-helpers/common/templates/GlobalVariableNoEvalTemplate.ts


+ 0 - 0
src/templates/GlobalVariableTemplate1.ts → src/custom-code-helpers/common/templates/GlobalVariableTemplate1.ts


+ 0 - 0
src/templates/GlobalVariableTemplate2.ts → src/custom-code-helpers/common/templates/GlobalVariableTemplate2.ts


+ 2 - 2
src/templates/SingleNodeCallControllerTemplate.ts → src/custom-code-helpers/common/templates/SingleCallControllerTemplate.ts

@@ -1,9 +1,9 @@
 /**
  * @returns {string}
  */
-export function SingleNodeCallControllerTemplate (): string {
+export function SingleCallControllerTemplate (): string {
     return `
-        const {singleNodeCallControllerFunctionName} = (function(){
+        const {callControllerFunctionName} = (function(){
             let firstCall = true;
             
             return function (context, fn){

+ 91 - 0
src/custom-code-helpers/console-output/ConsoleOutputDisableCodeHelper.ts

@@ -0,0 +1,91 @@
+import { inject, injectable, } from 'inversify';
+import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
+
+import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
+import { TStatement } from '../../types/node/TStatement';
+
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
+import { ICustomCodeHelperObfuscator } from '../../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
+import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
+
+import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
+
+import { ConsoleOutputDisableExpressionTemplate } from './templates/ConsoleOutputDisableExpressionTemplate';
+import { GlobalVariableNoEvalTemplate } from '../common/templates/GlobalVariableNoEvalTemplate';
+
+import { initializable } from '../../decorators/Initializable';
+
+import { AbstractCustomCodeHelper } from '../AbstractCustomCodeHelper';
+import { NodeUtils } from '../../node/NodeUtils';
+
+@injectable()
+export class ConsoleOutputDisableCodeHelper extends AbstractCustomCodeHelper {
+    /**
+     * @type {string}
+     */
+    @initializable()
+    private callsControllerFunctionName!: string;
+
+    /**
+     * @type {string}
+     */
+    @initializable()
+    private consoleOutputDisableFunctionName!: string;
+
+    /**
+     * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
+     * @param {ICustomCodeHelperObfuscator} customCodeHelperObfuscator
+     * @param {IRandomGenerator} randomGenerator
+     * @param {IOptions} options
+     */
+    public constructor (
+        @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
+            identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperObfuscator) customCodeHelperObfuscator: ICustomCodeHelperObfuscator,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            customCodeHelperObfuscator,
+            randomGenerator,
+            options
+        );
+    }
+
+    /**
+     * @param {string} callsControllerFunctionName
+     * @param {StaticRange} consoleOutputDisableFunctionName
+     */
+    public initialize (callsControllerFunctionName: string, consoleOutputDisableFunctionName: string): void {
+        this.callsControllerFunctionName = callsControllerFunctionName;
+        this.consoleOutputDisableFunctionName = consoleOutputDisableFunctionName;
+    }
+
+    /**
+     * @param {string} codeHelperTemplate
+     * @returns {TStatement[]}
+     */
+    protected getNodeStructure (codeHelperTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(codeHelperTemplate);
+    }
+
+    /**
+     * @returns {string}
+     */
+    protected getCodeHelperTemplate (): string {
+        const globalVariableTemplate: string = this.options.target !== ObfuscationTarget.BrowserNoEval
+            ? this.getGlobalVariableTemplate()
+            : GlobalVariableNoEvalTemplate();
+
+        return this.customCodeHelperFormatter.formatTemplate(ConsoleOutputDisableExpressionTemplate(), {
+            callControllerFunctionName: this.callsControllerFunctionName,
+            consoleLogDisableFunctionName: this.consoleOutputDisableFunctionName,
+            globalVariableTemplate
+        });
+    }
+}

+ 129 - 0
src/custom-code-helpers/console-output/group/ConsoleOutputCodeHelperGroup.ts

@@ -0,0 +1,129 @@
+import { inject, injectable, } from 'inversify';
+import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
+
+import { TCustomCodeHelperFactory } from '../../../types/container/custom-code-helpers/TCustomCodeHelperFactory';
+import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
+import { TInitialData } from '../../../types/TInitialData';
+import { TNodeWithLexicalScope } from '../../../types/node/TNodeWithLexicalScope';
+import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
+
+import { ICustomCodeHelper } from '../../../interfaces/custom-code-helpers/ICustomCodeHelper';
+import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
+import { ICallsGraphData } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
+
+import { initializable } from '../../../decorators/Initializable';
+
+import { CustomCodeHelper } from '../../../enums/custom-code-helpers/CustomCodeHelper';
+import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent';
+
+import { AbstractCustomCodeHelperGroup } from '../../AbstractCustomCodeHelperGroup';
+import { CallsControllerFunctionCodeHelper } from '../../calls-controller/CallsControllerFunctionCodeHelper';
+import { ConsoleOutputDisableCodeHelper } from '../ConsoleOutputDisableCodeHelper';
+import { NodeAppender } from '../../../node/NodeAppender';
+import { NodeLexicalScopeUtils } from '../../../node/NodeLexicalScopeUtils';
+import { NodeGuards } from '../../../node/NodeGuards';
+
+@injectable()
+export class ConsoleOutputCodeHelperGroup extends AbstractCustomCodeHelperGroup {
+    /**
+     * @type {ObfuscationEvent}
+     */
+    protected readonly appendEvent: ObfuscationEvent = ObfuscationEvent.BeforeObfuscation;
+
+    /**
+     * @type {Map<CustomCodeHelper, ICustomCodeHelper>}
+     */
+    @initializable()
+    protected customCodeHelpers!: Map <CustomCodeHelper, ICustomCodeHelper>;
+
+    /**
+     * @type {TCustomCodeHelperFactory}
+     */
+    private readonly customCodeHelperFactory: TCustomCodeHelperFactory;
+
+    /**
+     * @param {TCustomCodeHelperFactory} customCodeHelperFactory
+     * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {IRandomGenerator} randomGenerator
+     * @param {IOptions} options
+     */
+    public constructor (
+        @inject(ServiceIdentifiers.Factory__ICustomCodeHelper) customCodeHelperFactory: TCustomCodeHelperFactory,
+        @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
+            identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(identifierNamesGeneratorFactory, randomGenerator, options);
+
+        this.customCodeHelperFactory = customCodeHelperFactory;
+    }
+
+    /**
+     * @param {TNodeWithStatements} nodeWithStatements
+     * @param {ICallsGraphData[]} callsGraphData
+     */
+    public appendNodes (nodeWithStatements: TNodeWithStatements, callsGraphData: ICallsGraphData[]): void {
+        if (!this.options.disableConsoleOutput) {
+            return;
+        }
+
+        const randomCallsGraphIndex: number = this.getRandomCallsGraphIndex(callsGraphData.length);
+
+        const consoleOutputDisableHostNode: TNodeWithStatements = callsGraphData.length
+            ? NodeAppender.getOptimalBlockScope(callsGraphData, randomCallsGraphIndex)
+            : nodeWithStatements;
+        const callsControllerHostNode: TNodeWithStatements = callsGraphData.length
+            ? NodeAppender.getOptimalBlockScope(callsGraphData, randomCallsGraphIndex, 1)
+            : nodeWithStatements;
+
+        const consoleOutputDisableLexicalScopeNode: TNodeWithLexicalScope | null = NodeLexicalScopeUtils
+            .getLexicalScope(consoleOutputDisableHostNode) ?? null;
+
+        const consoleOutputDisableFunctionName: string = consoleOutputDisableLexicalScopeNode
+            && NodeGuards.isProgramNode(consoleOutputDisableLexicalScopeNode)
+            ? this.identifierNamesGenerator.generate(consoleOutputDisableLexicalScopeNode)
+            : this.randomGenerator.getRandomString(5);
+        const callsControllerFunctionName: string = consoleOutputDisableLexicalScopeNode
+            && NodeGuards.isProgramNode(consoleOutputDisableLexicalScopeNode)
+            ? this.identifierNamesGenerator.generate(consoleOutputDisableLexicalScopeNode)
+            : this.randomGenerator.getRandomString(5);
+
+        // consoleOutputDisableExpression helper nodes append
+        this.appendCustomNodeIfExist(
+            CustomCodeHelper.ConsoleOutputDisable,
+            (customCodeHelper: ICustomCodeHelper<TInitialData<ConsoleOutputDisableCodeHelper>>) => {
+                customCodeHelper.initialize(callsControllerFunctionName, consoleOutputDisableFunctionName);
+
+                NodeAppender.prepend(consoleOutputDisableHostNode, customCodeHelper.getNode());
+            }
+        );
+
+        // nodeCallsControllerFunction helper nodes append
+        this.appendCustomNodeIfExist(
+            CustomCodeHelper.CallsControllerFunction,
+            (customCodeHelper: ICustomCodeHelper<TInitialData<CallsControllerFunctionCodeHelper>>) => {
+                customCodeHelper.initialize(this.appendEvent, callsControllerFunctionName);
+
+                NodeAppender.prepend(callsControllerHostNode, customCodeHelper.getNode());
+            }
+        );
+    }
+
+    public initialize (): void {
+        this.customCodeHelpers = new Map <CustomCodeHelper, ICustomCodeHelper>();
+
+        if (!this.options.disableConsoleOutput) {
+            return;
+        }
+
+        const consoleOutputDisableExpressionCodeHelper: ICustomCodeHelper<TInitialData<ConsoleOutputDisableCodeHelper>> =
+            this.customCodeHelperFactory(CustomCodeHelper.ConsoleOutputDisable);
+        const callsControllerFunctionCodeHelper: ICustomCodeHelper<TInitialData<CallsControllerFunctionCodeHelper>> =
+            this.customCodeHelperFactory(CustomCodeHelper.CallsControllerFunction);
+
+        this.customCodeHelpers.set(CustomCodeHelper.ConsoleOutputDisable, consoleOutputDisableExpressionCodeHelper);
+        this.customCodeHelpers.set(CustomCodeHelper.CallsControllerFunction, callsControllerFunctionCodeHelper);
+    }
+}

+ 1 - 1
src/templates/console-output-nodes/console-output-disable-expression-node/ConsoleOutputDisableExpressionTemplate.ts → src/custom-code-helpers/console-output/templates/ConsoleOutputDisableExpressionTemplate.ts

@@ -3,7 +3,7 @@
  */
 export function ConsoleOutputDisableExpressionTemplate (): string {
     return `
-        const {consoleLogDisableFunctionName} = {singleNodeCallControllerFunctionName}(this, function () {
+        const {consoleLogDisableFunctionName} = {callControllerFunctionName}(this, function () {
             const func = function () {};
             
             {globalVariableTemplate}

+ 22 - 13
src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionCallNode.ts → src/custom-code-helpers/debug-protection/DebugProtectionFunctionCallCodeHelper.ts

@@ -4,19 +4,20 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
+import { ICustomCodeHelperObfuscator } from '../../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { initializable } from '../../decorators/Initializable';
 
-import { DebugProtectionFunctionCallTemplate } from '../../templates/debug-protection-nodes/debug-protection-function-call-node/DebugProtectionFunctionCallTemplate';
+import { DebugProtectionFunctionCallTemplate } from './templates/debug-protection-function-call/DebugProtectionFunctionCallTemplate';
 
-import { AbstractCustomNode } from '../AbstractCustomNode';
+import { AbstractCustomCodeHelper } from '../AbstractCustomCodeHelper';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
-export class DebugProtectionFunctionCallNode extends AbstractCustomNode {
+export class DebugProtectionFunctionCallCodeHelper extends AbstractCustomCodeHelper {
     /**
      * @type {string}
      */
@@ -31,18 +32,26 @@ export class DebugProtectionFunctionCallNode extends AbstractCustomNode {
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
+     * @param {ICustomCodeHelperObfuscator} customCodeHelperObfuscator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperObfuscator) customCodeHelperObfuscator: ICustomCodeHelperObfuscator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            customCodeHelperObfuscator,
+            randomGenerator,
+            options
+        );
     }
 
     /**
@@ -55,20 +64,20 @@ export class DebugProtectionFunctionCallNode extends AbstractCustomNode {
     }
 
     /**
-     * @param {string} nodeTemplate
+     * @param {string} codeHelperTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
-        return NodeUtils.convertCodeToStructure(nodeTemplate);
+    protected getNodeStructure (codeHelperTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(codeHelperTemplate);
     }
 
     /**
      * @returns {string}
      */
-    protected getNodeTemplate (): string {
-        return this.customNodeFormatter.formatTemplate(DebugProtectionFunctionCallTemplate(), {
+    protected getCodeHelperTemplate (): string {
+        return this.customCodeHelperFormatter.formatTemplate(DebugProtectionFunctionCallTemplate(), {
             debugProtectionFunctionName: this.debugProtectionFunctionName,
-            singleNodeCallControllerFunctionName: this.callsControllerFunctionName
+            callControllerFunctionName: this.callsControllerFunctionName
         });
     }
 }

+ 23 - 14
src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionNode.ts → src/custom-code-helpers/debug-protection/DebugProtectionFunctionCodeHelper.ts

@@ -4,23 +4,24 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
+import { ICustomCodeHelperObfuscator } from '../../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 
 import { initializable } from '../../decorators/Initializable';
 
-import { DebuggerTemplate } from '../../templates/debug-protection-nodes/debug-protection-function-node/DebuggerTemplate';
-import { DebuggerTemplateNoEval } from '../../templates/debug-protection-nodes/debug-protection-function-node/DebuggerTemplateNoEval';
-import { DebugProtectionFunctionTemplate } from '../../templates/debug-protection-nodes/debug-protection-function-node/DebugProtectionFunctionTemplate';
+import { DebuggerTemplate } from './templates/debug-protection-function/DebuggerTemplate';
+import { DebuggerTemplateNoEval } from './templates/debug-protection-function/DebuggerTemplateNoEval';
+import { DebugProtectionFunctionTemplate } from './templates/debug-protection-function/DebugProtectionFunctionTemplate';
 
-import { AbstractCustomNode } from '../AbstractCustomNode';
+import { AbstractCustomCodeHelper } from '../AbstractCustomCodeHelper';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
-export class DebugProtectionFunctionNode extends AbstractCustomNode {
+export class DebugProtectionFunctionCodeHelper extends AbstractCustomCodeHelper {
     /**
      * @type {string}
      */
@@ -29,18 +30,26 @@ export class DebugProtectionFunctionNode extends AbstractCustomNode {
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
+     * @param {ICustomCodeHelperObfuscator} customCodeHelperObfuscator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperObfuscator) customCodeHelperObfuscator: ICustomCodeHelperObfuscator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            customCodeHelperObfuscator,
+            randomGenerator,
+            options
+        );
     }
 
     /**
@@ -51,22 +60,22 @@ export class DebugProtectionFunctionNode extends AbstractCustomNode {
     }
 
     /**
-     * @param {string} nodeTemplate
+     * @param {string} codeHelperTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
-        return NodeUtils.convertCodeToStructure(nodeTemplate);
+    protected getNodeStructure (codeHelperTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(codeHelperTemplate);
     }
 
     /**
      * @returns {string}
      */
-    protected getNodeTemplate (): string {
+    protected getCodeHelperTemplate (): string {
         const debuggerTemplate: string = this.options.target !== ObfuscationTarget.BrowserNoEval
             ? DebuggerTemplate()
             : DebuggerTemplateNoEval();
 
-        return this.customNodeFormatter.formatTemplate(DebugProtectionFunctionTemplate(), {
+        return this.customCodeHelperFormatter.formatTemplate(DebugProtectionFunctionTemplate(), {
             debuggerTemplate,
             debugProtectionFunctionName: this.debugProtectionFunctionName
         });

+ 21 - 12
src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionIntervalNode.ts → src/custom-code-helpers/debug-protection/DebugProtectionFunctionIntervalCodeHelper.ts

@@ -4,19 +4,20 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
+import { ICustomCodeHelperObfuscator } from '../../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { initializable } from '../../decorators/Initializable';
 
-import { DebugProtectionFunctionIntervalTemplate } from '../../templates/debug-protection-nodes/debug-protection-function-interval-node/DebugProtectionFunctionIntervalTemplate';
+import { DebugProtectionFunctionIntervalTemplate } from './templates/debug-protection-function-interval/DebugProtectionFunctionIntervalTemplate';
 
-import { AbstractCustomNode } from '../AbstractCustomNode';
+import { AbstractCustomCodeHelper } from '../AbstractCustomCodeHelper';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
-export class DebugProtectionFunctionIntervalNode extends AbstractCustomNode {
+export class DebugProtectionFunctionIntervalCodeHelper extends AbstractCustomCodeHelper {
     /**
      * @type {string}
      */
@@ -25,18 +26,26 @@ export class DebugProtectionFunctionIntervalNode extends AbstractCustomNode {
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
+     * @param {ICustomCodeHelperObfuscator} customCodeHelperObfuscator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperObfuscator) customCodeHelperObfuscator: ICustomCodeHelperObfuscator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            customCodeHelperObfuscator,
+            randomGenerator,
+            options
+        );
     }
 
     /**
@@ -47,18 +56,18 @@ export class DebugProtectionFunctionIntervalNode extends AbstractCustomNode {
     }
 
     /**
-     * @param {string} nodeTemplate
+     * @param {string} codeHelperTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
-        return NodeUtils.convertCodeToStructure(nodeTemplate);
+    protected getNodeStructure (codeHelperTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(codeHelperTemplate);
     }
 
     /**
      * @returns {string}
      */
-    protected getNodeTemplate (): string {
-        return this.customNodeFormatter.formatTemplate(DebugProtectionFunctionIntervalTemplate(), {
+    protected getCodeHelperTemplate (): string {
+        return this.customCodeHelperFormatter.formatTemplate(DebugProtectionFunctionIntervalTemplate(), {
             debugProtectionFunctionName: this.debugProtectionFunctionName
         });
     }

+ 166 - 0
src/custom-code-helpers/debug-protection/group/DebugProtectionCodeHelperGroup.ts

@@ -0,0 +1,166 @@
+import { inject, injectable, } from 'inversify';
+import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
+
+import { TCustomCodeHelperFactory } from '../../../types/container/custom-code-helpers/TCustomCodeHelperFactory';
+import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
+import { TInitialData } from '../../../types/TInitialData';
+import { TNodeWithLexicalScope } from '../../../types/node/TNodeWithLexicalScope';
+import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
+
+import { ICustomCodeHelper } from '../../../interfaces/custom-code-helpers/ICustomCodeHelper';
+import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
+import { ICallsGraphData } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
+
+import { initializable } from '../../../decorators/Initializable';
+
+import { CustomCodeHelper } from '../../../enums/custom-code-helpers/CustomCodeHelper';
+import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent';
+
+import { AbstractCustomCodeHelperGroup } from '../../AbstractCustomCodeHelperGroup';
+import { CallsControllerFunctionCodeHelper } from '../../calls-controller/CallsControllerFunctionCodeHelper';
+import { DebugProtectionFunctionCodeHelper } from '../DebugProtectionFunctionCodeHelper';
+import { DebugProtectionFunctionCallCodeHelper } from '../DebugProtectionFunctionCallCodeHelper';
+import { DebugProtectionFunctionIntervalCodeHelper } from '../DebugProtectionFunctionIntervalCodeHelper';
+import { NodeAppender } from '../../../node/NodeAppender';
+import { NodeGuards } from '../../../node/NodeGuards';
+import { NodeLexicalScopeUtils } from '../../../node/NodeLexicalScopeUtils';
+
+@injectable()
+export class DebugProtectionCodeHelperGroup extends AbstractCustomCodeHelperGroup {
+    /**
+     * @type {ObfuscationEvent}
+     */
+    protected readonly appendEvent: ObfuscationEvent = ObfuscationEvent.BeforeObfuscation;
+
+    /**
+     * @type {Map<CustomCodeHelper, ICustomCodeHelper>}
+     */
+    @initializable()
+    protected customCodeHelpers!: Map <CustomCodeHelper, ICustomCodeHelper>;
+
+    /**
+     * @type {TCustomCodeHelperFactory}
+     */
+    private readonly customCodeHelperFactory: TCustomCodeHelperFactory;
+
+    /**
+     * @param {TCustomCodeHelperFactory} customCodeHelperFactory
+     * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {IRandomGenerator} randomGenerator
+     * @param {IOptions} options
+     */
+    public constructor (
+        @inject(ServiceIdentifiers.Factory__ICustomCodeHelper) customCodeHelperFactory: TCustomCodeHelperFactory,
+        @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
+            identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(identifierNamesGeneratorFactory, randomGenerator, options);
+
+        this.customCodeHelperFactory = customCodeHelperFactory;
+    }
+
+    /**
+     * @param {TNodeWithStatements} nodeWithStatements
+     * @param {ICallsGraphData[]} callsGraphData
+     */
+    public appendNodes (nodeWithStatements: TNodeWithStatements, callsGraphData: ICallsGraphData[]): void {
+        if (!this.options.debugProtection) {
+            return;
+        }
+
+        const randomCallsGraphIndex: number = this.getRandomCallsGraphIndex(callsGraphData.length);
+
+        const debugProtectionFunctionCallHostNode: TNodeWithStatements = callsGraphData.length
+            ? NodeAppender.getOptimalBlockScope(callsGraphData, randomCallsGraphIndex)
+            : nodeWithStatements;
+        const callsControllerHostNode: TNodeWithStatements = callsGraphData.length
+            ? NodeAppender.getOptimalBlockScope(callsGraphData, randomCallsGraphIndex, 1)
+            : nodeWithStatements;
+
+        const debugProtectionFunctionCallScopeNode: TNodeWithLexicalScope | null = NodeLexicalScopeUtils
+            .getLexicalScope(debugProtectionFunctionCallHostNode) ?? null;
+
+        const debugProtectionFunctionName: string = debugProtectionFunctionCallScopeNode
+            && NodeGuards.isProgramNode(debugProtectionFunctionCallScopeNode)
+            ? this.identifierNamesGenerator.generate(debugProtectionFunctionCallScopeNode)
+            : this.randomGenerator.getRandomString(5);
+        const callsControllerFunctionName: string = debugProtectionFunctionCallScopeNode
+            && NodeGuards.isProgramNode(debugProtectionFunctionCallScopeNode)
+            ? this.identifierNamesGenerator.generate(debugProtectionFunctionCallScopeNode)
+            : this.randomGenerator.getRandomString(5);
+
+        // debugProtectionFunctionCall helper nodes append
+        this.appendCustomNodeIfExist(
+            CustomCodeHelper.DebugProtectionFunctionCall,
+            (customCodeHelper: ICustomCodeHelper<TInitialData<DebugProtectionFunctionCallCodeHelper>>) => {
+                customCodeHelper.initialize(debugProtectionFunctionName, callsControllerFunctionName);
+
+                NodeAppender.prepend(debugProtectionFunctionCallHostNode, customCodeHelper.getNode());
+            }
+        );
+
+        // nodeCallsControllerFunction helper nodes append
+        this.appendCustomNodeIfExist(
+            CustomCodeHelper.CallsControllerFunction,
+            (customCodeHelper: ICustomCodeHelper<TInitialData<CallsControllerFunctionCodeHelper>>) => {
+                customCodeHelper.initialize(this.appendEvent, callsControllerFunctionName);
+
+                NodeAppender.prepend(callsControllerHostNode, customCodeHelper.getNode());
+            }
+        );
+
+        // debugProtectionFunction helper nodes append
+        this.appendCustomNodeIfExist(
+            CustomCodeHelper.DebugProtectionFunction,
+                (customCodeHelper: ICustomCodeHelper<TInitialData<DebugProtectionFunctionCodeHelper>>) => {
+                customCodeHelper.initialize(debugProtectionFunctionName);
+
+                NodeAppender.append(nodeWithStatements, customCodeHelper.getNode());
+            }
+        );
+
+        // debugProtectionFunctionInterval helper nodes append
+        this.appendCustomNodeIfExist(
+            CustomCodeHelper.DebugProtectionFunctionInterval,
+            (customCodeHelper: ICustomCodeHelper<TInitialData<DebugProtectionFunctionIntervalCodeHelper>>) => {
+                const programBodyLength: number = NodeGuards.isSwitchCaseNode(nodeWithStatements)
+                    ? nodeWithStatements.consequent.length
+                    : nodeWithStatements.body.length;
+                const randomIndex: number = this.randomGenerator.getRandomInteger(0, programBodyLength);
+
+                customCodeHelper.initialize(debugProtectionFunctionName);
+
+                NodeAppender.insertAtIndex(nodeWithStatements, customCodeHelper.getNode(), randomIndex);
+            }
+        );
+    }
+
+    public initialize (): void {
+        this.customCodeHelpers = new Map <CustomCodeHelper, ICustomCodeHelper>();
+
+        if (!this.options.debugProtection) {
+            return;
+        }
+
+        const debugProtectionFunctionCodeHelper: ICustomCodeHelper<TInitialData<DebugProtectionFunctionCodeHelper>> =
+            this.customCodeHelperFactory(CustomCodeHelper.DebugProtectionFunction);
+        const debugProtectionFunctionCallCodeHelper: ICustomCodeHelper<TInitialData<DebugProtectionFunctionCallCodeHelper>> =
+            this.customCodeHelperFactory(CustomCodeHelper.DebugProtectionFunctionCall);
+        const debugProtectionFunctionIntervalCodeHelper: ICustomCodeHelper<TInitialData<DebugProtectionFunctionIntervalCodeHelper>> =
+            this.customCodeHelperFactory(CustomCodeHelper.DebugProtectionFunctionInterval);
+        const callsControllerFunctionCodeHelper: ICustomCodeHelper<TInitialData<CallsControllerFunctionCodeHelper>> =
+            this.customCodeHelperFactory(CustomCodeHelper.CallsControllerFunction);
+
+        this.customCodeHelpers.set(CustomCodeHelper.DebugProtectionFunction, debugProtectionFunctionCodeHelper);
+        this.customCodeHelpers.set(CustomCodeHelper.DebugProtectionFunctionCall, debugProtectionFunctionCallCodeHelper);
+
+        if (this.options.debugProtectionInterval) {
+            this.customCodeHelpers.set(CustomCodeHelper.DebugProtectionFunctionInterval, debugProtectionFunctionIntervalCodeHelper);
+        }
+
+        this.customCodeHelpers.set(CustomCodeHelper.CallsControllerFunction, callsControllerFunctionCodeHelper);
+    }
+}

+ 1 - 1
src/templates/debug-protection-nodes/debug-protection-function-call-node/DebugProtectionFunctionCallTemplate.ts → src/custom-code-helpers/debug-protection/templates/debug-protection-function-call/DebugProtectionFunctionCallTemplate.ts

@@ -4,7 +4,7 @@
 export function DebugProtectionFunctionCallTemplate (): string {
     return `
         (function () {
-            {singleNodeCallControllerFunctionName}(
+            {callControllerFunctionName}(
                 this,
                 function () {
                     const regExp1 = new RegExp('function *\\\\( *\\\\)');

+ 0 - 0
src/templates/debug-protection-nodes/debug-protection-function-interval-node/DebugProtectionFunctionIntervalTemplate.ts → src/custom-code-helpers/debug-protection/templates/debug-protection-function-interval/DebugProtectionFunctionIntervalTemplate.ts


+ 0 - 0
src/templates/debug-protection-nodes/debug-protection-function-node/DebugProtectionFunctionTemplate.ts → src/custom-code-helpers/debug-protection/templates/debug-protection-function/DebugProtectionFunctionTemplate.ts


+ 0 - 0
src/templates/debug-protection-nodes/debug-protection-function-node/DebuggerTemplate.ts → src/custom-code-helpers/debug-protection/templates/debug-protection-function/DebuggerTemplate.ts


+ 0 - 0
src/templates/debug-protection-nodes/debug-protection-function-node/DebuggerTemplateNoEval.ts → src/custom-code-helpers/debug-protection/templates/debug-protection-function/DebuggerTemplateNoEval.ts


+ 35 - 18
src/custom-nodes/domain-lock-nodes/DomainLockNode.ts → src/custom-code-helpers/domain-lock/DomainLockCodeHelper.ts

@@ -4,37 +4,45 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
+import { ICustomCodeHelperObfuscator } from '../../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
 import { ICryptUtils } from '../../interfaces/utils/ICryptUtils';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 
 import { initializable } from '../../decorators/Initializable';
 
-import { DomainLockNodeTemplate } from '../../templates/domain-lock-nodes/domain-lock-node/DomainLockNodeTemplate';
-import { GlobalVariableNoEvalTemplate } from '../../templates/GlobalVariableNoEvalTemplate';
+import { DomainLockTemplate } from './templates/DomainLockTemplate';
+import { GlobalVariableNoEvalTemplate } from '../common/templates/GlobalVariableNoEvalTemplate';
 
-import { AbstractCustomNode } from '../AbstractCustomNode';
+import { AbstractCustomCodeHelper } from '../AbstractCustomCodeHelper';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
-export class DomainLockNode extends AbstractCustomNode {
+export class DomainLockCodeHelper extends AbstractCustomCodeHelper {
     /**
      * @type {string}
      */
     @initializable()
-    protected callsControllerFunctionName!: string;
+    private callsControllerFunctionName!: string;
 
     /**
      * @type {ICryptUtils}
      */
     private readonly cryptUtils: ICryptUtils;
 
+    /**
+     * @type {string}
+     */
+    @initializable()
+    private domainLockFunctionName!: string;
+
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
+     * @param {ICustomCodeHelperObfuscator} customCodeHelperObfuscator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {ICryptUtils} cryptUtils
@@ -42,35 +50,44 @@ export class DomainLockNode extends AbstractCustomNode {
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperObfuscator) customCodeHelperObfuscator: ICustomCodeHelperObfuscator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions,
         @inject(ServiceIdentifiers.ICryptUtils) cryptUtils: ICryptUtils
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            customCodeHelperObfuscator,
+            randomGenerator,
+            options
+        );
 
         this.cryptUtils = cryptUtils;
     }
 
     /**
      * @param {string} callsControllerFunctionName
+     * @param {string} domainLockFunctionName
      */
-    public initialize (callsControllerFunctionName: string): void {
+    public initialize (callsControllerFunctionName: string, domainLockFunctionName: string): void {
         this.callsControllerFunctionName = callsControllerFunctionName;
+        this.domainLockFunctionName = domainLockFunctionName;
     }
 
     /**
-     * @param {string} nodeTemplate
+     * @param {string} codeHelperTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
-        return NodeUtils.convertCodeToStructure(nodeTemplate);
+    protected getNodeStructure (codeHelperTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(codeHelperTemplate);
     }
 
     /**
      * @returns {string}
      */
-    protected getNodeTemplate (): string {
+    protected getCodeHelperTemplate (): string {
         const domainsString: string = this.options.domainLock.join(';');
         const [hiddenDomainsString, diff]: string[] = this.cryptUtils.hideString(
             domainsString,
@@ -80,12 +97,12 @@ export class DomainLockNode extends AbstractCustomNode {
             ? this.getGlobalVariableTemplate()
             : GlobalVariableNoEvalTemplate();
 
-        return this.customNodeFormatter.formatTemplate(DomainLockNodeTemplate(), {
-            domainLockFunctionName: this.identifierNamesGenerator.generate(),
+        return this.customCodeHelperFormatter.formatTemplate(DomainLockTemplate(), {
+            callControllerFunctionName: this.callsControllerFunctionName,
+            domainLockFunctionName: this.domainLockFunctionName,
             diff,
             domains: hiddenDomainsString,
-            globalVariableTemplate,
-            singleNodeCallControllerFunctionName: this.callsControllerFunctionName
+            globalVariableTemplate
         });
     }
 }

+ 129 - 0
src/custom-code-helpers/domain-lock/group/DomainLockCustomCodeHelperGroup.ts

@@ -0,0 +1,129 @@
+import { inject, injectable, } from 'inversify';
+import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
+
+import { TCustomCodeHelperFactory } from '../../../types/container/custom-code-helpers/TCustomCodeHelperFactory';
+import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
+import { TInitialData } from '../../../types/TInitialData';
+import { TNodeWithLexicalScope } from '../../../types/node/TNodeWithLexicalScope';
+import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
+
+import { ICustomCodeHelper } from '../../../interfaces/custom-code-helpers/ICustomCodeHelper';
+import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
+import { ICallsGraphData } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
+
+import { initializable } from '../../../decorators/Initializable';
+
+import { CustomCodeHelper } from '../../../enums/custom-code-helpers/CustomCodeHelper';
+import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent';
+
+import { AbstractCustomCodeHelperGroup } from '../../AbstractCustomCodeHelperGroup';
+import { CallsControllerFunctionCodeHelper } from '../../calls-controller/CallsControllerFunctionCodeHelper';
+import { DomainLockCodeHelper } from '../DomainLockCodeHelper';
+import { NodeAppender } from '../../../node/NodeAppender';
+import { NodeLexicalScopeUtils } from '../../../node/NodeLexicalScopeUtils';
+import { NodeGuards } from '../../../node/NodeGuards';
+
+@injectable()
+export class DomainLockCustomCodeHelperGroup extends AbstractCustomCodeHelperGroup {
+    /**
+     * @type {ObfuscationEvent}
+     */
+    protected readonly appendEvent: ObfuscationEvent = ObfuscationEvent.BeforeObfuscation;
+
+    /**
+     * @type {Map<CustomCodeHelper, ICustomCodeHelper>}
+     */
+    @initializable()
+    protected customCodeHelpers!: Map <CustomCodeHelper, ICustomCodeHelper>;
+
+    /**
+     * @type {TCustomCodeHelperFactory}
+     */
+    private readonly customCodeHelperFactory: TCustomCodeHelperFactory;
+
+    /**
+     * @param {TCustomCodeHelperFactory} customCodeHelperFactory
+     * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {IRandomGenerator} randomGenerator
+     * @param {IOptions} options
+     */
+    public constructor (
+        @inject(ServiceIdentifiers.Factory__ICustomCodeHelper) customCodeHelperFactory: TCustomCodeHelperFactory,
+        @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
+            identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(identifierNamesGeneratorFactory, randomGenerator, options);
+
+        this.customCodeHelperFactory = customCodeHelperFactory;
+    }
+
+    /**
+     * @param {TNodeWithStatements} nodeWithStatements
+     * @param {ICallsGraphData[]} callsGraphData
+     */
+    public appendNodes (nodeWithStatements: TNodeWithStatements, callsGraphData: ICallsGraphData[]): void {
+        if (!this.options.domainLock.length) {
+            return;
+        }
+
+        const randomCallsGraphIndex: number = this.getRandomCallsGraphIndex(callsGraphData.length);
+
+        const domainLockFunctionHostNode: TNodeWithStatements = callsGraphData.length
+            ? NodeAppender.getOptimalBlockScope(callsGraphData, randomCallsGraphIndex)
+            : nodeWithStatements;
+        const callsControllerHostNode: TNodeWithStatements = callsGraphData.length
+            ? NodeAppender.getOptimalBlockScope(callsGraphData, randomCallsGraphIndex, 1)
+            : nodeWithStatements;
+
+        const domainLockFunctionLexicalScopeNode: TNodeWithLexicalScope | null = NodeLexicalScopeUtils
+            .getLexicalScope(domainLockFunctionHostNode) ?? null;
+
+        const domainLockFunctionName: string = domainLockFunctionLexicalScopeNode
+            && NodeGuards.isProgramNode(domainLockFunctionLexicalScopeNode)
+            ? this.identifierNamesGenerator.generate(domainLockFunctionLexicalScopeNode)
+            : this.randomGenerator.getRandomString(5);
+        const callsControllerFunctionName: string = domainLockFunctionLexicalScopeNode
+            && NodeGuards.isProgramNode(domainLockFunctionLexicalScopeNode)
+            ? this.identifierNamesGenerator.generate(domainLockFunctionLexicalScopeNode)
+            : this.randomGenerator.getRandomString(5);
+
+        // domainLock helper nodes append
+        this.appendCustomNodeIfExist(
+            CustomCodeHelper.DomainLock,
+            (customCodeHelper: ICustomCodeHelper<TInitialData<DomainLockCodeHelper>>) => {
+                customCodeHelper.initialize(callsControllerFunctionName, domainLockFunctionName);
+
+                NodeAppender.prepend(domainLockFunctionHostNode, customCodeHelper.getNode());
+            }
+        );
+
+        // nodeCallsControllerFunction helper nodes append
+        this.appendCustomNodeIfExist(
+            CustomCodeHelper.CallsControllerFunction,
+            (customCodeHelper: ICustomCodeHelper<TInitialData<CallsControllerFunctionCodeHelper>>) => {
+                customCodeHelper.initialize(this.appendEvent, callsControllerFunctionName);
+
+                NodeAppender.prepend(callsControllerHostNode, customCodeHelper.getNode());
+            }
+        );
+    }
+
+    public initialize (): void {
+        this.customCodeHelpers = new Map <CustomCodeHelper, ICustomCodeHelper>();
+
+        if (!this.options.domainLock.length) {
+            return;
+        }
+
+        const domainLockCodeHelper: ICustomCodeHelper<TInitialData<DomainLockCodeHelper>> =
+            this.customCodeHelperFactory(CustomCodeHelper.DomainLock);
+        const callsControllerFunctionCodeHelper: ICustomCodeHelper<TInitialData<CallsControllerFunctionCodeHelper>> =
+            this.customCodeHelperFactory(CustomCodeHelper.CallsControllerFunction);
+
+        this.customCodeHelpers.set(CustomCodeHelper.DomainLock, domainLockCodeHelper);
+        this.customCodeHelpers.set(CustomCodeHelper.CallsControllerFunction, callsControllerFunctionCodeHelper);
+    }
+}

+ 2 - 2
src/templates/domain-lock-nodes/domain-lock-node/DomainLockNodeTemplate.ts → src/custom-code-helpers/domain-lock/templates/DomainLockTemplate.ts

@@ -1,9 +1,9 @@
 /**
  * @returns {string}
  */
-export function DomainLockNodeTemplate (): string {
+export function DomainLockTemplate (): string {
     return `
-        const {domainLockFunctionName} = {singleNodeCallControllerFunctionName}(this, function () {
+        const {domainLockFunctionName} = {callControllerFunctionName}(this, function () {
             
             {globalVariableTemplate}
             

+ 33 - 28
src/custom-nodes/self-defending-nodes/SelfDefendingUnicodeNode.ts → src/custom-code-helpers/self-defending/SelfDefendingUnicodeCodeHelper.ts

@@ -4,23 +4,21 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
+import { ICustomCodeHelperObfuscator } from '../../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
 import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { initializable } from '../../decorators/Initializable';
 
-import { NO_ADDITIONAL_NODES_PRESET } from '../../options/presets/NoCustomNodes';
+import { SelfDefendingTemplate } from './templates/SelfDefendingTemplate';
 
-import { SelfDefendingTemplate } from '../../templates/self-defending-nodes/self-defending-unicode-node/SelfDefendingTemplate';
-
-import { AbstractCustomNode } from '../AbstractCustomNode';
-import { JavaScriptObfuscator } from '../../JavaScriptObfuscatorFacade';
+import { AbstractCustomCodeHelper } from '../AbstractCustomCodeHelper';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
-export class SelfDefendingUnicodeNode extends AbstractCustomNode {
+export class SelfDefendingUnicodeCodeHelper extends AbstractCustomCodeHelper {
     /**
      * @type {IEscapeSequenceEncoder}
      */
@@ -32,9 +30,16 @@ export class SelfDefendingUnicodeNode extends AbstractCustomNode {
     @initializable()
     private callsControllerFunctionName!: string;
 
+    /**
+     * @type {string}
+     */
+    @initializable()
+    private selfDefendingFunctionName!: string;
+
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
+     * @param {ICustomCodeHelperObfuscator} customCodeHelperObfuscator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
@@ -42,47 +47,47 @@ export class SelfDefendingUnicodeNode extends AbstractCustomNode {
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperObfuscator) customCodeHelperObfuscator: ICustomCodeHelperObfuscator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions,
         @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            customCodeHelperObfuscator,
+            randomGenerator,
+            options
+        );
 
         this.escapeSequenceEncoder = escapeSequenceEncoder;
     }
 
     /**
      * @param {string} callsControllerFunctionName
+     * @param {string} selfDefendingFunctionName
      */
-    public initialize (callsControllerFunctionName: string): void {
+    public initialize (callsControllerFunctionName: string, selfDefendingFunctionName: string): void {
         this.callsControllerFunctionName = callsControllerFunctionName;
+        this.selfDefendingFunctionName = selfDefendingFunctionName;
     }
 
     /**
-     * @param {string} nodeTemplate
+     * @param {string} codeHelperTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
-        return NodeUtils.convertCodeToStructure(nodeTemplate);
+    protected getNodeStructure (codeHelperTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(codeHelperTemplate);
     }
 
     /**
      * @returns {string}
      */
-    protected getNodeTemplate (): string {
-        return JavaScriptObfuscator.obfuscate(
-            this.customNodeFormatter.formatTemplate(SelfDefendingTemplate(this.escapeSequenceEncoder), {
-                selfDefendingFunctionName: this.identifierNamesGenerator.generate(),
-                singleNodeCallControllerFunctionName: this.callsControllerFunctionName
-            }),
-            {
-                ...NO_ADDITIONAL_NODES_PRESET,
-                identifierNamesGenerator: this.options.identifierNamesGenerator,
-                identifiersDictionary: this.options.identifiersDictionary,
-                seed: this.options.seed,
-                unicodeEscapeSequence: true
-            }
-        ).getObfuscatedCode();
+    protected getCodeHelperTemplate (): string {
+        return this.customCodeHelperFormatter.formatTemplate(SelfDefendingTemplate(this.escapeSequenceEncoder), {
+            callControllerFunctionName: this.callsControllerFunctionName,
+            selfDefendingFunctionName: this.selfDefendingFunctionName
+        });
     }
 }

+ 126 - 0
src/custom-code-helpers/self-defending/group/SelfDefendingCodeHelperGroup.ts

@@ -0,0 +1,126 @@
+import { inject, injectable, } from 'inversify';
+import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
+
+import { TCustomCodeHelperFactory } from '../../../types/container/custom-code-helpers/TCustomCodeHelperFactory';
+import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
+import { TInitialData } from '../../../types/TInitialData';
+import { TNodeWithLexicalScope } from '../../../types/node/TNodeWithLexicalScope';
+import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
+
+import { ICustomCodeHelper } from '../../../interfaces/custom-code-helpers/ICustomCodeHelper';
+import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
+import { ICallsGraphData } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
+
+import { initializable } from '../../../decorators/Initializable';
+
+import { CustomCodeHelper } from '../../../enums/custom-code-helpers/CustomCodeHelper';
+import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent';
+
+import { AbstractCustomCodeHelperGroup } from '../../AbstractCustomCodeHelperGroup';
+import { CallsControllerFunctionCodeHelper } from '../../calls-controller/CallsControllerFunctionCodeHelper';
+import { NodeAppender } from '../../../node/NodeAppender';
+import { NodeLexicalScopeUtils } from '../../../node/NodeLexicalScopeUtils';
+import { SelfDefendingUnicodeCodeHelper } from '../SelfDefendingUnicodeCodeHelper';
+
+@injectable()
+export class SelfDefendingCodeHelperGroup extends AbstractCustomCodeHelperGroup {
+    /**
+     * @type {ObfuscationEvent}
+     */
+    protected appendEvent: ObfuscationEvent = ObfuscationEvent.BeforeObfuscation;
+
+    /**
+     * @type {Map<CustomCodeHelper, ICustomCodeHelper>}
+     */
+    @initializable()
+    protected customCodeHelpers!: Map <CustomCodeHelper, ICustomCodeHelper>;
+
+    /**
+     * @type {TCustomCodeHelperFactory}
+     */
+    private readonly customCodeHelperFactory: TCustomCodeHelperFactory;
+
+    /**
+     * @param {TCustomCodeHelperFactory} customCodeHelperFactory
+     * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {IRandomGenerator} randomGenerator
+     * @param {IOptions} options
+     */
+    public constructor (
+        @inject(ServiceIdentifiers.Factory__ICustomCodeHelper) customCodeHelperFactory: TCustomCodeHelperFactory,
+        @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
+            identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(identifierNamesGeneratorFactory, randomGenerator, options);
+
+        this.customCodeHelperFactory = customCodeHelperFactory;
+    }
+
+    /**
+     * @param {TNodeWithStatements} nodeWithStatements
+     * @param {ICallsGraphData[]} callsGraphData
+     */
+    public appendNodes (nodeWithStatements: TNodeWithStatements, callsGraphData: ICallsGraphData[]): void {
+        if (!this.options.selfDefending) {
+            return;
+        }
+
+        const randomCallsGraphIndex: number = this.getRandomCallsGraphIndex(callsGraphData.length);
+
+        const selfDefendingFunctionHostNode: TNodeWithStatements = callsGraphData.length
+            ? NodeAppender.getOptimalBlockScope(callsGraphData, randomCallsGraphIndex)
+            : nodeWithStatements;
+        const callsControllerHostNode: TNodeWithStatements = callsGraphData.length
+            ? NodeAppender.getOptimalBlockScope(callsGraphData, randomCallsGraphIndex, 1)
+            : nodeWithStatements;
+
+        const selfDefendingFunctionLexicalScopeNode: TNodeWithLexicalScope | null = NodeLexicalScopeUtils
+            .getLexicalScope(selfDefendingFunctionHostNode) ?? null;
+
+        const selfDefendingFunctionName: string = selfDefendingFunctionLexicalScopeNode
+            ? this.identifierNamesGenerator.generate(selfDefendingFunctionLexicalScopeNode)
+            : this.identifierNamesGenerator.generateForGlobalScope();
+        const callsControllerFunctionName: string = selfDefendingFunctionLexicalScopeNode
+            ? this.identifierNamesGenerator.generate(selfDefendingFunctionLexicalScopeNode)
+            : this.identifierNamesGenerator.generateForGlobalScope();
+
+        // selfDefendingUnicode helper nodes append
+        this.appendCustomNodeIfExist(
+            CustomCodeHelper.SelfDefendingUnicode,
+            (customCodeHelper: ICustomCodeHelper<TInitialData<SelfDefendingUnicodeCodeHelper>>) => {
+                customCodeHelper.initialize(callsControllerFunctionName, selfDefendingFunctionName);
+
+                NodeAppender.prepend(selfDefendingFunctionHostNode, customCodeHelper.getNode());
+            }
+        );
+
+        // nodeCallsControllerFunction helper nodes append
+        this.appendCustomNodeIfExist(
+            CustomCodeHelper.CallsControllerFunction,
+            (customCodeHelper: ICustomCodeHelper<TInitialData<CallsControllerFunctionCodeHelper>>) => {
+                customCodeHelper.initialize(this.appendEvent, callsControllerFunctionName);
+
+                NodeAppender.prepend(callsControllerHostNode, customCodeHelper.getNode());
+            }
+        );
+    }
+
+    public initialize (): void {
+        this.customCodeHelpers = new Map <CustomCodeHelper, ICustomCodeHelper>();
+
+        if (!this.options.selfDefending) {
+            return;
+        }
+
+        const selfDefendingUnicodeCodeHelper: ICustomCodeHelper<TInitialData<SelfDefendingUnicodeCodeHelper>> =
+            this.customCodeHelperFactory(CustomCodeHelper.SelfDefendingUnicode);
+        const callsControllerFunctionCodeHelper: ICustomCodeHelper<TInitialData<CallsControllerFunctionCodeHelper>> =
+            this.customCodeHelperFactory(CustomCodeHelper.CallsControllerFunction);
+
+        this.customCodeHelpers.set(CustomCodeHelper.SelfDefendingUnicode, selfDefendingUnicodeCodeHelper);
+        this.customCodeHelpers.set(CustomCodeHelper.CallsControllerFunction, callsControllerFunctionCodeHelper);
+    }
+}

+ 26 - 0
src/custom-code-helpers/self-defending/templates/SelfDefendingTemplate.ts

@@ -0,0 +1,26 @@
+import { IEscapeSequenceEncoder } from '../../../interfaces/utils/IEscapeSequenceEncoder';
+
+/**
+ * SelfDefendingTemplate. Enters code in infinity loop.
+ * Notice, that second and third call to recursiveFunc1('indexOf') has cyrillic `е` character instead latin
+ *
+ * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
+ * @returns {string}
+ */
+export function SelfDefendingTemplate (escapeSequenceEncoder: IEscapeSequenceEncoder): string {
+    return `
+        const {selfDefendingFunctionName} = {callControllerFunctionName}(this, function () {
+            const test = function () {
+                const regExp = test
+                    .constructor('return /" + this + "/')()
+                    .compile('^([^ ]+( +[^ ]+)+)+[^ ]}');
+                
+                return !regExp.test({selfDefendingFunctionName});
+            };
+            
+            return test();
+        });
+        
+        {selfDefendingFunctionName}();
+    `;
+}

+ 41 - 36
src/custom-nodes/string-array-nodes/StringArrayCallsWrapper.ts → src/custom-code-helpers/string-array/StringArrayCallsWrapperCodeHelper.ts

@@ -4,32 +4,30 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
+import { ICustomCodeHelperObfuscator } from '../../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
 import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
 
 import { initializable } from '../../decorators/Initializable';
 
-import { NO_ADDITIONAL_NODES_PRESET } from '../../options/presets/NoCustomNodes';
+import { AtobTemplate } from './templates/string-array-calls-wrapper/AtobTemplate';
+import { GlobalVariableNoEvalTemplate } from '../common/templates/GlobalVariableNoEvalTemplate';
+import { Rc4Template } from './templates/string-array-calls-wrapper/Rc4Template';
+import { SelfDefendingTemplate } from './templates/string-array-calls-wrapper/SelfDefendingTemplate';
+import { StringArrayBase64DecodeTemplate } from './templates/string-array-calls-wrapper/StringArrayBase64DecodeTemplate';
+import { StringArrayCallsWrapperTemplate } from './templates/string-array-calls-wrapper/StringArrayCallsWrapperTemplate';
+import { StringArrayRC4DecodeTemplate } from './templates/string-array-calls-wrapper/StringArrayRC4DecodeTemplate';
 
-import { AtobTemplate } from '../../templates/AtobTemplate';
-import { GlobalVariableNoEvalTemplate } from '../../templates/GlobalVariableNoEvalTemplate';
-import { Rc4Template } from '../../templates/Rc4Template';
-import { SelfDefendingTemplate } from '../../templates/string-array-nodes/string-array-calls-wrapper/SelfDefendingTemplate';
-import { StringArrayBase64DecodeNodeTemplate } from '../../templates/string-array-nodes/string-array-calls-wrapper/StringArrayBase64DecodeNodeTemplate';
-import { StringArrayCallsWrapperTemplate } from '../../templates/string-array-nodes/string-array-calls-wrapper/StringArrayCallsWrapperTemplate';
-import { StringArrayRc4DecodeNodeTemplate } from '../../templates/string-array-nodes/string-array-calls-wrapper/StringArrayRC4DecodeNodeTemplate';
-
-import { AbstractCustomNode } from '../AbstractCustomNode';
-import { JavaScriptObfuscator } from '../../JavaScriptObfuscatorFacade';
+import { AbstractCustomCodeHelper } from '../AbstractCustomCodeHelper';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
-export class StringArrayCallsWrapper extends AbstractCustomNode {
+export class StringArrayCallsWrapperCodeHelper extends AbstractCustomCodeHelper {
     /**
      * @type {IEscapeSequenceEncoder}
      */
@@ -49,7 +47,8 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
+     * @param {ICustomCodeHelperObfuscator} customCodeHelperObfuscator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
@@ -57,12 +56,19 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperObfuscator) customCodeHelperObfuscator: ICustomCodeHelperObfuscator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions,
         @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            customCodeHelperObfuscator,
+            randomGenerator,
+            options
+        );
 
         this.escapeSequenceEncoder = escapeSequenceEncoder;
     }
@@ -80,32 +86,31 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
     }
 
     /**
-     * @param {string} nodeTemplate
+     * @param {string} codeHelperTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
-        return NodeUtils.convertCodeToStructure(nodeTemplate);
+    protected getNodeStructure (codeHelperTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(codeHelperTemplate);
     }
 
     /**
      * @returns {string}
      */
-    protected getNodeTemplate (): string {
-        const decodeNodeTemplate: string = this.getDecodeStringArrayTemplate();
+    protected getCodeHelperTemplate (): string {
+        const decodeCodeHelperTemplate: string = this.getDecodeStringArrayTemplate();
+
+        const preservedNames: string[] = [`^${this.stringArrayName}$`];
 
-        return JavaScriptObfuscator.obfuscate(
-            this.customNodeFormatter.formatTemplate(StringArrayCallsWrapperTemplate(), {
-                decodeNodeTemplate,
+        return this.customCodeHelperObfuscator.obfuscateTemplate(
+            this.customCodeHelperFormatter.formatTemplate(StringArrayCallsWrapperTemplate(), {
+                decodeCodeHelperTemplate,
                 stringArrayCallsWrapperName: this.stringArrayCallsWrapperName,
                 stringArrayName: this.stringArrayName
             }),
             {
-                ...NO_ADDITIONAL_NODES_PRESET,
-                identifierNamesGenerator: this.options.identifierNamesGenerator,
-                identifiersDictionary: this.options.identifiersDictionary,
-                seed: this.randomGenerator.getRawSeed()
+                reservedNames: preservedNames
             }
-        ).getObfuscatedCode();
+        );
     }
 
     /**
@@ -115,13 +120,13 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
         const globalVariableTemplate: string = this.options.target !== ObfuscationTarget.BrowserNoEval
             ? this.getGlobalVariableTemplate()
             : GlobalVariableNoEvalTemplate();
-        const atobPolyfill: string = this.customNodeFormatter.formatTemplate(AtobTemplate(), { globalVariableTemplate });
+        const atobPolyfill: string = this.customCodeHelperFormatter.formatTemplate(AtobTemplate(), { globalVariableTemplate });
 
         let decodeStringArrayTemplate: string = '';
         let selfDefendingCode: string = '';
 
         if (this.options.selfDefending) {
-            selfDefendingCode = this.customNodeFormatter.formatTemplate(
+            selfDefendingCode = this.customCodeHelperFormatter.formatTemplate(
                 SelfDefendingTemplate(
                     this.randomGenerator,
                     this.escapeSequenceEncoder
@@ -135,12 +140,12 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
 
         switch (this.options.stringArrayEncoding) {
             case StringArrayEncoding.Rc4:
-                decodeStringArrayTemplate = this.customNodeFormatter.formatTemplate(
-                    StringArrayRc4DecodeNodeTemplate(this.randomGenerator),
+                decodeStringArrayTemplate = this.customCodeHelperFormatter.formatTemplate(
+                    StringArrayRC4DecodeTemplate(this.randomGenerator),
                     {
                         atobPolyfill,
-                        rc4Polyfill: Rc4Template(),
                         selfDefendingCode,
+                        rc4Polyfill: Rc4Template(),
                         stringArrayCallsWrapperName: this.stringArrayCallsWrapperName
                     }
                 );
@@ -148,8 +153,8 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
                 break;
 
             case StringArrayEncoding.Base64:
-                decodeStringArrayTemplate = this.customNodeFormatter.formatTemplate(
-                    StringArrayBase64DecodeNodeTemplate(this.randomGenerator),
+                decodeStringArrayTemplate = this.customCodeHelperFormatter.formatTemplate(
+                    StringArrayBase64DecodeTemplate(this.randomGenerator),
                     {
                         atobPolyfill,
                         selfDefendingCode,

+ 21 - 12
src/custom-nodes/string-array-nodes/StringArrayNode.ts → src/custom-code-helpers/string-array/StringArrayCodeHelper.ts

@@ -4,20 +4,21 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
+import { ICustomCodeHelperObfuscator } from '../../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 import { IStringArrayStorage } from '../../interfaces/storages/string-array-storage/IStringArrayStorage';
 
 import { initializable } from '../../decorators/Initializable';
 
-import { StringArrayTemplate } from '../../templates/string-array-nodes/string-array-node/StringArrayTemplate';
+import { StringArrayTemplate } from './templates/string-array/StringArrayTemplate';
 
-import { AbstractCustomNode } from '../AbstractCustomNode';
+import { AbstractCustomCodeHelper } from '../AbstractCustomCodeHelper';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
-export class StringArrayNode extends AbstractCustomNode {
+export class StringArrayCodeHelper extends AbstractCustomCodeHelper {
     /**
      * @type {IStringArrayStorage}
      */
@@ -32,18 +33,26 @@ export class StringArrayNode extends AbstractCustomNode {
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
+     * @param {ICustomCodeHelperObfuscator} customCodeHelperObfuscator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperObfuscator) customCodeHelperObfuscator: ICustomCodeHelperObfuscator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            customCodeHelperObfuscator,
+            randomGenerator,
+            options
+        );
     }
 
     /**
@@ -59,18 +68,18 @@ export class StringArrayNode extends AbstractCustomNode {
     }
 
     /**
-     * @param {string} nodeTemplate
+     * @param {string} codeHelperTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
-        return NodeUtils.convertCodeToStructure(nodeTemplate);
+    protected getNodeStructure (codeHelperTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(codeHelperTemplate);
     }
 
     /**
      * @returns {string}
      */
-    protected getNodeTemplate (): string {
-        return this.customNodeFormatter.formatTemplate(StringArrayTemplate(), {
+    protected getCodeHelperTemplate (): string {
+        return this.customCodeHelperFormatter.formatTemplate(StringArrayTemplate(), {
             stringArrayName: this.stringArrayName,
             stringArray: this.stringArrayStorage.toString()
         });

+ 31 - 27
src/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.ts → src/custom-code-helpers/string-array/StringArrayRotateFunctionCodeHelper.ts

@@ -4,25 +4,23 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
+import { ICustomCodeHelperObfuscator } from '../../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
 import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { initializable } from '../../decorators/Initializable';
 
-import { NO_ADDITIONAL_NODES_PRESET } from '../../options/presets/NoCustomNodes';
+import { SelfDefendingTemplate } from './templates/string-array-rotate-function/SelfDefendingTemplate';
+import { StringArrayRotateFunctionTemplate } from './templates/string-array-rotate-function/StringArrayRotateFunctionTemplate';
 
-import { SelfDefendingTemplate } from '../../templates/string-array-nodes/string-array-rotate-function-node/SelfDefendingTemplate';
-import { StringArrayRotateFunctionTemplate } from '../../templates/string-array-nodes/string-array-rotate-function-node/StringArrayRotateFunctionTemplate';
-
-import { AbstractCustomNode } from '../AbstractCustomNode';
-import { JavaScriptObfuscator } from '../../JavaScriptObfuscatorFacade';
+import { AbstractCustomCodeHelper } from '../AbstractCustomCodeHelper';
 import { NodeUtils } from '../../node/NodeUtils';
 import { NumberUtils } from '../../utils/NumberUtils';
 
 @injectable()
-export class StringArrayRotateFunctionNode extends AbstractCustomNode {
+export class StringArrayRotateFunctionCodeHelper extends AbstractCustomCodeHelper {
     /**
      * @type {IEscapeSequenceEncoder}
      */
@@ -42,7 +40,8 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
+     * @param {ICustomCodeHelperObfuscator} customCodeHelperObfuscator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
@@ -50,12 +49,19 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperObfuscator) customCodeHelperObfuscator: ICustomCodeHelperObfuscator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions,
         @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            customCodeHelperObfuscator,
+            randomGenerator,
+            options
+        );
 
         this.escapeSequenceEncoder = escapeSequenceEncoder;
     }
@@ -73,24 +79,25 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
     }
 
     /**
-     * @param {string} nodeTemplate
+     * @param {string} codeHelperTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
-        return NodeUtils.convertCodeToStructure(nodeTemplate);
+    protected getNodeStructure (codeHelperTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(codeHelperTemplate);
     }
 
     /**
      * @returns {string}
      */
-    protected getNodeTemplate (): string {
-        const timesName: string = this.identifierNamesGenerator.generate();
-        const whileFunctionName: string = this.identifierNamesGenerator.generate();
+    protected getCodeHelperTemplate (): string {
+        const timesName: string = this.identifierNamesGenerator.generateForGlobalScope();
+        const whileFunctionName: string = this.identifierNamesGenerator.generateForGlobalScope();
+        const preservedNames: string[] = [`^${this.stringArrayName}$`];
 
         let code: string = '';
 
         if (this.options.selfDefending) {
-            code = this.customNodeFormatter.formatTemplate(SelfDefendingTemplate(this.escapeSequenceEncoder), {
+            code = this.customCodeHelperFormatter.formatTemplate(SelfDefendingTemplate(this.escapeSequenceEncoder), {
                 timesName,
                 whileFunctionName
             });
@@ -98,20 +105,17 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
             code = `${whileFunctionName}(++${timesName})`;
         }
 
-        return JavaScriptObfuscator.obfuscate(
-            this.customNodeFormatter.formatTemplate(StringArrayRotateFunctionTemplate(), {
+        return this.customCodeHelperObfuscator.obfuscateTemplate(
+            this.customCodeHelperFormatter.formatTemplate(StringArrayRotateFunctionTemplate(), {
                 code,
                 timesName,
+                whileFunctionName,
                 stringArrayName: this.stringArrayName,
-                stringArrayRotationAmount: NumberUtils.toHex(this.stringArrayRotationAmount),
-                whileFunctionName
+                stringArrayRotationAmount: NumberUtils.toHex(this.stringArrayRotationAmount)
             }),
             {
-                ...NO_ADDITIONAL_NODES_PRESET,
-                identifierNamesGenerator: this.options.identifierNamesGenerator,
-                identifiersDictionary: this.options.identifiersDictionary,
-                seed: this.randomGenerator.getRawSeed()
+                reservedNames: preservedNames
             }
-        ).getObfuscatedCode();
+        );
     }
 }

+ 133 - 0
src/custom-code-helpers/string-array/group/StringArrayCodeHelperGroup.ts

@@ -0,0 +1,133 @@
+import { inject, injectable, } from 'inversify';
+import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
+
+import { TCustomCodeHelperFactory } from '../../../types/container/custom-code-helpers/TCustomCodeHelperFactory';
+import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
+import { TInitialData } from '../../../types/TInitialData';
+import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
+
+import { ICallsGraphData } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
+import { ICustomCodeHelper } from '../../../interfaces/custom-code-helpers/ICustomCodeHelper';
+import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
+import { IStringArrayStorage } from '../../../interfaces/storages/string-array-storage/IStringArrayStorage';
+
+import { initializable } from '../../../decorators/Initializable';
+
+import { CustomCodeHelper } from '../../../enums/custom-code-helpers/CustomCodeHelper';
+import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent';
+
+import { AbstractCustomCodeHelperGroup } from '../../AbstractCustomCodeHelperGroup';
+import { NodeAppender } from '../../../node/NodeAppender';
+import { StringArrayCodeHelper } from '../StringArrayCodeHelper';
+import { StringArrayCallsWrapperCodeHelper } from '../StringArrayCallsWrapperCodeHelper';
+import { StringArrayRotateFunctionCodeHelper } from '../StringArrayRotateFunctionCodeHelper';
+
+@injectable()
+export class StringArrayCodeHelperGroup extends AbstractCustomCodeHelperGroup {
+    /**
+     * @type {ObfuscationEvent}
+     */
+    protected appendEvent: ObfuscationEvent = ObfuscationEvent.AfterObfuscation;
+
+    /**
+     * @type {Map<CustomCodeHelper, ICustomCodeHelper>}
+     */
+    @initializable()
+    protected customCodeHelpers!: Map <CustomCodeHelper, ICustomCodeHelper>;
+
+    /**
+     * @type {TCustomCodeHelperFactory}
+     */
+    private readonly customCodeHelperFactory: TCustomCodeHelperFactory;
+
+    /**
+     * @type {IStringArrayStorage}
+     */
+    private readonly stringArrayStorage: IStringArrayStorage;
+
+    /**
+     * @param {TCustomCodeHelperFactory} customCodeHelperFactory
+     * @param {IStringArrayStorage} stringArrayStorage
+     * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {IRandomGenerator} randomGenerator
+     * @param {IOptions} options
+     */
+    public constructor (
+        @inject(ServiceIdentifiers.Factory__ICustomCodeHelper) customCodeHelperFactory: TCustomCodeHelperFactory,
+        @inject(ServiceIdentifiers.IStringArrayStorage) stringArrayStorage: IStringArrayStorage,
+        @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
+            identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(identifierNamesGeneratorFactory, randomGenerator, options);
+
+        this.customCodeHelperFactory = customCodeHelperFactory;
+        this.stringArrayStorage = stringArrayStorage;
+    }
+
+    /**
+     * @param {TNodeWithStatements} nodeWithStatements
+     * @param {ICallsGraphData[]} callsGraphData
+     */
+    public appendNodes (nodeWithStatements: TNodeWithStatements, callsGraphData: ICallsGraphData[]): void {
+        if (!this.stringArrayStorage.getLength()) {
+            return;
+        }
+
+        // stringArray helper nodes append
+        this.appendCustomNodeIfExist(
+            CustomCodeHelper.StringArray,
+            (customCodeHelper: ICustomCodeHelper<TInitialData<StringArrayCodeHelper>>) => {
+                NodeAppender.prepend(nodeWithStatements, customCodeHelper.getNode());
+            }
+        );
+
+        // stringArrayCallsWrapper helper nodes append
+        this.appendCustomNodeIfExist(
+            CustomCodeHelper.StringArrayCallsWrapper,
+            (customCodeHelper: ICustomCodeHelper<TInitialData<StringArrayCallsWrapperCodeHelper>>) => {
+                NodeAppender.insertAtIndex(nodeWithStatements, customCodeHelper.getNode(), 1);
+            }
+        );
+
+        // stringArrayRotateFunction helper nodes append
+        this.appendCustomNodeIfExist(
+            CustomCodeHelper.StringArrayRotateFunction,
+            (customCodeHelper: ICustomCodeHelper<TInitialData<StringArrayRotateFunctionCodeHelper>>) => {
+                NodeAppender.insertAtIndex(nodeWithStatements, customCodeHelper.getNode(), 1);
+            }
+        );
+    }
+
+    public initialize (): void {
+        this.customCodeHelpers = new Map <CustomCodeHelper, ICustomCodeHelper>();
+
+        if (!this.options.stringArray) {
+            return;
+        }
+
+        const stringArrayCodeHelper: ICustomCodeHelper<TInitialData<StringArrayCodeHelper>> =
+            this.customCodeHelperFactory(CustomCodeHelper.StringArray);
+        const stringArrayCallsWrapperCodeHelper: ICustomCodeHelper<TInitialData<StringArrayCallsWrapperCodeHelper>> =
+            this.customCodeHelperFactory(CustomCodeHelper.StringArrayCallsWrapper);
+        const stringArrayRotateFunctionCodeHelper: ICustomCodeHelper<TInitialData<StringArrayRotateFunctionCodeHelper>> =
+            this.customCodeHelperFactory(CustomCodeHelper.StringArrayRotateFunction);
+
+        const stringArrayName: string = this.stringArrayStorage.getStorageName();
+        const stringArrayCallsWrapperName: string = this.stringArrayStorage.getStorageCallsWrapperName();
+        const stringArrayRotationAmount: number = this.stringArrayStorage.getRotationAmount();
+
+        stringArrayCodeHelper.initialize(this.stringArrayStorage, stringArrayName);
+        stringArrayCallsWrapperCodeHelper.initialize(stringArrayName, stringArrayCallsWrapperName);
+        stringArrayRotateFunctionCodeHelper.initialize(stringArrayName, stringArrayRotationAmount);
+
+        this.customCodeHelpers.set(CustomCodeHelper.StringArray, stringArrayCodeHelper);
+        this.customCodeHelpers.set(CustomCodeHelper.StringArrayCallsWrapper, stringArrayCallsWrapperCodeHelper);
+
+        if (this.options.rotateStringArray) {
+            this.customCodeHelpers.set(CustomCodeHelper.StringArrayRotateFunction, stringArrayRotateFunctionCodeHelper);
+        }
+    }
+}

+ 0 - 0
src/templates/AtobTemplate.ts → src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/AtobTemplate.ts


+ 0 - 0
src/templates/Rc4Template.ts → src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/Rc4Template.ts


+ 2 - 2
src/templates/string-array-nodes/string-array-calls-wrapper/SelfDefendingTemplate.ts → src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/SelfDefendingTemplate.ts

@@ -1,5 +1,5 @@
-import { IEscapeSequenceEncoder } from '../../../interfaces/utils/IEscapeSequenceEncoder';
-import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
+import { IEscapeSequenceEncoder } from '../../../../interfaces/utils/IEscapeSequenceEncoder';
+import { IRandomGenerator } from '../../../../interfaces/utils/IRandomGenerator';
 
 /**
  * @param {IRandomGenerator} randomGenerator

+ 2 - 2
src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayBase64DecodeNodeTemplate.ts → src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/StringArrayBase64DecodeTemplate.ts

@@ -1,11 +1,11 @@
-import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
+import { IRandomGenerator } from '../../../../interfaces/utils/IRandomGenerator';
 
 /**
  * @param {IRandomGenerator} randomGenerator
  * @returns {string}
  * @constructor
  */
-export function StringArrayBase64DecodeNodeTemplate (
+export function StringArrayBase64DecodeTemplate (
     randomGenerator: IRandomGenerator
 ): string {
     const identifierLength: number = 6;

+ 1 - 1
src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayCallsWrapperTemplate.ts → src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/StringArrayCallsWrapperTemplate.ts

@@ -8,7 +8,7 @@ export function StringArrayCallsWrapperTemplate (): string {
             
             let value = {stringArrayName}[index];
             
-            {decodeNodeTemplate}
+            {decodeCodeHelperTemplate}
         
             return value;
         };

+ 2 - 2
src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayRC4DecodeNodeTemplate.ts → src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/StringArrayRC4DecodeTemplate.ts

@@ -1,11 +1,11 @@
-import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
+import { IRandomGenerator } from '../../../../interfaces/utils/IRandomGenerator';
 
 /**
  * @param {IRandomGenerator} randomGenerator
  * @returns {string}
  * @constructor
  */
-export function StringArrayRc4DecodeNodeTemplate (
+export function StringArrayRC4DecodeTemplate (
     randomGenerator: IRandomGenerator
 ): string {
     const identifierLength: number = 6;

+ 1 - 1
src/templates/string-array-nodes/string-array-rotate-function-node/SelfDefendingTemplate.ts → src/custom-code-helpers/string-array/templates/string-array-rotate-function/SelfDefendingTemplate.ts

@@ -1,4 +1,4 @@
-import { IEscapeSequenceEncoder } from '../../../interfaces/utils/IEscapeSequenceEncoder';
+import { IEscapeSequenceEncoder } from '../../../../interfaces/utils/IEscapeSequenceEncoder';
 
 /**
  * SelfDefendingTemplate. Enter code in infinity loop.

+ 0 - 0
src/templates/string-array-nodes/string-array-rotate-function-node/StringArrayRotateFunctionTemplate.ts → src/custom-code-helpers/string-array/templates/string-array-rotate-function/StringArrayRotateFunctionTemplate.ts


+ 0 - 0
src/templates/string-array-nodes/string-array-node/StringArrayTemplate.ts → src/custom-code-helpers/string-array/templates/string-array/StringArrayTemplate.ts


+ 11 - 40
src/custom-nodes/AbstractCustomNode.ts

@@ -5,30 +5,24 @@ import { TIdentifierNamesGeneratorFactory } from '../types/container/generators/
 import { TStatement } from '../types/node/TStatement';
 
 import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
+import { ICustomCodeHelperFormatter } from '../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
 import { IIdentifierNamesGenerator } from '../interfaces/generators/identifier-names-generators/IIdentifierNamesGenerator';
 import { IOptions } from '../interfaces/options/IOptions';
 import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../interfaces/custom-nodes/ICustomNodeFormatter';
-
-import { GlobalVariableTemplate1 } from '../templates/GlobalVariableTemplate1';
-import { GlobalVariableTemplate2 } from '../templates/GlobalVariableTemplate2';
 
 @injectable()
 export abstract class AbstractCustomNode <
     TInitialData extends any[] = any[]
 > implements ICustomNode <TInitialData> {
     /**
-     * @type {string[]}
+     * @type {TStatement[] | null}
      */
-    private static readonly globalVariableTemplateFunctions: string[] = [
-        GlobalVariableTemplate1(),
-        GlobalVariableTemplate2()
-    ];
+    protected cachedNode: TStatement[] | null = null;
 
     /**
-     * @type {TStatement[] | null}
+     * @type {ICustomCodeHelperFormatter}
      */
-    protected cachedNode: TStatement[] | null = null;
+    protected readonly customCodeHelperFormatter: ICustomCodeHelperFormatter;
 
     /**
      * @type {IIdentifierNamesGenerator}
@@ -45,26 +39,21 @@ export abstract class AbstractCustomNode <
      */
     protected readonly randomGenerator: IRandomGenerator;
 
-    /**
-     * @type {ICustomNodeFormatter}
-     */
-    protected readonly customNodeFormatter: ICustomNodeFormatter;
-
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     protected constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         this.identifierNamesGenerator = identifierNamesGeneratorFactory(options);
-        this.customNodeFormatter = customNodeFormatter;
+        this.customCodeHelperFormatter = customCodeHelperFormatter;
         this.randomGenerator = randomGenerator;
         this.options = options;
     }
@@ -74,32 +63,14 @@ export abstract class AbstractCustomNode <
      */
     public getNode (): TStatement[] {
         if (!this.cachedNode) {
-            const nodeTemplate: string = this.getNodeTemplate();
-
-            this.cachedNode = this.customNodeFormatter.formatStructure(
-                this.getNodeStructure(nodeTemplate)
+            this.cachedNode = this.customCodeHelperFormatter.formatStructure(
+                this.getNodeStructure()
             );
         }
 
         return this.cachedNode;
     }
 
-    /**
-     * @returns {string}
-     */
-    protected getGlobalVariableTemplate (): string {
-        return this.randomGenerator
-            .getRandomGenerator()
-            .pickone(AbstractCustomNode.globalVariableTemplateFunctions);
-    }
-
-    /**
-     * @returns {string}
-     */
-    protected getNodeTemplate (): string {
-        return '';
-    }
-
     /**
      * @param {TInitialData} args
      */
@@ -108,5 +79,5 @@ export abstract class AbstractCustomNode <
     /**
      * @returns {TStatement[]}
      */
-    protected abstract getNodeStructure (nodeTemplate: string): TStatement[];
+    protected abstract getNodeStructure (): TStatement[];
 }

+ 0 - 74
src/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.ts

@@ -1,74 +0,0 @@
-import { inject, injectable, } from 'inversify';
-import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
-
-import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
-import { TStatement } from '../../types/node/TStatement';
-
-import { IOptions } from '../../interfaces/options/IOptions';
-import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
-
-import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
-
-import { ConsoleOutputDisableExpressionTemplate } from '../../templates/console-output-nodes/console-output-disable-expression-node/ConsoleOutputDisableExpressionTemplate';
-import { GlobalVariableNoEvalTemplate } from '../../templates/GlobalVariableNoEvalTemplate';
-
-import { initializable } from '../../decorators/Initializable';
-
-import { AbstractCustomNode } from '../AbstractCustomNode';
-import { NodeUtils } from '../../node/NodeUtils';
-
-@injectable()
-export class ConsoleOutputDisableExpressionNode extends AbstractCustomNode {
-    /**
-     * @type {string}
-     */
-    @initializable()
-    private callsControllerFunctionName!: string;
-
-    /**
-     * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
-     * @param {IRandomGenerator} randomGenerator
-     * @param {IOptions} options
-     */
-    public constructor (
-        @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
-            identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
-        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions
-    ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
-    }
-
-    /**
-     * @param {string} callsControllerFunctionName
-     */
-    public initialize (callsControllerFunctionName: string): void {
-        this.callsControllerFunctionName = callsControllerFunctionName;
-    }
-
-    /**
-     * @param {string} nodeTemplate
-     * @returns {TStatement[]}
-     */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
-        return NodeUtils.convertCodeToStructure(nodeTemplate);
-    }
-
-    /**
-     * @returns {string}
-     */
-    protected getNodeTemplate (): string {
-        const globalVariableTemplate: string = this.options.target !== ObfuscationTarget.BrowserNoEval
-            ? this.getGlobalVariableTemplate()
-            : GlobalVariableNoEvalTemplate();
-
-        return this.customNodeFormatter.formatTemplate(ConsoleOutputDisableExpressionTemplate(), {
-            consoleLogDisableFunctionName: this.identifierNamesGenerator.generate(),
-            globalVariableTemplate,
-            singleNodeCallControllerFunctionName: this.callsControllerFunctionName
-        });
-    }
-}

+ 0 - 107
src/custom-nodes/console-output-nodes/group/ConsoleOutputCustomNodeGroup.ts

@@ -1,107 +0,0 @@
-import { inject, injectable, } from 'inversify';
-import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
-
-import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
-import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
-import { TInitialData } from '../../../types/TInitialData';
-import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
-
-import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
-import { IOptions } from '../../../interfaces/options/IOptions';
-import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { ICallsGraphData } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
-
-import { initializable } from '../../../decorators/Initializable';
-
-import { CustomNode } from '../../../enums/custom-nodes/CustomNode';
-import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent';
-
-import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
-import { ConsoleOutputDisableExpressionNode } from '../ConsoleOutputDisableExpressionNode';
-import { NodeAppender } from '../../../node/NodeAppender';
-import { NodeCallsControllerFunctionNode } from '../../node-calls-controller-nodes/NodeCallsControllerFunctionNode';
-
-@injectable()
-export class ConsoleOutputCustomNodeGroup extends AbstractCustomNodeGroup {
-    /**
-     * @type {ObfuscationEvent}
-     */
-    protected readonly appendEvent: ObfuscationEvent = ObfuscationEvent.BeforeObfuscation;
-
-    /**
-     * @type {Map<CustomNode, ICustomNode>}
-     */
-    @initializable()
-    protected customNodes!: Map <CustomNode, ICustomNode>;
-
-    /**
-     * @type {TCustomNodeFactory}
-     */
-    private readonly customNodeFactory: TCustomNodeFactory;
-
-    /**
-     * @param {TCustomNodeFactory} customNodeFactory
-     * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {IRandomGenerator} randomGenerator
-     * @param {IOptions} options
-     */
-    public constructor (
-        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
-        @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
-            identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions
-    ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
-
-        this.customNodeFactory = customNodeFactory;
-    }
-
-    /**
-     * @param {TNodeWithStatements} nodeWithStatements
-     * @param {ICallsGraphData[]} callsGraphData
-     */
-    public appendCustomNodes (nodeWithStatements: TNodeWithStatements, callsGraphData: ICallsGraphData[]): void {
-        const randomCallsGraphIndex: number = this.getRandomCallsGraphIndex(callsGraphData.length);
-
-        // consoleOutputDisableExpressionNode append
-        this.appendCustomNodeIfExist(CustomNode.ConsoleOutputDisableExpressionNode, (customNode: ICustomNode) => {
-            NodeAppender.appendToOptimalBlockScope(
-                callsGraphData,
-                nodeWithStatements,
-                customNode.getNode(),
-                randomCallsGraphIndex
-            );
-        });
-
-        // nodeCallsControllerFunctionNode append
-        this.appendCustomNodeIfExist(CustomNode.NodeCallsControllerFunctionNode, (customNode: ICustomNode) => {
-            const targetNodeWithStatements: TNodeWithStatements = callsGraphData.length
-                ? NodeAppender.getOptimalBlockScope(callsGraphData, randomCallsGraphIndex, 1)
-                : nodeWithStatements;
-
-            NodeAppender.prepend(targetNodeWithStatements, customNode.getNode());
-        });
-    }
-
-    public initialize (): void {
-        this.customNodes = new Map <CustomNode, ICustomNode>();
-
-        if (!this.options.disableConsoleOutput) {
-            return;
-        }
-
-        const callsControllerFunctionName: string = this.identifierNamesGenerator.generate();
-
-        const consoleOutputDisableExpressionNode: ICustomNode<TInitialData<ConsoleOutputDisableExpressionNode>> =
-            this.customNodeFactory(CustomNode.ConsoleOutputDisableExpressionNode);
-        const nodeCallsControllerFunctionNode: ICustomNode<TInitialData<NodeCallsControllerFunctionNode>> =
-            this.customNodeFactory(CustomNode.NodeCallsControllerFunctionNode);
-
-        consoleOutputDisableExpressionNode.initialize(callsControllerFunctionName);
-        nodeCallsControllerFunctionNode.initialize(this.appendEvent, callsControllerFunctionName);
-
-        this.customNodes.set(CustomNode.ConsoleOutputDisableExpressionNode, consoleOutputDisableExpressionNode);
-        this.customNodes.set(CustomNode.NodeCallsControllerFunctionNode, nodeCallsControllerFunctionNode);
-    }
-}

+ 10 - 6
src/custom-nodes/control-flow-flattening-nodes/BinaryExpressionFunctionNode.ts

@@ -6,9 +6,9 @@ import type { BinaryOperator } from 'estree';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { NodeFactory } from '../../node/NodeFactory';
@@ -23,18 +23,23 @@ export class BinaryExpressionFunctionNode extends AbstractCustomNode {
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            randomGenerator,
+            options
+        );
     }
 
     /**
@@ -45,10 +50,9 @@ export class BinaryExpressionFunctionNode extends AbstractCustomNode {
     }
 
     /**
-     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+    protected getNodeStructure (): TStatement[] {
         const structure: TStatement = NodeFactory.expressionStatementNode(
             NodeFactory.functionExpressionNode(
                 [

+ 10 - 6
src/custom-nodes/control-flow-flattening-nodes/BlockStatementControlFlowFlatteningNode.ts

@@ -6,9 +6,9 @@ import * as ESTree from 'estree';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { initializable } from '../../decorators/Initializable';
 
@@ -39,18 +39,23 @@ export class BlockStatementControlFlowFlatteningNode extends AbstractCustomNode
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            randomGenerator,
+            options
+        );
     }
 
     /**
@@ -69,10 +74,9 @@ export class BlockStatementControlFlowFlatteningNode extends AbstractCustomNode
     }
 
     /**
-     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+    protected getNodeStructure (): TStatement[] {
         const controllerIdentifierName: string = this.randomGenerator.getRandomString(6);
         const indexIdentifierName: string = this.randomGenerator.getRandomString(6);
         const structure: ESTree.BlockStatement = NodeFactory.blockStatementNode([

+ 10 - 6
src/custom-nodes/control-flow-flattening-nodes/CallExpressionFunctionNode.ts

@@ -6,9 +6,9 @@ import * as ESTree from 'estree';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { initializable } from '../../decorators/Initializable';
 
@@ -26,18 +26,23 @@ export class CallExpressionFunctionNode extends AbstractCustomNode {
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            randomGenerator,
+            options
+        );
     }
 
     /**
@@ -48,10 +53,9 @@ export class CallExpressionFunctionNode extends AbstractCustomNode {
     }
 
     /**
-     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+    protected getNodeStructure (): TStatement[] {
         const calleeIdentifier: ESTree.Identifier = NodeFactory.identifierNode('callee');
         const params: ESTree.Identifier[] = [];
         const argumentsLength: number = this.expressionArguments.length;

+ 10 - 6
src/custom-nodes/control-flow-flattening-nodes/LogicalExpressionFunctionNode.ts

@@ -6,9 +6,9 @@ import type { LogicalOperator } from 'estree';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { NodeFactory } from '../../node/NodeFactory';
@@ -23,18 +23,23 @@ export class LogicalExpressionFunctionNode extends AbstractCustomNode {
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            randomGenerator,
+            options
+        );
     }
 
     /**
@@ -45,10 +50,9 @@ export class LogicalExpressionFunctionNode extends AbstractCustomNode {
     }
 
     /**
-     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+    protected getNodeStructure (): TStatement[] {
         const structure: TStatement = NodeFactory.expressionStatementNode(
             NodeFactory.functionExpressionNode(
                 [

+ 10 - 6
src/custom-nodes/control-flow-flattening-nodes/StringLiteralNode.ts

@@ -4,9 +4,9 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { initializable } from '../../decorators/Initializable';
 
@@ -23,18 +23,23 @@ export class StringLiteralNode extends AbstractCustomNode {
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            randomGenerator,
+            options
+        );
     }
 
     /**
@@ -45,10 +50,9 @@ export class StringLiteralNode extends AbstractCustomNode {
     }
 
     /**
-     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+    protected getNodeStructure (): TStatement[] {
         const structure: TStatement = NodeFactory.expressionStatementNode(
             NodeFactory.literalNode(this.literalValue)
         );

+ 12 - 4
src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/CallExpressionControlFlowStorageCallNode.ts

@@ -6,9 +6,9 @@ import type * as ESTree from 'estree';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { initializable } from '../../../decorators/Initializable';
 
@@ -44,18 +44,23 @@ export class CallExpressionControlFlowStorageCallNode extends AbstractCustomNode
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            randomGenerator,
+            options
+        );
     }
 
     /**
@@ -76,6 +81,9 @@ export class CallExpressionControlFlowStorageCallNode extends AbstractCustomNode
         this.expressionArguments = expressionArguments;
     }
 
+    /**
+     * @returns {TStatement[]}
+     */
     protected getNodeStructure (): TStatement[] {
         const structure: TStatement = NodeFactory.expressionStatementNode(
             NodeFactory.callExpressionNode(

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

@@ -7,10 +7,10 @@ import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { initializable } from '../../../decorators/Initializable';
 
@@ -29,18 +29,23 @@ export class ControlFlowStorageNode extends AbstractCustomNode {
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            randomGenerator,
+            options
+        );
     }
 
     /**
@@ -51,10 +56,9 @@ export class ControlFlowStorageNode extends AbstractCustomNode {
     }
 
     /**
-     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+    protected getNodeStructure (): TStatement[] {
         const propertyNodes: ESTree.Property[] = Array
             .from<[string, ICustomNode]>(this.controlFlowStorage.getStorage())
             .map(([key, value]: [string, ICustomNode]) => {

+ 12 - 4
src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ExpressionWithOperatorControlFlowStorageCallNode.ts

@@ -6,9 +6,9 @@ import type { Expression } from 'estree';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { initializable } from '../../../decorators/Initializable';
 
@@ -42,18 +42,23 @@ export class ExpressionWithOperatorControlFlowStorageCallNode extends AbstractCu
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            randomGenerator,
+            options
+        );
     }
 
     /**
@@ -74,6 +79,9 @@ export class ExpressionWithOperatorControlFlowStorageCallNode extends AbstractCu
         this.rightValue = rightValue;
     }
 
+    /**
+     * @returns {TStatement[]}
+     */
     protected getNodeStructure (): TStatement[] {
         const structure: TStatement = NodeFactory.expressionStatementNode(
             NodeFactory.callExpressionNode(

+ 12 - 4
src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/StringLiteralControlFlowStorageCallNode.ts

@@ -4,9 +4,9 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { initializable } from '../../../decorators/Initializable';
 
@@ -30,18 +30,23 @@ export class StringLiteralControlFlowStorageCallNode extends AbstractCustomNode
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            randomGenerator,
+            options
+        );
     }
 
     /**
@@ -56,6 +61,9 @@ export class StringLiteralControlFlowStorageCallNode extends AbstractCustomNode
         this.controlFlowStorageKey = controlFlowStorageKey;
     }
 
+    /**
+     * @returns {TStatement[]}
+     */
     protected getNodeStructure (): TStatement[] {
         const structure: TStatement = NodeFactory.expressionStatementNode(
             NodeFactory.memberExpressionNode(

+ 10 - 6
src/custom-nodes/dead-code-injection-nodes/BlockStatementDeadCodeInjectionNode.ts

@@ -6,9 +6,9 @@ import type { BinaryOperator, BlockStatement } from 'estree';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { NodeFactory } from '../../node/NodeFactory';
@@ -28,18 +28,23 @@ export class BlockStatementDeadCodeInjectionNode extends AbstractCustomNode {
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            randomGenerator,
+            options
+        );
     }
 
     /**
@@ -55,10 +60,9 @@ export class BlockStatementDeadCodeInjectionNode extends AbstractCustomNode {
     }
 
     /**
-     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+    protected getNodeStructure (): TStatement[] {
         const random1: boolean = this.randomGenerator.getMathRandom() > 0.5;
         const random2: boolean = this.randomGenerator.getMathRandom() > 0.5;
 

+ 0 - 138
src/custom-nodes/debug-protection-nodes/group/DebugProtectionCustomNodeGroup.ts

@@ -1,138 +0,0 @@
-import { inject, injectable, } from 'inversify';
-import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
-
-import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
-import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
-import { TInitialData } from '../../../types/TInitialData';
-import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
-
-import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
-import { IOptions } from '../../../interfaces/options/IOptions';
-import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { ICallsGraphData } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
-
-import { initializable } from '../../../decorators/Initializable';
-
-import { CustomNode } from '../../../enums/custom-nodes/CustomNode';
-import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent';
-
-import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
-import { DebugProtectionFunctionNode } from '../DebugProtectionFunctionNode';
-import { DebugProtectionFunctionCallNode } from '../DebugProtectionFunctionCallNode';
-import { DebugProtectionFunctionIntervalNode } from '../DebugProtectionFunctionIntervalNode';
-import { NodeAppender } from '../../../node/NodeAppender';
-import { NodeCallsControllerFunctionNode } from '../../node-calls-controller-nodes/NodeCallsControllerFunctionNode';
-import { NodeGuards } from '../../../node/NodeGuards';
-
-@injectable()
-export class DebugProtectionCustomNodeGroup extends AbstractCustomNodeGroup {
-    /**
-     * @type {ObfuscationEvent}
-     */
-    protected readonly appendEvent: ObfuscationEvent = ObfuscationEvent.BeforeObfuscation;
-
-    /**
-     * @type {Map<CustomNode, ICustomNode>}
-     */
-    @initializable()
-    protected customNodes!: Map <CustomNode, ICustomNode>;
-
-    /**
-     * @type {TCustomNodeFactory}
-     */
-    private readonly customNodeFactory: TCustomNodeFactory;
-
-    /**
-     * @param {TCustomNodeFactory} customNodeFactory
-     * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {IRandomGenerator} randomGenerator
-     * @param {IOptions} options
-     */
-    public constructor (
-        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
-        @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
-            identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions
-    ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
-
-        this.customNodeFactory = customNodeFactory;
-    }
-
-    /**
-     * @param {TNodeWithStatements} nodeWithStatements
-     * @param {ICallsGraphData[]} callsGraphData
-     */
-    public appendCustomNodes (nodeWithStatements: TNodeWithStatements, callsGraphData: ICallsGraphData[]): void {
-        const randomCallsGraphIndex: number = this.getRandomCallsGraphIndex(callsGraphData.length);
-
-        // debugProtectionFunctionCallNode append
-        this.appendCustomNodeIfExist(CustomNode.DebugProtectionFunctionCallNode, (customNode: ICustomNode) => {
-            NodeAppender.appendToOptimalBlockScope(
-                callsGraphData,
-                nodeWithStatements,
-                customNode.getNode(),
-                randomCallsGraphIndex
-            );
-        });
-
-        // debugProtectionFunctionNode append
-        this.appendCustomNodeIfExist(CustomNode.DebugProtectionFunctionNode, (customNode: ICustomNode) => {
-            NodeAppender.append(nodeWithStatements, customNode.getNode());
-        });
-
-        // debugProtectionFunctionIntervalNode append
-        this.appendCustomNodeIfExist(CustomNode.DebugProtectionFunctionIntervalNode, (customNode: ICustomNode) => {
-            const programBodyLength: number = NodeGuards.isSwitchCaseNode(nodeWithStatements)
-                ? nodeWithStatements.consequent.length
-                : nodeWithStatements.body.length;
-            const randomIndex: number = this.randomGenerator.getRandomInteger(0, programBodyLength);
-
-            NodeAppender.insertAtIndex(nodeWithStatements, customNode.getNode(), randomIndex);
-        });
-
-        // nodeCallsControllerFunctionNode append
-        this.appendCustomNodeIfExist(CustomNode.NodeCallsControllerFunctionNode, (customNode: ICustomNode) => {
-            const targetNodeWithStatements: TNodeWithStatements = callsGraphData.length
-                ? NodeAppender.getOptimalBlockScope(callsGraphData, randomCallsGraphIndex, 1)
-                : nodeWithStatements;
-
-            NodeAppender.prepend(targetNodeWithStatements, customNode.getNode());
-        });
-    }
-
-    public initialize (): void {
-        this.customNodes = new Map <CustomNode, ICustomNode>();
-
-        if (!this.options.debugProtection) {
-            return;
-        }
-
-        const debugProtectionFunctionName: string = this.identifierNamesGenerator.generate();
-        const callsControllerFunctionName: string = this.identifierNamesGenerator.generate();
-
-        const debugProtectionFunctionNode: ICustomNode<TInitialData<DebugProtectionFunctionNode>> =
-            this.customNodeFactory(CustomNode.DebugProtectionFunctionNode);
-        const debugProtectionFunctionCallNode: ICustomNode<TInitialData<DebugProtectionFunctionCallNode>> =
-            this.customNodeFactory(CustomNode.DebugProtectionFunctionCallNode);
-        const debugProtectionFunctionIntervalNode: ICustomNode<TInitialData<DebugProtectionFunctionIntervalNode>> =
-            this.customNodeFactory(CustomNode.DebugProtectionFunctionIntervalNode);
-        const nodeCallsControllerFunctionNode: ICustomNode<TInitialData<NodeCallsControllerFunctionNode>> =
-            this.customNodeFactory(CustomNode.NodeCallsControllerFunctionNode);
-
-        debugProtectionFunctionNode.initialize(debugProtectionFunctionName);
-        debugProtectionFunctionCallNode.initialize(debugProtectionFunctionName, callsControllerFunctionName);
-        debugProtectionFunctionIntervalNode.initialize(debugProtectionFunctionName);
-        nodeCallsControllerFunctionNode.initialize(this.appendEvent, callsControllerFunctionName);
-
-        this.customNodes.set(CustomNode.DebugProtectionFunctionNode, debugProtectionFunctionNode);
-        this.customNodes.set(CustomNode.DebugProtectionFunctionCallNode, debugProtectionFunctionCallNode);
-
-        if (this.options.debugProtectionInterval) {
-            this.customNodes.set(CustomNode.DebugProtectionFunctionIntervalNode, debugProtectionFunctionIntervalNode);
-        }
-
-        this.customNodes.set(CustomNode.NodeCallsControllerFunctionNode, nodeCallsControllerFunctionNode);
-    }
-}

+ 0 - 107
src/custom-nodes/domain-lock-nodes/group/DomainLockCustomNodeGroup.ts

@@ -1,107 +0,0 @@
-import { inject, injectable, } from 'inversify';
-import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
-
-import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
-import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
-import { TInitialData } from '../../../types/TInitialData';
-import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
-
-import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
-import { IOptions } from '../../../interfaces/options/IOptions';
-import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { ICallsGraphData } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
-
-import { initializable } from '../../../decorators/Initializable';
-
-import { CustomNode } from '../../../enums/custom-nodes/CustomNode';
-import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent';
-
-import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
-import { DomainLockNode } from '../DomainLockNode';
-import { NodeAppender } from '../../../node/NodeAppender';
-import { NodeCallsControllerFunctionNode } from '../../node-calls-controller-nodes/NodeCallsControllerFunctionNode';
-
-@injectable()
-export class DomainLockCustomNodeGroup extends AbstractCustomNodeGroup {
-    /**
-     * @type {ObfuscationEvent}
-     */
-    protected readonly appendEvent: ObfuscationEvent = ObfuscationEvent.BeforeObfuscation;
-
-    /**
-     * @type {Map<CustomNode, ICustomNode>}
-     */
-    @initializable()
-    protected customNodes!: Map <CustomNode, ICustomNode>;
-
-    /**
-     * @type {TCustomNodeFactory}
-     */
-    private readonly customNodeFactory: TCustomNodeFactory;
-
-    /**
-     * @param {TCustomNodeFactory} customNodeFactory
-     * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {IRandomGenerator} randomGenerator
-     * @param {IOptions} options
-     */
-    public constructor (
-        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
-        @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
-            identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions
-    ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
-
-        this.customNodeFactory = customNodeFactory;
-    }
-
-    /**
-     * @param {TNodeWithStatements} nodeWithStatements
-     * @param {ICallsGraphData[]} callsGraphData
-     */
-    public appendCustomNodes (nodeWithStatements: TNodeWithStatements, callsGraphData: ICallsGraphData[]): void {
-        const randomCallsGraphIndex: number = this.getRandomCallsGraphIndex(callsGraphData.length);
-
-        // domainLockNode append
-        this.appendCustomNodeIfExist(CustomNode.DomainLockNode, (customNode: ICustomNode) => {
-            NodeAppender.appendToOptimalBlockScope(
-                callsGraphData,
-                nodeWithStatements,
-                customNode.getNode(),
-                randomCallsGraphIndex
-            );
-        });
-
-        // nodeCallsControllerFunctionNode append
-        this.appendCustomNodeIfExist(CustomNode.NodeCallsControllerFunctionNode, (customNode: ICustomNode) => {
-            const targetNodeWithStatements: TNodeWithStatements = callsGraphData.length
-                ? NodeAppender.getOptimalBlockScope(callsGraphData, randomCallsGraphIndex, 1)
-                : nodeWithStatements;
-
-            NodeAppender.prepend(targetNodeWithStatements, customNode.getNode());
-        });
-    }
-
-    public initialize (): void {
-        this.customNodes = new Map <CustomNode, ICustomNode>();
-
-        if (!this.options.domainLock.length) {
-            return;
-        }
-
-        const callsControllerFunctionName: string = this.identifierNamesGenerator.generate();
-
-        const domainLockNode: ICustomNode<TInitialData<DomainLockNode>> =
-            this.customNodeFactory(CustomNode.DomainLockNode);
-        const nodeCallsControllerFunctionNode: ICustomNode<TInitialData<NodeCallsControllerFunctionNode>> =
-            this.customNodeFactory(CustomNode.NodeCallsControllerFunctionNode);
-
-        domainLockNode.initialize(callsControllerFunctionName);
-        nodeCallsControllerFunctionNode.initialize(this.appendEvent, callsControllerFunctionName);
-
-        this.customNodes.set(CustomNode.DomainLockNode, domainLockNode);
-        this.customNodes.set(CustomNode.NodeCallsControllerFunctionNode, nodeCallsControllerFunctionNode);
-    }
-}

+ 23 - 10
src/custom-nodes/object-expression-keys-transformer-nodes/ObjectExpressionVariableDeclarationHostNode.ts

@@ -4,17 +4,23 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import * as ESTree from 'estree';
 
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
+import { TNodeWithLexicalScope } from '../../types/node/TNodeWithLexicalScope';
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { NodeFactory } from '../../node/NodeFactory';
+import { NodeGuards } from '../../node/NodeGuards';
 
 @injectable()
 export class ObjectExpressionVariableDeclarationHostNode extends AbstractCustomNode {
+    /**
+     * @type {TNodeWithLexicalScope}
+     */
+    private lexicalScopeNode!: TNodeWithLexicalScope;
     /**
      * @ type {Property}
      */
@@ -22,35 +28,42 @@ export class ObjectExpressionVariableDeclarationHostNode extends AbstractCustomN
 
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ICustomNodeFormatter} customNodeFormatter
+     * @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      */
     public constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
+        @inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
+        super(
+            identifierNamesGeneratorFactory,
+            customCodeHelperFormatter,
+            randomGenerator,
+            options
+        );
     }
 
-    public initialize (properties: ESTree.Property[]): void {
+    public initialize (lexicalScopeNode: TNodeWithLexicalScope, properties: ESTree.Property[]): void {
+        this.lexicalScopeNode = lexicalScopeNode;
         this.properties = properties;
     }
 
     /**
-     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      */
-    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+    protected getNodeStructure (): TStatement[] {
+        const variableDeclarationName: string = NodeGuards.isProgramNode(this.lexicalScopeNode)
+            ? this.identifierNamesGenerator.generateForGlobalScope()
+            : this.identifierNamesGenerator.generateForLexicalScope(this.lexicalScopeNode);
+
         const structure: TStatement = NodeFactory.variableDeclarationNode(
             [
                 NodeFactory.variableDeclaratorNode(
-                    NodeFactory.identifierNode(
-                        this.identifierNamesGenerator.generate()
-                    ),
+                    NodeFactory.identifierNode(variableDeclarationName),
                     NodeFactory.objectExpressionNode(this.properties)
                 )
             ],

+ 0 - 107
src/custom-nodes/self-defending-nodes/group/SelfDefendingCustomNodeGroup.ts

@@ -1,107 +0,0 @@
-import { inject, injectable, } from 'inversify';
-import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
-
-import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
-import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
-import { TInitialData } from '../../../types/TInitialData';
-import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
-
-import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
-import { IOptions } from '../../../interfaces/options/IOptions';
-import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { ICallsGraphData } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
-
-import { initializable } from '../../../decorators/Initializable';
-
-import { CustomNode } from '../../../enums/custom-nodes/CustomNode';
-import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent';
-
-import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
-import { NodeAppender } from '../../../node/NodeAppender';
-import { NodeCallsControllerFunctionNode } from '../../node-calls-controller-nodes/NodeCallsControllerFunctionNode';
-import { SelfDefendingUnicodeNode } from '../SelfDefendingUnicodeNode';
-
-@injectable()
-export class SelfDefendingCustomNodeGroup extends AbstractCustomNodeGroup {
-    /**
-     * @type {ObfuscationEvent}
-     */
-    protected appendEvent: ObfuscationEvent = ObfuscationEvent.AfterObfuscation;
-
-    /**
-     * @type {Map<CustomNode, ICustomNode>}
-     */
-    @initializable()
-    protected customNodes!: Map <CustomNode, ICustomNode>;
-
-    /**
-     * @type {TCustomNodeFactory}
-     */
-    private readonly customNodeFactory: TCustomNodeFactory;
-
-    /**
-     * @param {TCustomNodeFactory} customNodeFactory
-     * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {IRandomGenerator} randomGenerator
-     * @param {IOptions} options
-     */
-    public constructor (
-        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
-        @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
-            identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions
-    ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
-
-        this.customNodeFactory = customNodeFactory;
-    }
-
-    /**
-     * @param {TNodeWithStatements} nodeWithStatements
-     * @param {ICallsGraphData[]} callsGraphData
-     */
-    public appendCustomNodes (nodeWithStatements: TNodeWithStatements, callsGraphData: ICallsGraphData[]): void {
-        const randomCallsGraphIndex: number = this.getRandomCallsGraphIndex(callsGraphData.length);
-
-        // selfDefendingUnicodeNode append
-        this.appendCustomNodeIfExist(CustomNode.SelfDefendingUnicodeNode, (customNode: ICustomNode) => {
-            NodeAppender.appendToOptimalBlockScope(
-                callsGraphData,
-                nodeWithStatements,
-                customNode.getNode(),
-                randomCallsGraphIndex
-            );
-        });
-
-        // nodeCallsControllerFunctionNode append
-        this.appendCustomNodeIfExist(CustomNode.NodeCallsControllerFunctionNode, (customNode: ICustomNode) => {
-            const targetNodeWithStatements: TNodeWithStatements = callsGraphData.length
-                ? NodeAppender.getOptimalBlockScope(callsGraphData, randomCallsGraphIndex, 1)
-                : nodeWithStatements;
-
-            NodeAppender.prepend(targetNodeWithStatements, customNode.getNode());
-        });
-    }
-
-    public initialize (): void {
-        this.customNodes = new Map <CustomNode, ICustomNode>();
-
-        if (!this.options.selfDefending) {
-            return;
-        }
-
-        const callsControllerFunctionName: string = this.identifierNamesGenerator.generate();
-
-        const selfDefendingUnicodeNode: ICustomNode<TInitialData<SelfDefendingUnicodeNode>> =
-            this.customNodeFactory(CustomNode.SelfDefendingUnicodeNode);
-        const nodeCallsControllerFunctionNode: ICustomNode<TInitialData<NodeCallsControllerFunctionNode>> =
-            this.customNodeFactory(CustomNode.NodeCallsControllerFunctionNode);
-
-        selfDefendingUnicodeNode.initialize(callsControllerFunctionName);
-        nodeCallsControllerFunctionNode.initialize(this.appendEvent, callsControllerFunctionName);
-
-        this.customNodes.set(CustomNode.SelfDefendingUnicodeNode, selfDefendingUnicodeNode);
-        this.customNodes.set(CustomNode.NodeCallsControllerFunctionNode, nodeCallsControllerFunctionNode);
-    }
-}

+ 0 - 124
src/custom-nodes/string-array-nodes/group/StringArrayCustomNodeGroup.ts

@@ -1,124 +0,0 @@
-import { inject, injectable, } from 'inversify';
-import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
-
-import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
-import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
-import { TInitialData } from '../../../types/TInitialData';
-import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
-
-import { ICallsGraphData } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
-import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
-import { IOptions } from '../../../interfaces/options/IOptions';
-import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { IStringArrayStorage } from '../../../interfaces/storages/string-array-storage/IStringArrayStorage';
-
-import { initializable } from '../../../decorators/Initializable';
-
-import { CustomNode } from '../../../enums/custom-nodes/CustomNode';
-import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent';
-
-import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
-import { NodeAppender } from '../../../node/NodeAppender';
-import { StringArrayNode } from '../StringArrayNode';
-import { StringArrayCallsWrapper } from '../StringArrayCallsWrapper';
-import { StringArrayRotateFunctionNode } from '../StringArrayRotateFunctionNode';
-
-@injectable()
-export class StringArrayCustomNodeGroup extends AbstractCustomNodeGroup {
-    /**
-     * @type {ObfuscationEvent}
-     */
-    protected appendEvent: ObfuscationEvent = ObfuscationEvent.AfterObfuscation;
-
-    /**
-     * @type {Map<CustomNode, ICustomNode>}
-     */
-    @initializable()
-    protected customNodes!: Map <CustomNode, ICustomNode>;
-
-    /**
-     * @type {TCustomNodeFactory}
-     */
-    private readonly customNodeFactory: TCustomNodeFactory;
-
-    /**
-     * @type {IStringArrayStorage}
-     */
-    private readonly stringArrayStorage: IStringArrayStorage;
-
-    /**
-     * @param {TCustomNodeFactory} customNodeFactory
-     * @param {IStringArrayStorage} stringArrayStorage
-     * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {IRandomGenerator} randomGenerator
-     * @param {IOptions} options
-     */
-    public constructor (
-        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
-        @inject(ServiceIdentifiers.IStringArrayStorage) stringArrayStorage: IStringArrayStorage,
-        @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
-            identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions
-    ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
-
-        this.customNodeFactory = customNodeFactory;
-        this.stringArrayStorage = stringArrayStorage;
-    }
-
-    /**
-     * @param {TNodeWithStatements} nodeWithStatements
-     * @param {ICallsGraphData[]} callsGraphData
-     */
-    public appendCustomNodes (nodeWithStatements: TNodeWithStatements, callsGraphData: ICallsGraphData[]): void {
-        if (!this.stringArrayStorage.getLength()) {
-            return;
-        }
-
-        // stringArrayNode append
-        this.appendCustomNodeIfExist(CustomNode.StringArrayNode, (customNode: ICustomNode) => {
-            NodeAppender.prepend(nodeWithStatements, customNode.getNode());
-        });
-
-        // stringArrayCallsWrapper append
-        this.appendCustomNodeIfExist(CustomNode.StringArrayCallsWrapper, (customNode: ICustomNode) => {
-            NodeAppender.insertAtIndex(nodeWithStatements, customNode.getNode(), 1);
-        });
-
-        // stringArrayRotateFunctionNode append
-        this.appendCustomNodeIfExist(CustomNode.StringArrayRotateFunctionNode, (customNode: ICustomNode) => {
-            NodeAppender.insertAtIndex(nodeWithStatements, customNode.getNode(), 1);
-        });
-    }
-
-    public initialize (): void {
-        this.customNodes = new Map <CustomNode, ICustomNode>();
-
-        if (!this.options.stringArray) {
-            return;
-        }
-
-        const stringArrayNode: ICustomNode<TInitialData<StringArrayNode>> =
-            this.customNodeFactory(CustomNode.StringArrayNode);
-        const stringArrayCallsWrapper: ICustomNode<TInitialData<StringArrayCallsWrapper>> =
-            this.customNodeFactory(CustomNode.StringArrayCallsWrapper);
-        const stringArrayRotateFunctionNode: ICustomNode<TInitialData<StringArrayRotateFunctionNode>> =
-            this.customNodeFactory(CustomNode.StringArrayRotateFunctionNode);
-
-        const stringArrayName: string = this.stringArrayStorage.getStorageName();
-        const stringArrayCallsWrapperName: string = this.stringArrayStorage.getStorageCallsWrapperName();
-        const stringArrayRotationAmount: number = this.stringArrayStorage.getRotationAmount();
-
-        stringArrayNode.initialize(this.stringArrayStorage, stringArrayName);
-        stringArrayCallsWrapper.initialize(stringArrayName, stringArrayCallsWrapperName);
-        stringArrayRotateFunctionNode.initialize(stringArrayName, stringArrayRotationAmount);
-
-        this.customNodes.set(CustomNode.StringArrayNode, stringArrayNode);
-        this.customNodes.set(CustomNode.StringArrayCallsWrapper, stringArrayCallsWrapper);
-
-        if (this.options.rotateStringArray) {
-            this.customNodes.set(CustomNode.StringArrayRotateFunctionNode, stringArrayRotateFunctionNode);
-        }
-    }
-}

+ 8 - 0
src/declarations/environment.d.ts

@@ -0,0 +1,8 @@
+/* eslint-disable */
+
+declare namespace NodeJS {
+    export interface ProcessEnv {
+        VERSION?: string;
+        BUILD_TIMESTAMP?: string;
+    }
+}

+ 12 - 0
src/enums/custom-code-helpers/CustomCodeHelper.ts

@@ -0,0 +1,12 @@
+export enum CustomCodeHelper {
+    CallsControllerFunction = 'CallsControllerFunction',
+    ConsoleOutputDisable = 'ConsoleOutputDisable',
+    DebugProtectionFunctionCall = 'DebugProtectionFunctionCall',
+    DebugProtectionFunctionInterval = 'DebugProtectionFunctionInterval',
+    DebugProtectionFunction = 'DebugProtectionFunction',
+    DomainLock = 'DomainLock',
+    SelfDefendingUnicode = 'SelfDefendingUnicode',
+    StringArrayCallsWrapper = 'StringArrayCallsWrapper',
+    StringArray = 'StringArray',
+    StringArrayRotateFunction = 'StringArrayRotateFunction'
+}

+ 7 - 0
src/enums/custom-code-helpers/CustomCodeHelperGroup.ts

@@ -0,0 +1,7 @@
+export enum CustomCodeHelperGroup {
+    ConsoleOutput = 'ConsoleOutput',
+    DebugProtection = 'DebugProtection',
+    DomainLock = 'DomainLock',
+    SelfDefending = 'SelfDefending',
+    StringArray = 'StringArray'
+}

+ 0 - 12
src/enums/custom-nodes/CustomNode.ts

@@ -1,12 +0,0 @@
-export enum CustomNode {
-    ConsoleOutputDisableExpressionNode = 'ConsoleOutputDisableExpressionNode',
-    DebugProtectionFunctionCallNode = 'DebugProtectionFunctionCallNode',
-    DebugProtectionFunctionIntervalNode = 'DebugProtectionFunctionIntervalNode',
-    DebugProtectionFunctionNode = 'DebugProtectionFunctionNode',
-    DomainLockNode = 'DomainLockNode',
-    NodeCallsControllerFunctionNode = 'NodeCallsControllerFunctionNode',
-    SelfDefendingUnicodeNode = 'SelfDefendingUnicodeNode',
-    StringArrayCallsWrapper = 'StringArrayCallsWrapper',
-    StringArrayNode = 'StringArrayNode',
-    StringArrayRotateFunctionNode = 'StringArrayRotateFunctionNode'
-}

+ 0 - 7
src/enums/custom-nodes/CustomNodeGroup.ts

@@ -1,7 +0,0 @@
-export enum CustomNodeGroup {
-    ConsoleOutputCustomNodeGroup = 'ConsoleOutputCustomNodeGroup',
-    DebugProtectionCustomNodeGroup = 'DebugProtectionCustomNodeGroup',
-    DomainLockCustomNodeGroup = 'DomainLockCustomNodeGroup',
-    SelfDefendingCustomNodeGroup = 'SelfDefendingCustomNodeGroup',
-    StringArrayCustomNodeGroup = 'StringArrayCustomNodeGroup'
-}

+ 1 - 1
src/enums/node-transformers/NodeTransformer.ts

@@ -1,7 +1,7 @@
 export enum NodeTransformer {
     BlockStatementControlFlowTransformer = 'BlockStatementControlFlowTransformer',
     CommentsTransformer = 'CommentsTransformer',
-    CustomNodesTransformer = 'CustomNodesTransformer',
+    CustomCodeHelpersTransformer = 'CustomCodeHelpersTransformer',
     DeadCodeInjectionTransformer = 'DeadCodeInjectionTransformer',
     EvalCallExpressionTransformer = 'EvalCallExpressionTransformer',
     FunctionControlFlowTransformer = 'FunctionControlFlowTransformer',

+ 67 - 2
src/generators/identifier-names-generators/AbstractIdentifierNamesGenerator.ts

@@ -1,10 +1,14 @@
 import { inject, injectable } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
+import { TNodeWithLexicalScope } from '../../types/node/TNodeWithLexicalScope';
+
 import { IIdentifierNamesGenerator } from '../../interfaces/generators/identifier-names-generators/IIdentifierNamesGenerator';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
+import { NodeGuards } from '../../node/NodeGuards';
+
 @injectable()
 export abstract class AbstractIdentifierNamesGenerator implements IIdentifierNamesGenerator {
     /**
@@ -22,6 +26,11 @@ export abstract class AbstractIdentifierNamesGenerator implements IIdentifierNam
      */
     protected readonly preservedNamesSet: Set<string> = new Set();
 
+    /**
+     * @type {Map<TNodeWithLexicalScope, Set<string>>}
+     */
+    protected readonly lexicalScopesPreservedNamesMap: Map<TNodeWithLexicalScope, Set<string>> = new Map();
+
     /**
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
@@ -34,14 +43,37 @@ export abstract class AbstractIdentifierNamesGenerator implements IIdentifierNam
         this.options = options;
     }
 
+    /**
+     * @param {TNodeWithLexicalScope} lexicalScopeNode
+     * @param {number} nameLength
+     * @returns {string}
+     */
+    public generate (lexicalScopeNode: TNodeWithLexicalScope, nameLength?: number): string {
+        return NodeGuards.isProgramNode(lexicalScopeNode)
+            ? this.generateForGlobalScope()
+            : this.generateForLexicalScope(lexicalScopeNode);
+    }
+
     /**
      * @param {string} name
-     * @returns {void}
      */
     public preserveName (name: string): void {
         this.preservedNamesSet.add(name);
     }
 
+    /**
+     * @param {string} name
+     * @param {TNodeWithLexicalScope} lexicalScopeNode
+     */
+    public preserveNameForLexicalScope (name: string, lexicalScopeNode: TNodeWithLexicalScope): void {
+        const preservedNamesForLexicalScopeSet: Set<string> =
+            this.lexicalScopesPreservedNamesMap.get(lexicalScopeNode) ?? new Set();
+
+        preservedNamesForLexicalScopeSet.add(name);
+
+        this.lexicalScopesPreservedNamesMap.set(lexicalScopeNode, preservedNamesForLexicalScopeSet);
+    }
+
     /**
      * @param {string} name
      * @returns {boolean}
@@ -50,6 +82,32 @@ export abstract class AbstractIdentifierNamesGenerator implements IIdentifierNam
         return this.notReservedName(name) && !this.preservedNamesSet.has(name);
     }
 
+    /**
+     * @param {string} name
+     * @param {TNodeWithLexicalScope[]} lexicalScopeNodes
+     * @returns {boolean}
+     */
+    public isValidIdentifierNameInLexicalScopes (name: string, lexicalScopeNodes: TNodeWithLexicalScope[]): boolean {
+        if (!this.isValidIdentifierName(name)) {
+            return false;
+        }
+
+        for (const lexicalScope of lexicalScopeNodes) {
+            const preservedNamesForLexicalScopeSet: Set<string> | null =
+                this.lexicalScopesPreservedNamesMap.get(lexicalScope) ?? null;
+
+            if (!preservedNamesForLexicalScopeSet) {
+                continue;
+            }
+
+            if (preservedNamesForLexicalScopeSet.has(name)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
     /**
      * @param {string} name
      * @returns {boolean}
@@ -67,7 +125,14 @@ export abstract class AbstractIdentifierNamesGenerator implements IIdentifierNam
      * @param {number} nameLength
      * @returns {string}
      */
-    public abstract generate (nameLength?: number): string;
+    public abstract generateForGlobalScope (nameLength?: number): string;
+
+    /**
+     * @param {TNodeWithLexicalScope} lexicalScopeNode
+     * @param {number} nameLength
+     * @returns {string}
+     */
+    public abstract generateForLexicalScope (lexicalScopeNode: TNodeWithLexicalScope, nameLength?: number): string;
 
     /**
      * @param {number} nameLength

+ 59 - 13
src/generators/identifier-names-generators/DictionaryIdentifierNamesGenerator.ts

@@ -6,6 +6,8 @@ import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
 import { AbstractIdentifierNamesGenerator } from './AbstractIdentifierNamesGenerator';
+import { TNodeWithLexicalScope } from '../../types/node/TNodeWithLexicalScope';
+import { NodeLexicalScopeUtils } from '../../node/NodeLexicalScopeUtils';
 
 @injectable()
 export class DictionaryIdentifierNamesGenerator extends AbstractIdentifierNamesGenerator {
@@ -67,21 +69,32 @@ export class DictionaryIdentifierNamesGenerator extends AbstractIdentifierNamesG
         return null;
     }
 
-    public generate (): string {
-        if (!this.identifierNamesSet.size) {
-            throw new Error('Too many identifiers in the code, add more words to identifiers dictionary');
-        }
+    public generateForGlobalScope (): string {
+        const identifierName: string = this.generateNewDictionaryName();
 
-        const iteratorResult: IteratorResult<string> = this.identifiersIterator.next();
+        this.preserveName(identifierName);
 
-        if (!iteratorResult.done) {
-            return iteratorResult.value;
+        return identifierName;
+    }
+
+    /**
+     * @param {TNodeWithLexicalScope} lexicalScopeNode
+     * @returns {string}
+     */
+    public generateForLexicalScope (lexicalScopeNode: TNodeWithLexicalScope): string {
+        const lexicalScopes: TNodeWithLexicalScope[] = [
+            lexicalScopeNode,
+            ...NodeLexicalScopeUtils.getLexicalScopes(lexicalScopeNode)
+        ];
+        const identifierName: string = this.generateNewDictionaryName();
+
+        if (!this.isValidIdentifierNameInLexicalScopes(identifierName, lexicalScopes)) {
+            return this.generateForLexicalScope(lexicalScopeNode);
         }
 
-        this.identifierNamesSet = new Set(this.getIncrementedIdentifierNames([...this.identifierNamesSet]));
-        this.identifiersIterator = this.identifierNamesSet.values();
+        this.preserveNameForLexicalScope(identifierName, lexicalScopeNode);
 
-        return this.generate();
+        return identifierName;
     }
 
     /**
@@ -89,11 +102,44 @@ export class DictionaryIdentifierNamesGenerator extends AbstractIdentifierNamesG
      */
     public generateWithPrefix (): string {
         const prefix: string = this.options.identifiersPrefix ?
-            `${this.options.identifiersPrefix}_`
+            `${this.options.identifiersPrefix}`
             : '';
-        const identifierName: string = this.generate();
+        const identifierName: string = this.generateNewDictionaryName();
+        const identifierNameWithPrefix: string = `${prefix}${identifierName}`;
+
+        if (!this.isValidIdentifierName(identifierNameWithPrefix)) {
+            return this.generateWithPrefix();
+        }
+
+        this.preserveName(identifierNameWithPrefix);
+
+        return identifierNameWithPrefix;
+    }
+
+    /**
+     * @returns {string}
+     */
+    private generateNewDictionaryName (): string {
+        if (!this.identifierNamesSet.size) {
+            throw new Error('Too many identifiers in the code, add more words to identifiers dictionary');
+        }
+
+        const iteratorResult: IteratorResult<string> = this.identifiersIterator.next();
+
+        if (!iteratorResult.done) {
+            const identifierName: string =iteratorResult.value;
+
+            if (!this.isValidIdentifierName(identifierName)) {
+                return this.generateNewDictionaryName();
+            }
+
+            return iteratorResult.value;
+        }
+
+        this.identifierNamesSet = new Set(this.getIncrementedIdentifierNames([...this.identifierNamesSet]));
+        this.identifiersIterator = this.identifierNamesSet.values();
 
-        return `${prefix}${identifierName}`.replace('__', '_');
+        return this.generateNewDictionaryName();
     }
 
     /**

+ 16 - 10
src/generators/identifier-names-generators/HexadecimalIdentifierNamesGenerator.ts

@@ -1,6 +1,8 @@
 import { inject, injectable } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
+import { TNodeWithLexicalScope } from '../../types/node/TNodeWithLexicalScope';
+
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
@@ -15,11 +17,6 @@ export class HexadecimalIdentifierNamesGenerator extends AbstractIdentifierNames
      */
     private static readonly baseIdentifierNameLength: number = 6;
 
-    /**
-     * @type {Set<string>}
-     */
-    private readonly randomVariableNameSet: Set <string> = new Set();
-
     /**
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
@@ -35,7 +32,7 @@ export class HexadecimalIdentifierNamesGenerator extends AbstractIdentifierNames
      * @param {number} nameLength
      * @returns {string}
      */
-    public generate (nameLength?: number): string {
+    public generateForGlobalScope (nameLength?: number): string {
         const rangeMinInteger: number = 10000;
         const rangeMaxInteger: number = 99_999_999;
         const randomInteger: number = this.randomGenerator.getRandomInteger(rangeMinInteger, rangeMaxInteger);
@@ -47,21 +44,30 @@ export class HexadecimalIdentifierNamesGenerator extends AbstractIdentifierNames
         const baseIdentifierName: string = hexadecimalNumber.substr(0, baseNameLength);
         const identifierName: string = `_${Utils.hexadecimalPrefix}${baseIdentifierName}`;
 
-        if (this.randomVariableNameSet.has(identifierName)) {
-            return this.generate(nameLength);
+        if (!this.isValidIdentifierName(identifierName)) {
+            return this.generateForGlobalScope(nameLength);
         }
 
-        this.randomVariableNameSet.add(identifierName);
+        this.preserveName(identifierName);
 
         return identifierName;
     }
 
+    /**
+     * @param {TNodeWithLexicalScope} lexicalScopeNode
+     * @param {number} nameLength
+     * @returns {string}
+     */
+    public generateForLexicalScope (lexicalScopeNode: TNodeWithLexicalScope, nameLength?: number): string {
+        return this.generateForGlobalScope(nameLength);
+    }
+
     /**
      * @param {number} nameLength
      * @returns {string}
      */
     public generateWithPrefix (nameLength?: number): string {
-        const identifierName: string = this.generate(nameLength);
+        const identifierName: string = this.generateForGlobalScope(nameLength);
 
         return `${this.options.identifiersPrefix}${identifierName}`.replace('__', '_');
     }

+ 67 - 4
src/generators/identifier-names-generators/MangledIdentifierNamesGenerator.ts

@@ -1,10 +1,13 @@
 import { inject, injectable } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
+import { TNodeWithLexicalScope } from '../../types/node/TNodeWithLexicalScope';
+
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
 import { AbstractIdentifierNamesGenerator } from './AbstractIdentifierNamesGenerator';
+import { NodeLexicalScopeUtils } from '../../node/NodeLexicalScopeUtils';
 
 @injectable()
 export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGenerator {
@@ -13,6 +16,11 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene
      */
     private static readonly initMangledNameCharacter: string = '9';
 
+    /**
+     * @type {Map<TNodeWithLexicalScope, string>}
+     */
+    private static readonly lastMangledNameInScopeMap: Map <TNodeWithLexicalScope, string> = new Map();
+
     /**
      * @type {string[]}
      */
@@ -50,10 +58,37 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene
      * @param {number} nameLength
      * @returns {string}
      */
-    public generate (nameLength?: number): string {
+    public generateForGlobalScope (nameLength?: number): string {
         const identifierName: string = this.generateNewMangledName(this.previousMangledName);
 
         this.previousMangledName = identifierName;
+        this.preserveName(identifierName);
+
+        return identifierName;
+    }
+
+    /**
+     * @param {TNodeWithLexicalScope} lexicalScopeNode
+     * @param {number} nameLength
+     * @returns {string}
+     */
+    public generateForLexicalScope (lexicalScopeNode: TNodeWithLexicalScope, nameLength?: number): string {
+        const lexicalScopes: TNodeWithLexicalScope[] = [
+            lexicalScopeNode,
+            ...NodeLexicalScopeUtils.getLexicalScopes(lexicalScopeNode)
+        ];
+
+        const lastMangledNameForScope: string = this.getLastMangledNameForScopes(lexicalScopes);
+
+        let identifierName: string = lastMangledNameForScope;
+
+        do {
+            identifierName = this.generateNewMangledName(identifierName);
+        } while (!this.isValidIdentifierNameInLexicalScopes(identifierName, lexicalScopes));
+
+        MangledIdentifierNamesGenerator.lastMangledNameInScopeMap.set(lexicalScopeNode, identifierName);
+
+        this.preserveNameForLexicalScope(identifierName, lexicalScopeNode);
 
         return identifierName;
     }
@@ -64,11 +99,20 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene
      */
     public generateWithPrefix (nameLength?: number): string {
         const prefix: string = this.options.identifiersPrefix ?
-            `${this.options.identifiersPrefix}_`
+            `${this.options.identifiersPrefix}`
             : '';
-        const identifierName: string = this.generate(nameLength);
+        const identifierName: string = this.generateNewMangledName(this.previousMangledName);
+        const identifierNameWithPrefix: string = `${prefix}${identifierName}`;
+
+        this.previousMangledName = identifierName;
 
-        return `${prefix}${identifierName}`;
+        if (!this.isValidIdentifierName(identifierNameWithPrefix)) {
+            return this.generateWithPrefix(nameLength);
+        }
+
+        this.preserveName(identifierNameWithPrefix);
+
+        return identifierNameWithPrefix;
     }
 
     /**
@@ -124,4 +168,23 @@ export class MangledIdentifierNamesGenerator extends AbstractIdentifierNamesGene
 
         return newMangledName;
     }
+
+    /**
+     * @param {TNodeWithLexicalScope[]} lexicalScopeNodes
+     * @returns {string}
+     */
+    private getLastMangledNameForScopes (lexicalScopeNodes: TNodeWithLexicalScope[]): string {
+        for (const lexicalScope of lexicalScopeNodes) {
+            const lastMangledName: string | null = MangledIdentifierNamesGenerator.lastMangledNameInScopeMap
+                .get(lexicalScope) ?? null;
+
+            if (!lastMangledName) {
+                continue;
+            }
+
+            return lastMangledName;
+        }
+
+        return MangledIdentifierNamesGenerator.initMangledNameCharacter;
+    }
 }

+ 0 - 11
src/interfaces/IASTParserFacadeInputData.ts

@@ -1,11 +0,0 @@
-export interface IASTParserFacadeInputData {
-    /**
-     * @type {string}
-     */
-    sourceCode: string;
-
-    /**
-     * @type {string}
-     */
-    inputFilePath?: string;
-}

+ 12 - 0
src/interfaces/custom-code-helpers/ICustomCodeHelper.ts

@@ -0,0 +1,12 @@
+import { TStatement } from '../../types/node/TStatement';
+
+import { IInitializable } from '../IInitializable';
+
+export interface ICustomCodeHelper <
+    TInitialData extends any[] = any[]
+> extends IInitializable<TInitialData> {
+    /**
+     * @returns ESTree.Node[]
+     */
+    getNode (): TStatement[];
+}

+ 1 - 1
src/interfaces/custom-nodes/ICustomNodeFormatter.ts → src/interfaces/custom-code-helpers/ICustomCodeHelperFormatter.ts

@@ -1,7 +1,7 @@
 import { TObject } from '../../types/TObject';
 import { TStatement } from '../../types/node/TStatement';
 
-export interface ICustomNodeFormatter {
+export interface ICustomCodeHelperFormatter {
     /**
      * @param {string} template
      * @param {TMapping} mapping

+ 6 - 6
src/interfaces/custom-nodes/ICustomNodeGroup.ts → src/interfaces/custom-code-helpers/ICustomCodeHelperGroup.ts

@@ -1,18 +1,18 @@
 import { TNodeWithStatements } from '../../types/node/TNodeWithStatements';
 
-import { ICustomNode } from './ICustomNode';
+import { ICustomCodeHelper } from './ICustomCodeHelper';
 import { IInitializable } from '../IInitializable';
 import { ICallsGraphData } from '../analyzers/calls-graph-analyzer/ICallsGraphData';
 
-import { CustomNode } from '../../enums/custom-nodes/CustomNode';
+import { CustomCodeHelper } from '../../enums/custom-code-helpers/CustomCodeHelper';
 import { ObfuscationEvent } from '../../enums/event-emitters/ObfuscationEvent';
 
-export interface ICustomNodeGroup extends IInitializable {
+export interface ICustomCodeHelperGroup extends IInitializable {
     /**
      * @param nodeWithStatements
      * @param callsGraphData
      */
-    appendCustomNodes (nodeWithStatements: TNodeWithStatements, callsGraphData: ICallsGraphData[]): void;
+    appendNodes (nodeWithStatements: TNodeWithStatements, callsGraphData: ICallsGraphData[]): void;
 
     /**
      * @returns {ObfuscationEvent}
@@ -20,9 +20,9 @@ export interface ICustomNodeGroup extends IInitializable {
     getAppendEvent (): ObfuscationEvent;
 
     /**
-     * @type {Map <CustomNode, ICustomNode>}
+     * @type {Map <CustomCodeHelper, ICustomCodeHelper>}
      */
-    getCustomNodes (): Map <CustomNode, ICustomNode>;
+    getCustomCodeHelpers (): Map <CustomCodeHelper, ICustomCodeHelper>;
 
     initialize (): void;
 }

+ 10 - 0
src/interfaces/custom-code-helpers/ICustomCodeHelperObfuscator.ts

@@ -0,0 +1,10 @@
+import { TInputOptions } from '../../types/options/TInputOptions';
+
+export interface ICustomCodeHelperObfuscator {
+    /**
+     * @param {string} template
+     * @param {TInputOptions} additionalOptions
+     * @returns {string}
+     */
+    obfuscateTemplate (template: string, additionalOptions?: TInputOptions): string;
+}

+ 33 - 3
src/interfaces/generators/identifier-names-generators/IIdentifierNamesGenerator.ts

@@ -1,9 +1,26 @@
+import { TNodeWithLexicalScope } from '../../../types/node/TNodeWithLexicalScope';
+
 export interface IIdentifierNamesGenerator {
     /**
+     * @param {TNodeWithLexicalScope} lexicalScopeNode
+     * @param {number} nameLength
+     * @returns {string}
+     */
+    generate (lexicalScopeNode: TNodeWithLexicalScope, nameLength?: number): string;
+
+    /**
+     * @param {number} nameLength
+     * @returns {string}
+     */
+    generateForGlobalScope (nameLength?: number): string;
+
+    /**
+     * @param {TNodeWithLexicalScope} lexicalScopeNode
      * @param {number} nameLength
      * @returns {string}
      */
-    generate (nameLength?: number): string;
+    generateForLexicalScope (lexicalScopeNode: TNodeWithLexicalScope, nameLength?: number): string;
+
 
     /**
      * @param {number} nameLength
@@ -18,7 +35,20 @@ export interface IIdentifierNamesGenerator {
     isValidIdentifierName (identifierName: string): boolean;
 
     /**
-     * @param {string} name
+     * @param {string} identifierName
+     * @param {TNodeWithLexicalScope[]} lexicalScopeNodes
+     * @returns {boolean}
+     */
+    isValidIdentifierNameInLexicalScopes (identifierName: string, lexicalScopeNodes: TNodeWithLexicalScope[]): boolean;
+
+    /**
+     * @param {string} identifierName
+     */
+    preserveName (identifierName: string): void;
+
+    /**
+     * @param {string} identifierName
+     * @param {TNodeWithLexicalScope} lexicalScope
      */
-    preserveName (name: string): void;
+    preserveNameForLexicalScope (identifierName: string, lexicalScope: TNodeWithLexicalScope): void;
 }

+ 8 - 2
src/interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/IIdentifierObfuscatingReplacer.ts

@@ -18,7 +18,13 @@ export interface IIdentifierObfuscatingReplacer extends IObfuscatingReplacer <ES
     storeLocalName (identifierNode: ESTree.Identifier, lexicalScopeNode: TNodeWithLexicalScope): void;
 
     /**
-     * @param {string} name
+     * @param {Identifier} identifierNode
+     */
+    preserveName (identifierNode: ESTree.Identifier): void;
+
+    /**
+     * @param {Identifier} identifierNode
+     * @param {TNodeWithLexicalScope} lexicalScopeNode
      */
-    preserveName (name: string): void;
+    preserveNameForLexicalScope (identifierNode: ESTree.Identifier, lexicalScopeNode: TNodeWithLexicalScope): void;
 }

+ 17 - 0
src/interfaces/node/IScopeIdentifiersTraverser.ts

@@ -0,0 +1,17 @@
+import * as ESTree from 'estree';
+
+import { TScopeIdentifiersTraverserCallback } from '../../types/node/TScopeIdentifiersTraverserCallback';
+
+export interface IScopeIdentifiersTraverser {
+    /**
+     * @param {Program} programNode
+     * @param {Node | null} parentNode
+     * @param {TScopeIdentifiersTraverserCallback} callback
+     */
+    traverse (
+        programNode: ESTree.Program,
+        parentNode: ESTree.Node | null,
+        callback: TScopeIdentifiersTraverserCallback
+    ): void;
+
+}

+ 11 - 0
src/interfaces/node/IScopeIdentifiersTraverserCallbackData.ts

@@ -0,0 +1,11 @@
+import * as eslintScope from 'eslint-scope';
+
+import { TNodeWithLexicalScope } from '../../types/node/TNodeWithLexicalScope';
+
+export interface IScopeIdentifiersTraverserCallbackData {
+    isGlobalDeclaration: boolean;
+    rootScope: eslintScope.Scope;
+    variable: eslintScope.Variable;
+    variableLexicalScopeNode: TNodeWithLexicalScope;
+    variableScope: eslintScope.Scope;
+}

+ 0 - 1
src/interfaces/options/IOptions.ts

@@ -20,7 +20,6 @@ export interface IOptions {
     readonly identifiersDictionary: string[];
     readonly identifiersPrefix: string;
     readonly inputFileName: string;
-    readonly inputFilePath: string;
     readonly log: boolean;
     readonly renameGlobals: boolean;
     readonly reservedNames: string[];

+ 2 - 0
src/interfaces/utils/IRandomGenerator.ts

@@ -1,3 +1,5 @@
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-ignore
 import type * as Chance from 'chance';
 
 export interface IRandomGenerator {

+ 24 - 3
src/node-transformers/converting-transformers/ObjectExpressionKeysTransformer.ts

@@ -58,9 +58,13 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
         hostStatement: ESTree.Statement
     ): boolean {
         return ObjectExpressionKeysTransformer.isReferencedIdentifierName(
-            objectExpressionNode,
-            hostStatement
-        );
+                objectExpressionNode,
+                hostStatement
+            )
+            || ObjectExpressionKeysTransformer.isProhibitedSequenceExpression(
+                objectExpressionNode,
+                hostStatement
+            );
     }
 
     /**
@@ -110,6 +114,23 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
         return isReferencedIdentifierName;
     }
 
+    /**
+     * @param {ObjectExpression} objectExpressionNode
+     * @param {Node} hostNode
+     * @returns {boolean}
+     */
+    private static isProhibitedSequenceExpression (
+        objectExpressionNode: ESTree.ObjectExpression,
+        hostNode: ESTree.Node,
+    ): boolean {
+        return NodeGuards.isExpressionStatementNode(hostNode)
+            && NodeGuards.isSequenceExpressionNode(hostNode.expression)
+            && hostNode.expression.expressions.some((expressionNode: ESTree.Expression) =>
+                NodeGuards.isCallExpressionNode(expressionNode)
+                && NodeGuards.isSuperNode(expressionNode.callee)
+            );
+    }
+
     /**
      * @param {TransformationStage} transformationStage
      * @returns {IVisitor | null}

+ 24 - 7
src/node-transformers/converting-transformers/object-expression-extractors/ObjectExpressionToVariableDeclarationExtractor.ts

@@ -19,6 +19,8 @@ import { NodeAppender } from '../../../node/NodeAppender';
 import { NodeGuards } from '../../../node/NodeGuards';
 import { NodeStatementUtils } from '../../../node/NodeStatementUtils';
 import { NodeUtils } from '../../../node/NodeUtils';
+import { TNodeWithLexicalScope } from '../../../types/node/TNodeWithLexicalScope';
+import { NodeLexicalScopeUtils } from '../../../node/NodeLexicalScopeUtils';
 
 @injectable()
 export class ObjectExpressionToVariableDeclarationExtractor implements IObjectExpressionExtractor {
@@ -74,19 +76,30 @@ export class ObjectExpressionToVariableDeclarationExtractor implements IObjectEx
         objectExpressionNode: ESTree.ObjectExpression,
         hostStatement: ESTree.Statement
     ): IObjectExpressionExtractorResult {
-        const properties: ESTree.Property[] = objectExpressionNode.properties;
+        const hostNodeWithStatements: TNodeWithStatements = NodeStatementUtils.getScopeOfNode(hostStatement);
+        const lexicalScopeNode: TNodeWithLexicalScope | null = NodeGuards.isNodeWithLexicalScope(hostNodeWithStatements)
+            ? hostNodeWithStatements
+            : NodeLexicalScopeUtils.getLexicalScope(hostNodeWithStatements) ?? null;
 
-        const newObjectExpressionHostStatement: ESTree.VariableDeclaration = this.getObjectExpressionHostNode(properties);
-        const newObjectExpressionIdentifier: ESTree.Identifier = this.getObjectExpressionIdentifierNode(newObjectExpressionHostStatement);
-        const newObjectExpressionNode: ESTree.ObjectExpression = this.getObjectExpressionNode(newObjectExpressionHostStatement);
+        if (!lexicalScopeNode) {
+            throw new Error('Cannot find lexical scope node for the host statement node');
+        }
+
+        const properties: ESTree.Property[] = objectExpressionNode.properties;
 
+        const newObjectExpressionHostStatement: ESTree.VariableDeclaration = this.getObjectExpressionHostNode(
+            lexicalScopeNode,
+            properties
+        );
         const statementsToInsert: TStatement[] = [newObjectExpressionHostStatement];
-        const hostNodeWithStatements: TNodeWithStatements = NodeStatementUtils.getScopeOfNode(hostStatement);
 
         NodeAppender.insertBefore(hostNodeWithStatements, statementsToInsert, hostStatement);
         NodeUtils.parentizeAst(newObjectExpressionHostStatement);
         NodeUtils.parentizeNode(newObjectExpressionHostStatement, hostNodeWithStatements);
 
+        const newObjectExpressionIdentifier: ESTree.Identifier = this.getObjectExpressionIdentifierNode(newObjectExpressionHostStatement);
+        const newObjectExpressionNode: ESTree.ObjectExpression = this.getObjectExpressionNode(newObjectExpressionHostStatement);
+
         return {
             nodeToReplace: newObjectExpressionIdentifier,
             objectExpressionHostStatement: newObjectExpressionHostStatement,
@@ -95,16 +108,20 @@ export class ObjectExpressionToVariableDeclarationExtractor implements IObjectEx
     }
 
     /**
+     * @param {TNodeWithLexicalScope} lexicalScopeNode
      * @param {Property[]} properties
      * @returns {VariableDeclaration}
      */
-    private getObjectExpressionHostNode (properties: ESTree.Property[]): ESTree.VariableDeclaration {
+    private getObjectExpressionHostNode (
+        lexicalScopeNode: TNodeWithLexicalScope,
+        properties: ESTree.Property[]
+    ): ESTree.VariableDeclaration {
         const variableDeclarationHostNodeCustomNode: ICustomNode<TInitialData<ObjectExpressionVariableDeclarationHostNode>> =
             this.objectExpressionKeysTransformerCustomNodeFactory(
                 ObjectExpressionKeysTransformerCustomNode.ObjectExpressionVariableDeclarationHostNode
             );
 
-        variableDeclarationHostNodeCustomNode.initialize(properties);
+        variableDeclarationHostNodeCustomNode.initialize(lexicalScopeNode, properties);
 
         const statementNode: TStatement = variableDeclarationHostNodeCustomNode.getNode()[0];
 

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

@@ -351,17 +351,22 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
      */
     private makeClonedBlockStatementNodeUnique (clonedBlockStatementNode: ESTree.BlockStatement): ESTree.BlockStatement {
         // should wrap cloned block statement node into function node for correct scope encapsulation
-        const hostNode: ESTree.FunctionExpression = NodeFactory
-            .functionExpressionNode([], clonedBlockStatementNode);
+        const hostNode: ESTree.Program = NodeFactory.programNode([
+            NodeFactory.expressionStatementNode(
+                NodeFactory.functionExpressionNode([], clonedBlockStatementNode)
+            )
+        ]);
 
+        NodeUtils.parentizeAst(hostNode);
         NodeUtils.parentizeNode(hostNode, hostNode);
-        NodeUtils.parentizeNode(clonedBlockStatementNode, hostNode);
 
-        return this.transformersRunner.transform(
+        this.transformersRunner.transform(
             hostNode,
             DeadCodeInjectionTransformer.transformersToRenameBlockScopeIdentifiers,
             TransformationStage.Obfuscating
-        ).body;
+        );
+
+        return clonedBlockStatementNode;
     }
 
     /**

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików