Browse Source

Merge pull request #491 from javascript-obfuscator/prevailing-kind-of-variables-control-flow-fix

Fixed `TypeError: Assignment to constant variable`
Timofey Kachalov 5 years ago
parent
commit
7658c28957
48 changed files with 476 additions and 277 deletions
  1. 4 0
      CHANGELOG.md
  2. 0 0
      dist/index.browser.js
  3. 0 0
      dist/index.cli.js
  4. 0 0
      dist/index.js
  5. 1 1
      package.json
  6. 1 1
      src/container/ServiceIdentifiers.ts
  7. 10 3
      src/container/modules/custom-nodes/CustomNodesModule.ts
  8. 0 7
      src/container/modules/utils/UtilsModule.ts
  9. 19 8
      src/custom-nodes/AbstractCustomNode.ts
  10. 65 0
      src/custom-nodes/CustomNodeFormatter.ts
  11. 9 8
      src/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.ts
  12. 6 5
      src/custom-nodes/control-flow-flattening-nodes/BinaryExpressionFunctionNode.ts
  13. 14 19
      src/custom-nodes/control-flow-flattening-nodes/BlockStatementControlFlowFlatteningNode.ts
  14. 6 5
      src/custom-nodes/control-flow-flattening-nodes/CallExpressionFunctionNode.ts
  15. 6 5
      src/custom-nodes/control-flow-flattening-nodes/LogicalExpressionFunctionNode.ts
  16. 6 5
      src/custom-nodes/control-flow-flattening-nodes/StringLiteralNode.ts
  17. 4 4
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/CallExpressionControlFlowStorageCallNode.ts
  18. 8 18
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ControlFlowStorageNode.ts
  19. 4 4
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ExpressionWithOperatorControlFlowStorageCallNode.ts
  20. 4 4
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/StringLiteralControlFlowStorageCallNode.ts
  21. 6 5
      src/custom-nodes/dead-code-injection-nodes/BlockStatementDeadCodeInjectionNode.ts
  22. 9 8
      src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionCallNode.ts
  23. 9 8
      src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionIntervalNode.ts
  24. 9 8
      src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionNode.ts
  25. 9 8
      src/custom-nodes/domain-lock-nodes/DomainLockNode.ts
  26. 10 9
      src/custom-nodes/node-calls-controller-nodes/NodeCallsControllerFunctionNode.ts
  27. 8 20
      src/custom-nodes/object-expression-keys-transformer-nodes/BasePropertiesExtractorObjectExpressionHostNode.ts
  28. 9 8
      src/custom-nodes/self-defending-nodes/SelfDefendingUnicodeNode.ts
  29. 13 12
      src/custom-nodes/string-array-nodes/StringArrayCallsWrapper.ts
  30. 9 8
      src/custom-nodes/string-array-nodes/StringArrayNode.ts
  31. 10 9
      src/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.ts
  32. 20 0
      src/interfaces/custom-nodes/ICustomNodeFormatter.d.ts
  33. 0 13
      src/interfaces/utils/ITemplateFormatter.d.ts
  34. 0 53
      src/utils/TemplateFormatter.ts
  35. 24 4
      test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/BlockStatementControlFlowTransformer.spec.ts
  36. 1 1
      test/functional-tests/node-transformers/control-flow-transformers/function-control-flow-transformer/FunctionControlFlowTransformer.spec.ts
  37. 1 1
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/ObjectExpressionKeysTransformer.spec.ts
  38. 3 1
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/prevailing-kind-of-variables-const.js
  39. 3 1
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/prevailing-kind-of-variables-let.js
  40. 3 1
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/prevailing-kind-of-variables-var.js
  41. 98 0
      test/functional-tests/templates/domain-lock-nodes/DomainLockNodeTemplate.spec.ts
  42. 1 0
      test/functional-tests/templates/domain-lock-nodes/fixtures/prevailing-kind-of-variables-const.js
  43. 1 0
      test/functional-tests/templates/domain-lock-nodes/fixtures/prevailing-kind-of-variables-let.js
  44. 1 0
      test/functional-tests/templates/domain-lock-nodes/fixtures/prevailing-kind-of-variables-var.js
  45. 12 0
      test/functional-tests/templates/string-array-nodes/string-array-calls-wrapper-node-template/StringArrayCallsWrapperNodeTemplate.spec.ts
  46. 12 0
      test/functional-tests/templates/string-array-nodes/string-array-rotate-function-template/StringArrayRotateFunctionTemplate.spec.ts
  47. 12 0
      test/functional-tests/templates/string-array-nodes/string-array-template/StringArrayTemplate.spec.ts
  48. 16 2
      test/runtime-tests/JavaScriptObfuscatorRuntime.spec.ts

+ 4 - 0
CHANGELOG.md

@@ -1,5 +1,9 @@
 Change Log
 Change Log
 
 
+v0.22.1
+---
+* Fixed `TypeError: Assignment to constant variable` when auto-detection of kind of variables is inserted `const` variables for `controlFlowStorage` nodes
+
 v0.22.0
 v0.22.0
 ---
 ---
 * **Breaking:** auto-detection of kind of variables of inserted nodes, based on most prevailing kind of variables of source code
 * **Breaking:** auto-detection of kind of variables of inserted nodes, based on most prevailing kind of variables of source code

File diff suppressed because it is too large
+ 0 - 0
dist/index.browser.js


File diff suppressed because it is too large
+ 0 - 0
dist/index.cli.js


File diff suppressed because it is too large
+ 0 - 0
dist/index.js


+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "javascript-obfuscator",
   "name": "javascript-obfuscator",
-  "version": "0.22.0",
+  "version": "0.22.1",
   "description": "JavaScript obfuscator",
   "description": "JavaScript obfuscator",
   "keywords": [
   "keywords": [
     "obfuscator",
     "obfuscator",

+ 1 - 1
src/container/ServiceIdentifiers.ts

@@ -21,6 +21,7 @@ export enum ServiceIdentifiers {
     ICustomNode = 'ICustomNode',
     ICustomNode = 'ICustomNode',
     ICustomNodeGroup = 'ICustomNodeGroup',
     ICustomNodeGroup = 'ICustomNodeGroup',
     IControlFlowReplacer = 'IControlFlowReplacer',
     IControlFlowReplacer = 'IControlFlowReplacer',
+    ICustomNodeFormatter = 'ICustomNodeFormatter',
     IEscapeSequenceEncoder = 'IEscapeSequenceEncoder',
     IEscapeSequenceEncoder = 'IEscapeSequenceEncoder',
     IIdentifierNamesGenerator = 'IIdentifierNamesGenerator',
     IIdentifierNamesGenerator = 'IIdentifierNamesGenerator',
     IIdentifierObfuscatingReplacer = 'IIdentifierObfuscatingReplacer',
     IIdentifierObfuscatingReplacer = 'IIdentifierObfuscatingReplacer',
@@ -40,7 +41,6 @@ export enum ServiceIdentifiers {
     IRandomGenerator = 'IRandomGenerator',
     IRandomGenerator = 'IRandomGenerator',
     ISourceCode = 'ISourceCode',
     ISourceCode = 'ISourceCode',
     ISourceMapCorrector = 'ISourceMapCorrector',
     ISourceMapCorrector = 'ISourceMapCorrector',
-    ITemplateFormatter = 'ITemplateFormatter',
     ITransformersRunner = 'ITransformersRunner',
     ITransformersRunner = 'ITransformersRunner',
     Newable__ICustomNode = 'Newable<ICustomNode>',
     Newable__ICustomNode = 'Newable<ICustomNode>',
     Newable__TControlFlowStorage = 'Newable<TControlFlowStorage>',
     Newable__TControlFlowStorage = 'Newable<TControlFlowStorage>',

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

@@ -3,6 +3,7 @@ import { ContainerModule, interfaces } from 'inversify';
 import { ServiceIdentifiers } from '../../ServiceIdentifiers';
 import { ServiceIdentifiers } from '../../ServiceIdentifiers';
 
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
+import { ICustomNodeFormatter } from '../../../interfaces/custom-nodes/ICustomNodeFormatter';
 import { ICustomNodeGroup } from '../../../interfaces/custom-nodes/ICustomNodeGroup';
 import { ICustomNodeGroup } from '../../../interfaces/custom-nodes/ICustomNodeGroup';
 
 
 import { ControlFlowCustomNode } from "../../../enums/custom-nodes/ControlFlowCustomNode";
 import { ControlFlowCustomNode } from "../../../enums/custom-nodes/ControlFlowCustomNode";
@@ -25,6 +26,7 @@ import { CallExpressionControlFlowStorageCallNode } from '../../../custom-nodes/
 import { CallExpressionFunctionNode } from '../../../custom-nodes/control-flow-flattening-nodes/CallExpressionFunctionNode';
 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 { ControlFlowStorageNode } from '../../../custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ControlFlowStorageNode';
 import { ConsoleOutputDisableExpressionNode } from '../../../custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode';
 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 { DebugProtectionFunctionCallNode } from '../../../custom-nodes/debug-protection-nodes/DebugProtectionFunctionCallNode';
 import { DebugProtectionFunctionIntervalNode } from '../../../custom-nodes/debug-protection-nodes/DebugProtectionFunctionIntervalNode';
 import { DebugProtectionFunctionIntervalNode } from '../../../custom-nodes/debug-protection-nodes/DebugProtectionFunctionIntervalNode';
 import { DebugProtectionFunctionNode } from '../../../custom-nodes/debug-protection-nodes/DebugProtectionFunctionNode';
 import { DebugProtectionFunctionNode } from '../../../custom-nodes/debug-protection-nodes/DebugProtectionFunctionNode';
@@ -160,7 +162,7 @@ export const customNodesModule: interfaces.ContainerModule = new ContainerModule
             .getConstructorFactory<ControlFlowCustomNode, ICustomNode>(
             .getConstructorFactory<ControlFlowCustomNode, ICustomNode>(
                 ServiceIdentifiers.Newable__ICustomNode,
                 ServiceIdentifiers.Newable__ICustomNode,
                 ServiceIdentifiers.Factory__IIdentifierNamesGenerator,
                 ServiceIdentifiers.Factory__IIdentifierNamesGenerator,
-                ServiceIdentifiers.ITemplateFormatter,
+                ServiceIdentifiers.ICustomNodeFormatter,
                 ServiceIdentifiers.IRandomGenerator,
                 ServiceIdentifiers.IRandomGenerator,
                 ServiceIdentifiers.IOptions,
                 ServiceIdentifiers.IOptions,
                 ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer
                 ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer
@@ -172,7 +174,7 @@ export const customNodesModule: interfaces.ContainerModule = new ContainerModule
             .getConstructorFactory<DeadCodeInjectionCustomNode, ICustomNode>(
             .getConstructorFactory<DeadCodeInjectionCustomNode, ICustomNode>(
                 ServiceIdentifiers.Newable__ICustomNode,
                 ServiceIdentifiers.Newable__ICustomNode,
                 ServiceIdentifiers.Factory__IIdentifierNamesGenerator,
                 ServiceIdentifiers.Factory__IIdentifierNamesGenerator,
-                ServiceIdentifiers.ITemplateFormatter,
+                ServiceIdentifiers.ICustomNodeFormatter,
                 ServiceIdentifiers.IRandomGenerator,
                 ServiceIdentifiers.IRandomGenerator,
                 ServiceIdentifiers.IOptions
                 ServiceIdentifiers.IOptions
             ));
             ));
@@ -183,7 +185,7 @@ export const customNodesModule: interfaces.ContainerModule = new ContainerModule
             .getConstructorFactory<ObjectExpressionKeysTransformerCustomNode, ICustomNode>(
             .getConstructorFactory<ObjectExpressionKeysTransformerCustomNode, ICustomNode>(
                 ServiceIdentifiers.Newable__ICustomNode,
                 ServiceIdentifiers.Newable__ICustomNode,
                 ServiceIdentifiers.Factory__IIdentifierNamesGenerator,
                 ServiceIdentifiers.Factory__IIdentifierNamesGenerator,
-                ServiceIdentifiers.ITemplateFormatter,
+                ServiceIdentifiers.ICustomNodeFormatter,
                 ServiceIdentifiers.IRandomGenerator,
                 ServiceIdentifiers.IRandomGenerator,
                 ServiceIdentifiers.IOptions,
                 ServiceIdentifiers.IOptions,
                 ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer
                 ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer
@@ -193,4 +195,9 @@ export const customNodesModule: interfaces.ContainerModule = new ContainerModule
     bind<ICustomNodeGroup>(ServiceIdentifiers.Factory__ICustomNodeGroup)
     bind<ICustomNodeGroup>(ServiceIdentifiers.Factory__ICustomNodeGroup)
         .toFactory<ICustomNodeGroup>(InversifyContainerFacade
         .toFactory<ICustomNodeGroup>(InversifyContainerFacade
             .getFactory<CustomNodeGroup, ICustomNodeGroup>(ServiceIdentifiers.ICustomNodeGroup));
             .getFactory<CustomNodeGroup, ICustomNodeGroup>(ServiceIdentifiers.ICustomNodeGroup));
+
+    // custom node formatter
+    bind<ICustomNodeFormatter>(ServiceIdentifiers.ICustomNodeFormatter)
+        .to(CustomNodeFormatter)
+        .inSingletonScope();
 });
 });

+ 0 - 7
src/container/modules/utils/UtilsModule.ts

@@ -7,7 +7,6 @@ import { IEscapeSequenceEncoder } from '../../../interfaces/utils/IEscapeSequenc
 import { ILevelledTopologicalSorter } from '../../../interfaces/utils/ILevelledTopologicalSorter';
 import { ILevelledTopologicalSorter } from '../../../interfaces/utils/ILevelledTopologicalSorter';
 import { INodeTransformerNamesGroupsBuilder } from '../../../interfaces/utils/INodeTransformerNamesGroupsBuilder';
 import { INodeTransformerNamesGroupsBuilder } from '../../../interfaces/utils/INodeTransformerNamesGroupsBuilder';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../../interfaces/utils/ITemplateFormatter';
 
 
 import { ArrayUtils } from '../../../utils/ArrayUtils';
 import { ArrayUtils } from '../../../utils/ArrayUtils';
 import { CryptUtils } from '../../../utils/CryptUtils';
 import { CryptUtils } from '../../../utils/CryptUtils';
@@ -15,7 +14,6 @@ import { EscapeSequenceEncoder } from '../../../utils/EscapeSequenceEncoder';
 import { LevelledTopologicalSorter } from '../../../utils/LevelledTopologicalSorter';
 import { LevelledTopologicalSorter } from '../../../utils/LevelledTopologicalSorter';
 import { NodeTransformerNamesGroupsBuilder } from '../../../utils/NodeTransformerNamesGroupsBuilder';
 import { NodeTransformerNamesGroupsBuilder } from '../../../utils/NodeTransformerNamesGroupsBuilder';
 import { RandomGenerator } from '../../../utils/RandomGenerator';
 import { RandomGenerator } from '../../../utils/RandomGenerator';
-import { TemplateFormatter } from '../../../utils/TemplateFormatter';
 
 
 export const utilsModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
 export const utilsModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
     // array utils
     // array utils
@@ -46,9 +44,4 @@ export const utilsModule: interfaces.ContainerModule = new ContainerModule((bind
     bind<INodeTransformerNamesGroupsBuilder>(ServiceIdentifiers.INodeTransformerNamesGroupsBuilder)
     bind<INodeTransformerNamesGroupsBuilder>(ServiceIdentifiers.INodeTransformerNamesGroupsBuilder)
         .to(NodeTransformerNamesGroupsBuilder)
         .to(NodeTransformerNamesGroupsBuilder)
         .inSingletonScope();
         .inSingletonScope();
-
-    // template formatter
-    bind<ITemplateFormatter>(ServiceIdentifiers.ITemplateFormatter)
-        .to(TemplateFormatter)
-        .inSingletonScope();
 });
 });

+ 19 - 8
src/custom-nodes/AbstractCustomNode.ts

@@ -8,7 +8,7 @@ import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
 import { IIdentifierNamesGenerator } from '../interfaces/generators/identifier-names-generators/IIdentifierNamesGenerator';
 import { IIdentifierNamesGenerator } from '../interfaces/generators/identifier-names-generators/IIdentifierNamesGenerator';
 import { IOptions } from '../interfaces/options/IOptions';
 import { IOptions } from '../interfaces/options/IOptions';
 import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { GlobalVariableTemplate1 } from '../templates/GlobalVariableTemplate1';
 import { GlobalVariableTemplate1 } from '../templates/GlobalVariableTemplate1';
 import { GlobalVariableTemplate2 } from '../templates/GlobalVariableTemplate2';
 import { GlobalVariableTemplate2 } from '../templates/GlobalVariableTemplate2';
@@ -46,25 +46,25 @@ export abstract class AbstractCustomNode <
     protected readonly randomGenerator: IRandomGenerator;
     protected readonly randomGenerator: IRandomGenerator;
 
 
     /**
     /**
-     * @type {ITemplateFormatter}
+     * @type {ICustomNodeFormatter}
      */
      */
-    protected readonly templateFormatter: ITemplateFormatter;
+    protected readonly customNodeFormatter: ICustomNodeFormatter;
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
     protected constructor (
     protected constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
         this.identifierNamesGenerator = identifierNamesGeneratorFactory(options);
         this.identifierNamesGenerator = identifierNamesGeneratorFactory(options);
-        this.templateFormatter = templateFormatter;
+        this.customNodeFormatter = customNodeFormatter;
         this.randomGenerator = randomGenerator;
         this.randomGenerator = randomGenerator;
         this.options = options;
         this.options = options;
     }
     }
@@ -79,7 +79,11 @@ export abstract class AbstractCustomNode <
      */
      */
     public getNode (): TStatement[] {
     public getNode (): TStatement[] {
         if (!this.cachedNode) {
         if (!this.cachedNode) {
-            this.cachedNode = this.getNodeStructure();
+            const nodeTemplate: string = this.getNodeTemplate();
+
+            this.cachedNode = this.customNodeFormatter.formatStructure(
+                this.getNodeStructure(nodeTemplate)
+            );
         }
         }
 
 
         return this.cachedNode;
         return this.cachedNode;
@@ -97,5 +101,12 @@ export abstract class AbstractCustomNode <
     /**
     /**
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected abstract getNodeStructure (): TStatement[];
+    protected abstract getNodeStructure (nodeTemplate: string): TStatement[];
+
+    /**
+     * @returns {string}
+     */
+    protected getNodeTemplate (): string {
+        return '';
+    }
 }
 }

+ 65 - 0
src/custom-nodes/CustomNodeFormatter.ts

@@ -0,0 +1,65 @@
+import { inject, injectable } from 'inversify';
+import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
+
+import * as estraverse from 'estraverse';
+import * as ESTree from 'estree';
+import format from 'string-template';
+
+import { TObject } from '../types/TObject';
+import { TStatement } from '../types/node/TStatement';
+
+import { ICustomNodeFormatter } from '../interfaces/custom-nodes/ICustomNodeFormatter';
+import { IPrevailingKindOfVariablesAnalyzer } from '../interfaces/analyzers/calls-graph-analyzer/IPrevailingKindOfVariablesAnalyzer';
+
+import { NodeGuards } from '../node/NodeGuards';
+
+@injectable()
+export class CustomNodeFormatter implements ICustomNodeFormatter {
+    /**
+     * @type {ESTree.VariableDeclaration['kind']}
+     */
+    private readonly prevailingKindOfVariables: ESTree.VariableDeclaration['kind'];
+
+    constructor (
+        @inject(ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer)
+            prevailingKindOfVariablesAnalyzer: IPrevailingKindOfVariablesAnalyzer
+    ) {
+        this.prevailingKindOfVariables = prevailingKindOfVariablesAnalyzer.getPrevailingKind();
+    }
+
+    /**
+     * @param {string} template
+     * @param {TMapping} mapping
+     * @returns {string}
+     */
+    public formatTemplate <TMapping extends TObject> (
+        template: string,
+        mapping: TMapping
+    ): string {
+        return format(template, mapping);
+    }
+
+    /**
+     * @param {TStatement[]} statements
+     * @returns {TStatement[]}
+     */
+    public formatStructure (statements: TStatement[]): TStatement[] {
+        for (const statement of statements) {
+            estraverse.replace(statement, {
+                enter: (node: ESTree.Node): ESTree.Node | void => {
+                    if (!NodeGuards.isVariableDeclarationNode(node)) {
+                        return;
+                    }
+
+                    if (this.prevailingKindOfVariables === 'var') {
+                        node.kind = 'var';
+                    }
+
+                    return node;
+                }
+            });
+        }
+
+        return statements;
+    }
+}

+ 9 - 8
src/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.ts

@@ -6,7 +6,7 @@ import { TStatement } from '../../types/node/TStatement';
 
 
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 
 
@@ -28,18 +28,18 @@ export class ConsoleOutputDisableExpressionNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -50,21 +50,22 @@ export class ConsoleOutputDisableExpressionNode extends AbstractCustomNode {
     }
     }
 
 
     /**
     /**
+     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected getNodeStructure (): TStatement[] {
-        return NodeUtils.convertCodeToStructure(this.getTemplate());
+    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(nodeTemplate);
     }
     }
 
 
     /**
     /**
      * @returns {string}
      * @returns {string}
      */
      */
-    protected getTemplate (): string {
+    protected getNodeTemplate (): string {
         const globalVariableTemplate: string = this.options.target !== ObfuscationTarget.BrowserNoEval
         const globalVariableTemplate: string = this.options.target !== ObfuscationTarget.BrowserNoEval
             ? this.getGlobalVariableTemplate()
             ? this.getGlobalVariableTemplate()
             : GlobalVariableNoEvalTemplate();
             : GlobalVariableNoEvalTemplate();
 
 
-        return this.templateFormatter.format(ConsoleOutputDisableExpressionTemplate(), {
+        return this.customNodeFormatter.formatTemplate(ConsoleOutputDisableExpressionTemplate(), {
             consoleLogDisableFunctionName: this.identifierNamesGenerator.generate(),
             consoleLogDisableFunctionName: this.identifierNamesGenerator.generate(),
             globalVariableTemplate,
             globalVariableTemplate,
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName

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

@@ -8,7 +8,7 @@ import { TStatement } from '../../types/node/TStatement';
 
 
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -26,18 +26,18 @@ export class BinaryExpressionFunctionNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -48,9 +48,10 @@ export class BinaryExpressionFunctionNode extends AbstractCustomNode {
     }
     }
 
 
     /**
     /**
+     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected getNodeStructure (): TStatement[] {
+    protected getNodeStructure (nodeTemplate: string): TStatement[] {
         const structure: TStatement = NodeFactory.expressionStatementNode(
         const structure: TStatement = NodeFactory.expressionStatementNode(
             NodeFactory.functionExpressionNode(
             NodeFactory.functionExpressionNode(
                 [
                 [

+ 14 - 19
src/custom-nodes/control-flow-flattening-nodes/BlockStatementControlFlowFlatteningNode.ts

@@ -7,9 +7,8 @@ import { TIdentifierNamesGeneratorFactory } from '../../types/container/generato
 import { TStatement } from '../../types/node/TStatement';
 import { TStatement } from '../../types/node/TStatement';
 
 
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
-import { IPrevailingKindOfVariablesAnalyzer } from '../../interfaces/analyzers/calls-graph-analyzer/IPrevailingKindOfVariablesAnalyzer';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -32,11 +31,6 @@ export class BlockStatementControlFlowFlatteningNode extends AbstractCustomNode
     @initializable()
     @initializable()
     private originalKeysIndexesInShuffledArray!: number[];
     private originalKeysIndexesInShuffledArray!: number[];
 
 
-    /**
-     * @type {ESTree.VariableDeclaration['kind']}
-     */
-    private readonly prevailingKindOfVariables: ESTree.VariableDeclaration['kind'];
-
     /**
     /**
      * @type {number[]}
      * @type {number[]}
      */
      */
@@ -45,23 +39,18 @@ export class BlockStatementControlFlowFlatteningNode extends AbstractCustomNode
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
-     * @param {IPrevailingKindOfVariablesAnalyzer} prevailingKindOfVariablesAnalyzer
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions,
-        @inject(ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer)
-            prevailingKindOfVariablesAnalyzer: IPrevailingKindOfVariablesAnalyzer,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
-
-        this.prevailingKindOfVariables = prevailingKindOfVariablesAnalyzer.getPrevailingKind();
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -80,9 +69,10 @@ export class BlockStatementControlFlowFlatteningNode extends AbstractCustomNode
     }
     }
 
 
     /**
     /**
+     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected getNodeStructure (): TStatement[] {
+    protected getNodeStructure (nodeTemplate: string): TStatement[] {
         const controllerIdentifierName: string = this.randomGenerator.getRandomString(6);
         const controllerIdentifierName: string = this.randomGenerator.getRandomString(6);
         const indexIdentifierName: string = this.randomGenerator.getRandomString(6);
         const indexIdentifierName: string = this.randomGenerator.getRandomString(6);
         const structure: ESTree.BlockStatement = NodeFactory.blockStatementNode([
         const structure: ESTree.BlockStatement = NodeFactory.blockStatementNode([
@@ -101,13 +91,18 @@ export class BlockStatementControlFlowFlatteningNode extends AbstractCustomNode
                                 NodeFactory.literalNode('|')
                                 NodeFactory.literalNode('|')
                             ]
                             ]
                         )
                         )
-                    ),
+                    )
+                ],
+                'const'
+            ),
+            NodeFactory.variableDeclarationNode(
+                [
                     NodeFactory.variableDeclaratorNode(
                     NodeFactory.variableDeclaratorNode(
                         NodeFactory.identifierNode(indexIdentifierName),
                         NodeFactory.identifierNode(indexIdentifierName),
                         NodeFactory.literalNode(0)
                         NodeFactory.literalNode(0)
                     )
                     )
                 ],
                 ],
-                this.prevailingKindOfVariables
+                'let'
             ),
             ),
             NodeFactory.whileStatementNode(
             NodeFactory.whileStatementNode(
                 NodeFactory.literalNode(true),
                 NodeFactory.literalNode(true),

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

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

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

@@ -8,7 +8,7 @@ import { TStatement } from '../../types/node/TStatement';
 
 
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -26,18 +26,18 @@ export class LogicalExpressionFunctionNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -48,9 +48,10 @@ export class LogicalExpressionFunctionNode extends AbstractCustomNode {
     }
     }
 
 
     /**
     /**
+     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected getNodeStructure (): TStatement[] {
+    protected getNodeStructure (nodeTemplate: string): TStatement[] {
         const structure: TStatement = NodeFactory.expressionStatementNode(
         const structure: TStatement = NodeFactory.expressionStatementNode(
             NodeFactory.functionExpressionNode(
             NodeFactory.functionExpressionNode(
                 [
                 [

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

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

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

@@ -12,7 +12,7 @@ import { TStatement } from '../../../types/node/TStatement';
 
 
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from "../../../interfaces/utils/IRandomGenerator";
 import { IRandomGenerator } from "../../../interfaces/utils/IRandomGenerator";
-import { ITemplateFormatter } from '../../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { initializable } from '../../../decorators/Initializable';
 import { initializable } from '../../../decorators/Initializable';
 
 
@@ -48,18 +48,18 @@ export class CallExpressionControlFlowStorageCallNode extends AbstractCustomNode
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**

+ 8 - 18
src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ControlFlowStorageNode.ts

@@ -9,9 +9,8 @@ import { TStatement } from '../../../types/node/TStatement';
 
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IOptions } from '../../../interfaces/options/IOptions';
-import { IPrevailingKindOfVariablesAnalyzer } from '../../../interfaces/analyzers/calls-graph-analyzer/IPrevailingKindOfVariablesAnalyzer';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { initializable } from '../../../decorators/Initializable';
 import { initializable } from '../../../decorators/Initializable';
 
 
@@ -28,30 +27,20 @@ export class ControlFlowStorageNode extends AbstractCustomNode {
     @initializable()
     @initializable()
     private controlFlowStorage!: TControlFlowStorage;
     private controlFlowStorage!: TControlFlowStorage;
 
 
-    /**
-     * @type {ESTree.VariableDeclaration['kind']}
-     */
-    private readonly prevailingKindOfVariables: ESTree.VariableDeclaration['kind'];
-
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
-     * @param {IPrevailingKindOfVariablesAnalyzer} prevailingKindOfVariablesAnalyzer
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions,
-        @inject(ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer)
-            prevailingKindOfVariablesAnalyzer: IPrevailingKindOfVariablesAnalyzer
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
-
-        this.prevailingKindOfVariables = prevailingKindOfVariablesAnalyzer.getPrevailingKind();
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -62,9 +51,10 @@ export class ControlFlowStorageNode extends AbstractCustomNode {
     }
     }
 
 
     /**
     /**
+     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected getNodeStructure (): TStatement[] {
+    protected getNodeStructure (nodeTemplate: string): TStatement[] {
         const propertyNodes: ESTree.Property[] = Array
         const propertyNodes: ESTree.Property[] = Array
             .from<[string, ICustomNode]>(this.controlFlowStorage.getStorage())
             .from<[string, ICustomNode]>(this.controlFlowStorage.getStorage())
             .map(([key, value]: [string, ICustomNode]) => {
             .map(([key, value]: [string, ICustomNode]) => {
@@ -87,7 +77,7 @@ export class ControlFlowStorageNode extends AbstractCustomNode {
                     NodeFactory.objectExpressionNode(propertyNodes)
                     NodeFactory.objectExpressionNode(propertyNodes)
                 )
                 )
             ],
             ],
-            this.prevailingKindOfVariables
+            'const'
         );
         );
 
 
         structure = NodeUtils.parentizeAst(structure);
         structure = NodeUtils.parentizeAst(structure);

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

@@ -8,7 +8,7 @@ import { TStatement } from '../../../types/node/TStatement';
 
 
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { initializable } from '../../../decorators/Initializable';
 import { initializable } from '../../../decorators/Initializable';
 
 
@@ -44,18 +44,18 @@ export class ExpressionWithOperatorControlFlowStorageCallNode extends AbstractCu
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**

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

@@ -6,7 +6,7 @@ import { TStatement } from '../../../types/node/TStatement';
 
 
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { initializable } from '../../../decorators/Initializable';
 import { initializable } from '../../../decorators/Initializable';
 
 
@@ -30,18 +30,18 @@ export class StringLiteralControlFlowStorageCallNode extends AbstractCustomNode
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**

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

@@ -8,7 +8,7 @@ import { TStatement } from '../../types/node/TStatement';
 
 
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -32,18 +32,18 @@ export class BlockStatementDeadCodeInjectionNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -59,9 +59,10 @@ export class BlockStatementDeadCodeInjectionNode extends AbstractCustomNode {
     }
     }
 
 
     /**
     /**
+     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected getNodeStructure (): TStatement[] {
+    protected getNodeStructure (nodeTemplate: string): TStatement[] {
         const random1: boolean = this.randomGenerator.getMathRandom() > 0.5;
         const random1: boolean = this.randomGenerator.getMathRandom() > 0.5;
         const random2: boolean = this.randomGenerator.getMathRandom() > 0.5;
         const random2: boolean = this.randomGenerator.getMathRandom() > 0.5;
 
 

+ 9 - 8
src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionCallNode.ts

@@ -6,7 +6,7 @@ import { TStatement } from '../../types/node/TStatement';
 
 
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -31,18 +31,18 @@ export class DebugProtectionFunctionCallNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -55,17 +55,18 @@ export class DebugProtectionFunctionCallNode extends AbstractCustomNode {
     }
     }
 
 
     /**
     /**
+     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected getNodeStructure (): TStatement[] {
-        return NodeUtils.convertCodeToStructure(this.getTemplate());
+    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(nodeTemplate);
     }
     }
 
 
     /**
     /**
      * @returns {string}
      * @returns {string}
      */
      */
-    protected getTemplate (): string {
-        return this.templateFormatter.format(DebugProtectionFunctionCallTemplate(), {
+    protected getNodeTemplate (): string {
+        return this.customNodeFormatter.formatTemplate(DebugProtectionFunctionCallTemplate(), {
             debugProtectionFunctionName: this.debugProtectionFunctionName,
             debugProtectionFunctionName: this.debugProtectionFunctionName,
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName
         });
         });

+ 9 - 8
src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionIntervalNode.ts

@@ -6,7 +6,7 @@ import { TStatement } from '../../types/node/TStatement';
 
 
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -25,18 +25,18 @@ export class DebugProtectionFunctionIntervalNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -47,17 +47,18 @@ export class DebugProtectionFunctionIntervalNode extends AbstractCustomNode {
     }
     }
 
 
     /**
     /**
+     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected getNodeStructure (): TStatement[] {
-        return NodeUtils.convertCodeToStructure(this.getTemplate());
+    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(nodeTemplate);
     }
     }
 
 
     /**
     /**
      * @returns {string}
      * @returns {string}
      */
      */
-    protected getTemplate (): string {
-        return this.templateFormatter.format(DebugProtectionFunctionIntervalTemplate(), {
+    protected getNodeTemplate (): string {
+        return this.customNodeFormatter.formatTemplate(DebugProtectionFunctionIntervalTemplate(), {
             debugProtectionFunctionName: this.debugProtectionFunctionName
             debugProtectionFunctionName: this.debugProtectionFunctionName
         });
         });
     }
     }

+ 9 - 8
src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionNode.ts

@@ -6,7 +6,7 @@ import { TStatement } from '../../types/node/TStatement';
 
 
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 
 
@@ -29,18 +29,18 @@ export class DebugProtectionFunctionNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -51,21 +51,22 @@ export class DebugProtectionFunctionNode extends AbstractCustomNode {
     }
     }
 
 
     /**
     /**
+     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected getNodeStructure (): TStatement[] {
-        return NodeUtils.convertCodeToStructure(this.getTemplate());
+    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(nodeTemplate);
     }
     }
 
 
     /**
     /**
      * @returns {string}
      * @returns {string}
      */
      */
-    protected getTemplate (): string {
+    protected getNodeTemplate (): string {
         const debuggerTemplate: string = this.options.target !== ObfuscationTarget.BrowserNoEval
         const debuggerTemplate: string = this.options.target !== ObfuscationTarget.BrowserNoEval
             ? DebuggerTemplate()
             ? DebuggerTemplate()
             : DebuggerTemplateNoEval();
             : DebuggerTemplateNoEval();
 
 
-        return this.templateFormatter.format(DebugProtectionFunctionTemplate(), {
+        return this.customNodeFormatter.formatTemplate(DebugProtectionFunctionTemplate(), {
             debuggerTemplate,
             debuggerTemplate,
             debugProtectionFunctionName: this.debugProtectionFunctionName
             debugProtectionFunctionName: this.debugProtectionFunctionName
         });
         });

+ 9 - 8
src/custom-nodes/domain-lock-nodes/DomainLockNode.ts

@@ -7,7 +7,7 @@ import { TStatement } from '../../types/node/TStatement';
 import { ICryptUtils } from '../../interfaces/utils/ICryptUtils';
 import { ICryptUtils } from '../../interfaces/utils/ICryptUtils';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 
 
@@ -34,7 +34,7 @@ export class DomainLockNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      * @param {ICryptUtils} cryptUtils
      * @param {ICryptUtils} cryptUtils
@@ -42,12 +42,12 @@ export class DomainLockNode extends AbstractCustomNode {
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions,
         @inject(ServiceIdentifiers.IOptions) options: IOptions,
         @inject(ServiceIdentifiers.ICryptUtils) cryptUtils: ICryptUtils
         @inject(ServiceIdentifiers.ICryptUtils) cryptUtils: ICryptUtils
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
 
 
         this.cryptUtils = cryptUtils;
         this.cryptUtils = cryptUtils;
     }
     }
@@ -60,16 +60,17 @@ export class DomainLockNode extends AbstractCustomNode {
     }
     }
 
 
     /**
     /**
+     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected getNodeStructure (): TStatement[] {
-        return NodeUtils.convertCodeToStructure(this.getTemplate());
+    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(nodeTemplate);
     }
     }
 
 
     /**
     /**
      * @returns {string}
      * @returns {string}
      */
      */
-    protected getTemplate (): string {
+    protected getNodeTemplate (): string {
         const domainsString: string = this.options.domainLock.join(';');
         const domainsString: string = this.options.domainLock.join(';');
         const [hiddenDomainsString, diff]: string[] = this.cryptUtils.hideString(
         const [hiddenDomainsString, diff]: string[] = this.cryptUtils.hideString(
             domainsString,
             domainsString,
@@ -79,7 +80,7 @@ export class DomainLockNode extends AbstractCustomNode {
             ? this.getGlobalVariableTemplate()
             ? this.getGlobalVariableTemplate()
             : GlobalVariableNoEvalTemplate();
             : GlobalVariableNoEvalTemplate();
 
 
-        return this.templateFormatter.format(DomainLockNodeTemplate(), {
+        return this.customNodeFormatter.formatTemplate(DomainLockNodeTemplate(), {
             domainLockFunctionName: this.identifierNamesGenerator.generate(),
             domainLockFunctionName: this.identifierNamesGenerator.generate(),
             diff: diff,
             diff: diff,
             domains: hiddenDomainsString,
             domains: hiddenDomainsString,

+ 10 - 9
src/custom-nodes/node-calls-controller-nodes/NodeCallsControllerFunctionNode.ts

@@ -18,7 +18,7 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../options/presets/NoCustomNodes'
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { JavaScriptObfuscator } from '../../JavaScriptObfuscatorFacade';
 import { JavaScriptObfuscator } from '../../JavaScriptObfuscatorFacade';
 import { NodeUtils } from '../../node/NodeUtils';
 import { NodeUtils } from '../../node/NodeUtils';
-import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 @injectable()
 @injectable()
 export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
 export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
@@ -36,18 +36,18 @@ export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -60,19 +60,20 @@ export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
     }
     }
 
 
     /**
     /**
+     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected getNodeStructure (): TStatement[] {
-        return NodeUtils.convertCodeToStructure(this.getTemplate());
+    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(nodeTemplate);
     }
     }
 
 
     /**
     /**
      * @returns {string}
      * @returns {string}
      */
      */
-    protected getTemplate (): string {
+    protected getNodeTemplate (): string {
         if (this.appendEvent === ObfuscationEvent.AfterObfuscation) {
         if (this.appendEvent === ObfuscationEvent.AfterObfuscation) {
             return JavaScriptObfuscator.obfuscate(
             return JavaScriptObfuscator.obfuscate(
-                this.templateFormatter.format(SingleNodeCallControllerTemplate(), {
+                this.customNodeFormatter.formatTemplate(SingleNodeCallControllerTemplate(), {
                     singleNodeCallControllerFunctionName: this.callsControllerFunctionName
                     singleNodeCallControllerFunctionName: this.callsControllerFunctionName
                 }),
                 }),
                 {
                 {
@@ -84,7 +85,7 @@ export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
             ).getObfuscatedCode();
             ).getObfuscatedCode();
         }
         }
 
 
-        return this.templateFormatter.format(SingleNodeCallControllerTemplate(), {
+        return this.customNodeFormatter.formatTemplate(SingleNodeCallControllerTemplate(), {
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName
         });
         });
     }
     }

+ 8 - 20
src/custom-nodes/object-expression-keys-transformer-nodes/BasePropertiesExtractorObjectExpressionHostNode.ts

@@ -1,53 +1,41 @@
 import { inject, injectable, } from 'inversify';
 import { inject, injectable, } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 
-import * as ESTree from 'estree';
-
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TStatement } from '../../types/node/TStatement';
 import { TStatement } from '../../types/node/TStatement';
 
 
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
-import { IPrevailingKindOfVariablesAnalyzer } from '../../interfaces/analyzers/calls-graph-analyzer/IPrevailingKindOfVariablesAnalyzer';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { NodeFactory } from '../../node/NodeFactory';
 import { NodeFactory } from '../../node/NodeFactory';
 
 
 @injectable()
 @injectable()
 export class BasePropertiesExtractorObjectExpressionHostNode extends AbstractCustomNode {
 export class BasePropertiesExtractorObjectExpressionHostNode extends AbstractCustomNode {
-    /**
-     * @type {ESTree.VariableDeclaration['kind']}
-     */
-    private readonly prevailingKindOfVariables: ESTree.VariableDeclaration['kind'];
-
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
-     * @param {IPrevailingKindOfVariablesAnalyzer} prevailingKindOfVariablesAnalyzer
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions,
-        @inject(ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer)
-            prevailingKindOfVariablesAnalyzer: IPrevailingKindOfVariablesAnalyzer,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
-
-        this.prevailingKindOfVariables = prevailingKindOfVariablesAnalyzer.getPrevailingKind();
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
     }
     }
 
 
     public initialize (): void {}
     public initialize (): void {}
 
 
     /**
     /**
+     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected getNodeStructure (): TStatement[] {
+    protected getNodeStructure (nodeTemplate: string): TStatement[] {
         const structure: TStatement = NodeFactory.variableDeclarationNode(
         const structure: TStatement = NodeFactory.variableDeclarationNode(
             [
             [
                 NodeFactory.variableDeclaratorNode(
                 NodeFactory.variableDeclaratorNode(
@@ -57,7 +45,7 @@ export class BasePropertiesExtractorObjectExpressionHostNode extends AbstractCus
                     NodeFactory.objectExpressionNode([])
                     NodeFactory.objectExpressionNode([])
                 )
                 )
             ],
             ],
-            this.prevailingKindOfVariables
+            'const'
         );
         );
 
 
         return [structure];
         return [structure];

+ 9 - 8
src/custom-nodes/self-defending-nodes/SelfDefendingUnicodeNode.ts

@@ -7,7 +7,7 @@ import { TStatement } from '../../types/node/TStatement';
 import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
 import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -34,7 +34,7 @@ export class SelfDefendingUnicodeNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
      * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
@@ -42,12 +42,12 @@ export class SelfDefendingUnicodeNode extends AbstractCustomNode {
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions,
         @inject(ServiceIdentifiers.IOptions) options: IOptions,
         @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
         @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
 
 
         this.escapeSequenceEncoder = escapeSequenceEncoder;
         this.escapeSequenceEncoder = escapeSequenceEncoder;
     }
     }
@@ -60,18 +60,19 @@ export class SelfDefendingUnicodeNode extends AbstractCustomNode {
     }
     }
 
 
     /**
     /**
+     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected getNodeStructure (): TStatement[] {
-        return NodeUtils.convertCodeToStructure(this.getTemplate());
+    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(nodeTemplate);
     }
     }
 
 
     /**
     /**
      * @returns {string}
      * @returns {string}
      */
      */
-    protected getTemplate (): string {
+    protected getNodeTemplate (): string {
         return JavaScriptObfuscator.obfuscate(
         return JavaScriptObfuscator.obfuscate(
-            this.templateFormatter.format(SelfDefendingTemplate(this.escapeSequenceEncoder), {
+            this.customNodeFormatter.formatTemplate(SelfDefendingTemplate(this.escapeSequenceEncoder), {
                 selfDefendingFunctionName: this.identifierNamesGenerator.generate(),
                 selfDefendingFunctionName: this.identifierNamesGenerator.generate(),
                 singleNodeCallControllerFunctionName: this.callsControllerFunctionName
                 singleNodeCallControllerFunctionName: this.callsControllerFunctionName
             }),
             }),

+ 13 - 12
src/custom-nodes/string-array-nodes/StringArrayCallsWrapper.ts

@@ -7,7 +7,7 @@ import { TStatement } from '../../types/node/TStatement';
 import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
 import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
 import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
@@ -49,7 +49,7 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
      * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
@@ -57,12 +57,12 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions,
         @inject(ServiceIdentifiers.IOptions) options: IOptions,
         @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
         @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
 
 
         this.escapeSequenceEncoder = escapeSequenceEncoder;
         this.escapeSequenceEncoder = escapeSequenceEncoder;
     }
     }
@@ -80,20 +80,21 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
     }
     }
 
 
     /**
     /**
+     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected getNodeStructure (): TStatement[] {
-        return NodeUtils.convertCodeToStructure(this.getTemplate());
+    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(nodeTemplate);
     }
     }
 
 
     /**
     /**
      * @returns {string}
      * @returns {string}
      */
      */
-    protected getTemplate (): string {
+    protected getNodeTemplate (): string {
         const decodeNodeTemplate: string = this.getDecodeStringArrayTemplate();
         const decodeNodeTemplate: string = this.getDecodeStringArrayTemplate();
 
 
         return JavaScriptObfuscator.obfuscate(
         return JavaScriptObfuscator.obfuscate(
-            this.templateFormatter.format(StringArrayCallsWrapperTemplate(), {
+            this.customNodeFormatter.formatTemplate(StringArrayCallsWrapperTemplate(), {
                 decodeNodeTemplate,
                 decodeNodeTemplate,
                 stringArrayCallsWrapperName: this.stringArrayCallsWrapperName,
                 stringArrayCallsWrapperName: this.stringArrayCallsWrapperName,
                 stringArrayName: this.stringArrayName
                 stringArrayName: this.stringArrayName
@@ -114,13 +115,13 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
         const globalVariableTemplate: string = this.options.target !== ObfuscationTarget.BrowserNoEval
         const globalVariableTemplate: string = this.options.target !== ObfuscationTarget.BrowserNoEval
             ? this.getGlobalVariableTemplate()
             ? this.getGlobalVariableTemplate()
             : GlobalVariableNoEvalTemplate();
             : GlobalVariableNoEvalTemplate();
-        const atobPolyfill: string = this.templateFormatter.format(AtobTemplate(), { globalVariableTemplate });
+        const atobPolyfill: string = this.customNodeFormatter.formatTemplate(AtobTemplate(), { globalVariableTemplate });
 
 
         let decodeStringArrayTemplate: string = '';
         let decodeStringArrayTemplate: string = '';
         let selfDefendingCode: string = '';
         let selfDefendingCode: string = '';
 
 
         if (this.options.selfDefending) {
         if (this.options.selfDefending) {
-            selfDefendingCode = this.templateFormatter.format(
+            selfDefendingCode = this.customNodeFormatter.formatTemplate(
                 SelfDefendingTemplate(
                 SelfDefendingTemplate(
                     this.randomGenerator,
                     this.randomGenerator,
                     this.escapeSequenceEncoder
                     this.escapeSequenceEncoder
@@ -134,7 +135,7 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
 
 
         switch (this.options.stringArrayEncoding) {
         switch (this.options.stringArrayEncoding) {
             case StringArrayEncoding.Rc4:
             case StringArrayEncoding.Rc4:
-                decodeStringArrayTemplate = this.templateFormatter.format(
+                decodeStringArrayTemplate = this.customNodeFormatter.formatTemplate(
                     StringArrayRc4DecodeNodeTemplate(this.randomGenerator),
                     StringArrayRc4DecodeNodeTemplate(this.randomGenerator),
                     {
                     {
                         atobPolyfill,
                         atobPolyfill,
@@ -147,7 +148,7 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
                 break;
                 break;
 
 
             case StringArrayEncoding.Base64:
             case StringArrayEncoding.Base64:
-                decodeStringArrayTemplate = this.templateFormatter.format(
+                decodeStringArrayTemplate = this.customNodeFormatter.formatTemplate(
                     StringArrayBase64DecodeNodeTemplate(this.randomGenerator),
                     StringArrayBase64DecodeNodeTemplate(this.randomGenerator),
                     {
                     {
                         atobPolyfill,
                         atobPolyfill,

+ 9 - 8
src/custom-nodes/string-array-nodes/StringArrayNode.ts

@@ -7,7 +7,7 @@ import { TStringArrayStorage } from '../../types/storages/TStringArrayStorage';
 
 
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -39,18 +39,18 @@ export class StringArrayNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -78,17 +78,18 @@ export class StringArrayNode extends AbstractCustomNode {
     }
     }
 
 
     /**
     /**
+     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected getNodeStructure (): TStatement[] {
-        return NodeUtils.convertCodeToStructure(this.getTemplate());
+    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(nodeTemplate);
     }
     }
 
 
     /**
     /**
      * @returns {string}
      * @returns {string}
      */
      */
-    protected getTemplate (): string {
-        return this.templateFormatter.format(StringArrayTemplate(), {
+    protected getNodeTemplate (): string {
+        return this.customNodeFormatter.formatTemplate(StringArrayTemplate(), {
             stringArrayName: this.stringArrayName,
             stringArrayName: this.stringArrayName,
             stringArray: this.stringArrayStorage.toString()
             stringArray: this.stringArrayStorage.toString()
         });
         });

+ 10 - 9
src/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.ts

@@ -7,7 +7,7 @@ import { TStatement } from '../../types/node/TStatement';
 import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
 import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
+import { ICustomNodeFormatter } from '../../interfaces/custom-nodes/ICustomNodeFormatter';
 
 
 import { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -42,7 +42,7 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
-     * @param {ITemplateFormatter} templateFormatter
+     * @param {ICustomNodeFormatter} customNodeFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
      * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
@@ -50,12 +50,12 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
-        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
+        @inject(ServiceIdentifiers.ICustomNodeFormatter) customNodeFormatter: ICustomNodeFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions,
         @inject(ServiceIdentifiers.IOptions) options: IOptions,
         @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
         @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, customNodeFormatter, randomGenerator, options);
 
 
         this.escapeSequenceEncoder = escapeSequenceEncoder;
         this.escapeSequenceEncoder = escapeSequenceEncoder;
     }
     }
@@ -73,23 +73,24 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
     }
     }
 
 
     /**
     /**
+     * @param {string} nodeTemplate
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
-    protected getNodeStructure (): TStatement[] {
-        return NodeUtils.convertCodeToStructure(this.getTemplate());
+    protected getNodeStructure (nodeTemplate: string): TStatement[] {
+        return NodeUtils.convertCodeToStructure(nodeTemplate);
     }
     }
 
 
     /**
     /**
      * @returns {string}
      * @returns {string}
      */
      */
-    protected getTemplate (): string {
+    protected getNodeTemplate (): string {
         const timesName: string = this.identifierNamesGenerator.generate();
         const timesName: string = this.identifierNamesGenerator.generate();
         const whileFunctionName: string = this.identifierNamesGenerator.generate();
         const whileFunctionName: string = this.identifierNamesGenerator.generate();
 
 
         let code: string = '';
         let code: string = '';
 
 
         if (this.options.selfDefending) {
         if (this.options.selfDefending) {
-            code = this.templateFormatter.format(SelfDefendingTemplate(this.escapeSequenceEncoder), {
+            code = this.customNodeFormatter.formatTemplate(SelfDefendingTemplate(this.escapeSequenceEncoder), {
                 timesName,
                 timesName,
                 whileFunctionName
                 whileFunctionName
             });
             });
@@ -98,7 +99,7 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
         }
         }
 
 
         return JavaScriptObfuscator.obfuscate(
         return JavaScriptObfuscator.obfuscate(
-            this.templateFormatter.format(StringArrayRotateFunctionTemplate(), {
+            this.customNodeFormatter.formatTemplate(StringArrayRotateFunctionTemplate(), {
                 code,
                 code,
                 timesName,
                 timesName,
                 stringArrayName: this.stringArrayName,
                 stringArrayName: this.stringArrayName,

+ 20 - 0
src/interfaces/custom-nodes/ICustomNodeFormatter.d.ts

@@ -0,0 +1,20 @@
+import { TObject } from '../../types/TObject';
+import { TStatement } from '../../types/node/TStatement';
+
+export interface ICustomNodeFormatter {
+    /**
+     * @param {string} template
+     * @param {TMapping} mapping
+     * @returns {string}
+     */
+    formatTemplate <TMapping extends TObject> (
+        template: string,
+        mapping: TMapping
+    ): string;
+
+    /**
+     * @param {TStatement[]} structure
+     * @returns {TStatement[]}
+     */
+    formatStructure (structure: TStatement[]): TStatement[];
+}

+ 0 - 13
src/interfaces/utils/ITemplateFormatter.d.ts

@@ -1,13 +0,0 @@
-import { TObject } from '../../types/TObject';
-
-export interface ITemplateFormatter {
-    /**
-     * @param {string} template
-     * @param {TMapping} mapping
-     * @returns {string}
-     */
-    format <TMapping extends TObject> (
-        template: string,
-        mapping: TMapping
-    ): string;
-}

+ 0 - 53
src/utils/TemplateFormatter.ts

@@ -1,53 +0,0 @@
-import { inject, injectable } from 'inversify';
-import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
-
-import * as ESTree from 'estree';
-import format from 'string-template';
-
-import { TObject } from '../types/TObject';
-
-import { IPrevailingKindOfVariablesAnalyzer } from '../interfaces/analyzers/calls-graph-analyzer/IPrevailingKindOfVariablesAnalyzer';
-import { ITemplateFormatter } from '../interfaces/utils/ITemplateFormatter';
-
-@injectable()
-export class TemplateFormatter implements ITemplateFormatter {
-    /**
-     * @type {IPrevailingKindOfVariablesAnalyzer}
-     */
-    private readonly prevailingKindOfVariablesAnalyzer: IPrevailingKindOfVariablesAnalyzer;
-
-    /**
-     * @param {IPrevailingKindOfVariablesAnalyzer} prevailingKindOfVariablesAnalyzer
-     */
-    constructor (
-        @inject(ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer)
-            prevailingKindOfVariablesAnalyzer: IPrevailingKindOfVariablesAnalyzer,
-    ) {
-        this.prevailingKindOfVariablesAnalyzer = prevailingKindOfVariablesAnalyzer;
-    }
-
-    public format <TMapping extends TObject> (
-        template: string,
-        mapping: TMapping
-    ): string {
-        const formattedTemplate: string = format(template, mapping);
-        const prevailingKindOfVariables: ESTree.VariableDeclaration['kind'] =
-            this.prevailingKindOfVariablesAnalyzer.getPrevailingKind();
-
-        return this.replaceKindOfVariablesToPrevailingKind(formattedTemplate, prevailingKindOfVariables);
-    }
-
-    /**
-     * @param {string} template
-     * @param {ESTree.VariableDeclaration['kind']} prevailingKindOfVariables
-     * @returns {string}
-     */
-    private replaceKindOfVariablesToPrevailingKind (
-        template: string,
-        prevailingKindOfVariables: ESTree.VariableDeclaration['kind']
-    ): string {
-        return prevailingKindOfVariables === 'var'
-            ? template.replace(/(?<!\w)(?:let|const)(?!\w)/g, prevailingKindOfVariables)
-            : template;
-    }
-}

+ 24 - 4
test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/BlockStatementControlFlowTransformer.spec.ts

@@ -85,6 +85,7 @@ describe('BlockStatementControlFlowTransformer', function () {
 
 
             describe('switch-case map', () => {
             describe('switch-case map', () => {
                 const switchCaseMapVariableRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *_0x(?:[a-f0-9]){4,6}\['.*'\]\['split'\]\('\|'\)/;
                 const switchCaseMapVariableRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *_0x(?:[a-f0-9]){4,6}\['.*'\]\['split'\]\('\|'\)/;
+                const switchCaseMapIndexVariableRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *0x0;/;
                 const switchCaseMapStringRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *\{'.*' *: *'(.*)'\};/;
                 const switchCaseMapStringRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *\{'.*' *: *'(.*)'\};/;
                 const expectedSwitchCasesSequence: string[] = ['0', '1', '2', '3', '4'];
                 const expectedSwitchCasesSequence: string[] = ['0', '1', '2', '3', '4'];
 
 
@@ -100,6 +101,10 @@ describe('BlockStatementControlFlowTransformer', function () {
                     assert.match(obfuscatedCode, switchCaseMapVariableRegExp);
                     assert.match(obfuscatedCode, switchCaseMapVariableRegExp);
                 });
                 });
 
 
+                it('should use correct kind of index variable for switch-case map', () => {
+                    assert.match(obfuscatedCode, switchCaseMapIndexVariableRegExp);
+                });
+
                 it('should create valid switch-case map variable with order of switch cases sequence', () => {
                 it('should create valid switch-case map variable with order of switch cases sequence', () => {
                     assert.deepEqual(switchCaseMap, expectedSwitchCasesSequence);
                     assert.deepEqual(switchCaseMap, expectedSwitchCasesSequence);
                 });
                 });
@@ -669,7 +674,8 @@ describe('BlockStatementControlFlowTransformer', function () {
                 });
                 });
 
 
                 describe('switch-case map', () => {
                 describe('switch-case map', () => {
-                    const switchCaseMapVariableRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *_0x(?:[a-f0-9]){4,6}\['.*'\]\['split'\]\('\|'\)/;
+                    const switchCaseMapVariableRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *_0x(?:[a-f0-9]){4,6}\['.*'\]\['split'\]\('\|'\);/;
+                    const switchCaseMapIndexVariableRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *0x0;/;
                     const switchCaseMapStringRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *\{'.*' *: *'(.*)'\};/;
                     const switchCaseMapStringRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *\{'.*' *: *'(.*)'\};/;
                     const expectedSwitchCasesSequence: string[] = ['0', '1', '2', '3', '4'];
                     const expectedSwitchCasesSequence: string[] = ['0', '1', '2', '3', '4'];
 
 
@@ -685,6 +691,10 @@ describe('BlockStatementControlFlowTransformer', function () {
                         assert.match(obfuscatedCode, switchCaseMapVariableRegExp);
                         assert.match(obfuscatedCode, switchCaseMapVariableRegExp);
                     });
                     });
 
 
+                    it('should use correct kind of index variable for switch-case map', () => {
+                        assert.match(obfuscatedCode, switchCaseMapIndexVariableRegExp);
+                    });
+
                     it('should use correct kind of variable for switch cases sequence', () => {
                     it('should use correct kind of variable for switch cases sequence', () => {
                         assert.deepEqual(switchCaseMap, expectedSwitchCasesSequence);
                         assert.deepEqual(switchCaseMap, expectedSwitchCasesSequence);
                     });
                     });
@@ -708,7 +718,8 @@ describe('BlockStatementControlFlowTransformer', function () {
                 });
                 });
 
 
                 describe('switch-case map', () => {
                 describe('switch-case map', () => {
-                    const switchCaseMapVariableRegExp: RegExp = /const *_0x(?:[a-f0-9]){4,6} *= *_0x(?:[a-f0-9]){4,6}\['.*'\]\['split'\]\('\|'\)/;
+                    const switchCaseMapVariableRegExp: RegExp = /const *_0x(?:[a-f0-9]){4,6} *= *_0x(?:[a-f0-9]){4,6}\['.*'\]\['split'\]\('\|'\);/;
+                    const switchCaseMapIndexVariableRegExp: RegExp = /let *_0x(?:[a-f0-9]){4,6} *= *0x0;/;
                     const switchCaseMapStringRegExp: RegExp = /const *_0x(?:[a-f0-9]){4,6} *= *\{'.*' *: *'(.*)'\};/;
                     const switchCaseMapStringRegExp: RegExp = /const *_0x(?:[a-f0-9]){4,6} *= *\{'.*' *: *'(.*)'\};/;
                     const expectedSwitchCasesSequence: string[] = ['0', '1', '2', '3', '4'];
                     const expectedSwitchCasesSequence: string[] = ['0', '1', '2', '3', '4'];
 
 
@@ -724,6 +735,10 @@ describe('BlockStatementControlFlowTransformer', function () {
                         assert.match(obfuscatedCode, switchCaseMapVariableRegExp);
                         assert.match(obfuscatedCode, switchCaseMapVariableRegExp);
                     });
                     });
 
 
+                    it('should use correct kind of index variable for switch-case map', () => {
+                        assert.match(obfuscatedCode, switchCaseMapIndexVariableRegExp);
+                    });
+
                     it('should use correct kind of variable for switch cases sequence', () => {
                     it('should use correct kind of variable for switch cases sequence', () => {
                         assert.deepEqual(switchCaseMap, expectedSwitchCasesSequence);
                         assert.deepEqual(switchCaseMap, expectedSwitchCasesSequence);
                     });
                     });
@@ -747,8 +762,9 @@ describe('BlockStatementControlFlowTransformer', function () {
                 });
                 });
 
 
                 describe('switch-case map', () => {
                 describe('switch-case map', () => {
-                    const switchCaseMapVariableRegExp: RegExp = /let *_0x(?:[a-f0-9]){4,6} *= *_0x(?:[a-f0-9]){4,6}\['.*'\]\['split'\]\('\|'\)/;
-                    const switchCaseMapStringRegExp: RegExp = /let *_0x(?:[a-f0-9]){4,6} *= *\{'.*' *: *'(.*)'\};/;
+                    const switchCaseMapVariableRegExp: RegExp = /const *_0x(?:[a-f0-9]){4,6} *= *_0x(?:[a-f0-9]){4,6}\['.*'\]\['split'\]\('\|'\)/;
+                    const switchCaseMapIndexVariableRegExp: RegExp = /let *_0x(?:[a-f0-9]){4,6} *= *0x0;/;
+                    const switchCaseMapStringRegExp: RegExp = /const *_0x(?:[a-f0-9]){4,6} *= *\{'.*' *: *'(.*)'\};/;
                     const expectedSwitchCasesSequence: string[] = ['0', '1', '2', '3', '4'];
                     const expectedSwitchCasesSequence: string[] = ['0', '1', '2', '3', '4'];
 
 
                     let switchCaseMap: string[];
                     let switchCaseMap: string[];
@@ -763,6 +779,10 @@ describe('BlockStatementControlFlowTransformer', function () {
                         assert.match(obfuscatedCode, switchCaseMapVariableRegExp);
                         assert.match(obfuscatedCode, switchCaseMapVariableRegExp);
                     });
                     });
 
 
+                    it('should use correct kind of index variable for switch-case map', () => {
+                        assert.match(obfuscatedCode, switchCaseMapIndexVariableRegExp);
+                    });
+
                     it('should use correct kind of variable for switch cases sequence', () => {
                     it('should use correct kind of variable for switch cases sequence', () => {
                         assert.deepEqual(switchCaseMap, expectedSwitchCasesSequence);
                         assert.deepEqual(switchCaseMap, expectedSwitchCasesSequence);
                     });
                     });

+ 1 - 1
test/functional-tests/node-transformers/control-flow-transformers/function-control-flow-transformer/FunctionControlFlowTransformer.spec.ts

@@ -317,7 +317,7 @@ describe('FunctionControlFlowTransformer', function () {
             });
             });
 
 
             describe('Variant #3 - `let` kind', () => {
             describe('Variant #3 - `let` kind', () => {
-                const regexp: RegExp = new RegExp(`let *${variableMatch} *= *\\{`);
+                const regexp: RegExp = new RegExp(`const *${variableMatch} *= *\\{`);
 
 
                 let obfuscatedCode: string;
                 let obfuscatedCode: string;
 
 

+ 1 - 1
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/ObjectExpressionKeysTransformer.spec.ts

@@ -1045,7 +1045,7 @@ describe('ObjectExpressionKeysTransformer', () => {
 
 
         describe('Variant #3: `let` kind`', () => {
         describe('Variant #3: `let` kind`', () => {
             const match: string = `` +
             const match: string = `` +
-                `let *${variableMatch} *= *{};` +
+                `const *${variableMatch} *= *{};` +
                 `${variableMatch}\\['foo'] *= *'bar';` +
                 `${variableMatch}\\['foo'] *= *'bar';` +
                 `${variableMatch}\\['baz'] *= *'bark';` +
                 `${variableMatch}\\['baz'] *= *'bark';` +
             ``;
             ``;

+ 3 - 1
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/prevailing-kind-of-variables-const.js

@@ -1,5 +1,7 @@
+const test = 1;
+
 (function(){
 (function(){
-    const object = {
+    return {
         foo: 'bar',
         foo: 'bar',
         baz: 'bark'
         baz: 'bark'
     };
     };

+ 3 - 1
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/prevailing-kind-of-variables-let.js

@@ -1,5 +1,7 @@
+let test = 1;
+
 (function(){
 (function(){
-    let object = {
+    return {
         foo: 'bar',
         foo: 'bar',
         baz: 'bark'
         baz: 'bark'
     };
     };

+ 3 - 1
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/prevailing-kind-of-variables-var.js

@@ -1,5 +1,7 @@
+var test = 1;
+
 (function(){
 (function(){
-    var object = {
+    return {
         foo: 'bar',
         foo: 'bar',
         baz: 'bark'
         baz: 'bark'
     };
     };

+ 98 - 0
test/functional-tests/templates/domain-lock-nodes/DomainLockNodeTemplate.spec.ts

@@ -8,11 +8,16 @@ import { ServiceIdentifiers } from '../../../../src/container/ServiceIdentifiers
 
 
 import { ICryptUtils } from '../../../../src/interfaces/utils/ICryptUtils';
 import { ICryptUtils } from '../../../../src/interfaces/utils/ICryptUtils';
 import { IInversifyContainerFacade } from '../../../../src/interfaces/container/IInversifyContainerFacade';
 import { IInversifyContainerFacade } from '../../../../src/interfaces/container/IInversifyContainerFacade';
+import { IObfuscatedCode } from '../../../../src/interfaces/source-code/IObfuscatedCode';
+
+import { NO_ADDITIONAL_NODES_PRESET } from '../../../../src/options/presets/NoCustomNodes';
 
 
 import { DomainLockNodeTemplate } from '../../../../src/templates/domain-lock-nodes/domain-lock-node/DomainLockNodeTemplate';
 import { DomainLockNodeTemplate } from '../../../../src/templates/domain-lock-nodes/domain-lock-node/DomainLockNodeTemplate';
 import { GlobalVariableTemplate1 } from '../../../../src/templates/GlobalVariableTemplate1';
 import { GlobalVariableTemplate1 } from '../../../../src/templates/GlobalVariableTemplate1';
 
 
 import { InversifyContainerFacade } from '../../../../src/container/InversifyContainerFacade';
 import { InversifyContainerFacade } from '../../../../src/container/InversifyContainerFacade';
+import { JavaScriptObfuscator } from '../../../../src/JavaScriptObfuscatorFacade';
+import { readFileAsString } from '../../../helpers/readFileAsString';
 
 
 /**
 /**
  * @param {string} currentDomain
  * @param {string} currentDomain
@@ -521,4 +526,97 @@ describe('DomainLockNodeTemplate', () => {
             });
             });
         });
         });
     });
     });
+
+    describe('Prevailing kind of variables', () => {
+        const getCodeTemplate = (obfuscatedCode: string) => `
+            global.document = {
+                domain: 'obfuscator.io'
+            };
+            ${obfuscatedCode}
+        `;
+
+        describe('`var` kind', () => {
+            let obfuscatedCode: string,
+                domainLockVariableRegExp: RegExp = /var _0x([a-f0-9]){4,6} *= *new *RegExp/;
+
+            beforeEach(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-var.js');
+                const obfuscatedCodeObject: IObfuscatedCode = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_ADDITIONAL_NODES_PRESET,
+                        domainLock: ['obfuscator.io'],
+                        stringArray: true,
+                        stringArrayThreshold: 1
+                    }
+                );
+
+                obfuscatedCode = obfuscatedCodeObject.getObfuscatedCode();
+            });
+
+            it('Should return correct kind of variables for domain lock code', () => {
+                assert.match(obfuscatedCode, domainLockVariableRegExp);
+            });
+
+            it('Should does not break on obfuscating', () => {
+                assert.doesNotThrow(() => eval(getCodeTemplate(obfuscatedCode)));
+            });
+        });
+
+        describe('`const` kind', () => {
+            let obfuscatedCode: string,
+                domainLockVariableRegExp: RegExp = /const _0x([a-f0-9]){4,6} *= *new *RegExp/;
+
+            beforeEach(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-const.js');
+                const obfuscatedCodeObject: IObfuscatedCode = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_ADDITIONAL_NODES_PRESET,
+                        domainLock: ['obfuscator.io'],
+                        stringArray: true,
+                        stringArrayThreshold: 1
+                    }
+                );
+
+                obfuscatedCode = obfuscatedCodeObject.getObfuscatedCode();
+            });
+
+            it('Should return correct kind of variables for domain lock code', () => {
+                assert.match(obfuscatedCode, domainLockVariableRegExp);
+            });
+
+            it('Should does not break on obfuscating', () => {
+                assert.doesNotThrow(() => eval(getCodeTemplate(obfuscatedCode)));
+            });
+        });
+
+        describe('`let` kind', () => {
+            let obfuscatedCode: string,
+                domainLockVariableRegExp: RegExp = /const _0x([a-f0-9]){4,6} *= *new *RegExp/;
+
+            beforeEach(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-let.js');
+                const obfuscatedCodeObject: IObfuscatedCode = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_ADDITIONAL_NODES_PRESET,
+                        domainLock: ['obfuscator.io'],
+                        stringArray: true,
+                        stringArrayThreshold: 1
+                    }
+                );
+
+                obfuscatedCode = obfuscatedCodeObject.getObfuscatedCode();
+            });
+
+            it('Should return correct kind of variables for domain lock code', () => {
+                assert.match(obfuscatedCode, domainLockVariableRegExp);
+            });
+
+            it('Should does not break on obfuscating', () => {
+                assert.doesNotThrow(() => eval(getCodeTemplate(obfuscatedCode)));
+            });
+        });
+    });
 });
 });

+ 1 - 0
test/functional-tests/templates/domain-lock-nodes/fixtures/prevailing-kind-of-variables-const.js

@@ -0,0 +1 @@
+const foo = 'foo';

+ 1 - 0
test/functional-tests/templates/domain-lock-nodes/fixtures/prevailing-kind-of-variables-let.js

@@ -0,0 +1 @@
+let foo = 'foo';

+ 1 - 0
test/functional-tests/templates/domain-lock-nodes/fixtures/prevailing-kind-of-variables-var.js

@@ -0,0 +1 @@
+var foo = 'foo';

+ 12 - 0
test/functional-tests/templates/string-array-nodes/string-array-calls-wrapper-node-template/StringArrayCallsWrapperNodeTemplate.spec.ts

@@ -139,6 +139,10 @@ describe('StringArrayCallsWrapperNodeTemplate', () => {
             it('Should return correct kind of variables for string array calls wrapper', () => {
             it('Should return correct kind of variables for string array calls wrapper', () => {
                 assert.match(obfuscatedCode, stringArrayCallsWrapperRegExp);
                 assert.match(obfuscatedCode, stringArrayCallsWrapperRegExp);
             });
             });
+
+            it('Should does not break on obfuscating', () => {
+                assert.doesNotThrow(() => obfuscatedCode);
+            });
         });
         });
 
 
         describe('`const` kind', () => {
         describe('`const` kind', () => {
@@ -162,6 +166,10 @@ describe('StringArrayCallsWrapperNodeTemplate', () => {
             it('Should return correct kind of variables for string array calls wrapper', () => {
             it('Should return correct kind of variables for string array calls wrapper', () => {
                 assert.match(obfuscatedCode, stringArrayCallsWrapperRegExp);
                 assert.match(obfuscatedCode, stringArrayCallsWrapperRegExp);
             });
             });
+
+            it('Should does not break on obfuscating', () => {
+                assert.doesNotThrow(() => obfuscatedCode);
+            });
         });
         });
 
 
         describe('`let` kind', () => {
         describe('`let` kind', () => {
@@ -185,6 +193,10 @@ describe('StringArrayCallsWrapperNodeTemplate', () => {
             it('Should return correct kind of variables for string array calls wrapper', () => {
             it('Should return correct kind of variables for string array calls wrapper', () => {
                 assert.match(obfuscatedCode, stringArrayCallsWrapperRegExp);
                 assert.match(obfuscatedCode, stringArrayCallsWrapperRegExp);
             });
             });
+
+            it('Should does not break on obfuscating', () => {
+                assert.doesNotThrow(() => obfuscatedCode);
+            });
         });
         });
     });
     });
 });
 });

+ 12 - 0
test/functional-tests/templates/string-array-nodes/string-array-rotate-function-template/StringArrayRotateFunctionTemplate.spec.ts

@@ -33,6 +33,10 @@ describe('StringArrayRotateFunctionTemplate', () => {
             it('Should return correct kind of variables for string array rotate function', () => {
             it('Should return correct kind of variables for string array rotate function', () => {
                 assert.match(obfuscatedCode, stringArrayRotateFunctionRegExp);
                 assert.match(obfuscatedCode, stringArrayRotateFunctionRegExp);
             });
             });
+
+            it('Should does not break on obfuscating', () => {
+                assert.doesNotThrow(() => obfuscatedCode);
+            });
         });
         });
 
 
         describe('`const` kind', () => {
         describe('`const` kind', () => {
@@ -57,6 +61,10 @@ describe('StringArrayRotateFunctionTemplate', () => {
             it('Should return correct kind of variables for string array rotate function', () => {
             it('Should return correct kind of variables for string array rotate function', () => {
                 assert.match(obfuscatedCode, stringArrayRotateFunctionRegExp);
                 assert.match(obfuscatedCode, stringArrayRotateFunctionRegExp);
             });
             });
+
+            it('Should does not break on obfuscating', () => {
+                assert.doesNotThrow(() => obfuscatedCode);
+            });
         });
         });
 
 
         describe('`let` kind', () => {
         describe('`let` kind', () => {
@@ -81,6 +89,10 @@ describe('StringArrayRotateFunctionTemplate', () => {
             it('Should return correct kind of variables for string array rotate function', () => {
             it('Should return correct kind of variables for string array rotate function', () => {
                 assert.match(obfuscatedCode, stringArrayRotateFunctionRegExp);
                 assert.match(obfuscatedCode, stringArrayRotateFunctionRegExp);
             });
             });
+
+            it('Should does not break on obfuscating', () => {
+                assert.doesNotThrow(() => obfuscatedCode);
+            });
         });
         });
     });
     });
 });
 });

+ 12 - 0
test/functional-tests/templates/string-array-nodes/string-array-template/StringArrayTemplate.spec.ts

@@ -32,6 +32,10 @@ describe('StringArrayTemplate', () => {
             it('Should return correct kind of variables for string array', () => {
             it('Should return correct kind of variables for string array', () => {
                 assert.match(obfuscatedCode, stringArrayRegExp);
                 assert.match(obfuscatedCode, stringArrayRegExp);
             });
             });
+
+            it('Should does not break on obfuscating', () => {
+                assert.doesNotThrow(() => obfuscatedCode);
+            });
         });
         });
 
 
         describe('`const` kind', () => {
         describe('`const` kind', () => {
@@ -55,6 +59,10 @@ describe('StringArrayTemplate', () => {
             it('Should return correct kind of variables for string array', () => {
             it('Should return correct kind of variables for string array', () => {
                 assert.match(obfuscatedCode, stringArrayRegExp);
                 assert.match(obfuscatedCode, stringArrayRegExp);
             });
             });
+
+            it('Should does not break on obfuscating', () => {
+                assert.doesNotThrow(() => obfuscatedCode);
+            });
         });
         });
 
 
         describe('`let` kind', () => {
         describe('`let` kind', () => {
@@ -78,6 +86,10 @@ describe('StringArrayTemplate', () => {
             it('Should return correct kind of variables for string array', () => {
             it('Should return correct kind of variables for string array', () => {
                 assert.match(obfuscatedCode, stringArrayRegExp);
                 assert.match(obfuscatedCode, stringArrayRegExp);
             });
             });
+
+            it('Should does not break on obfuscating', () => {
+                assert.doesNotThrow(() => obfuscatedCode);
+            });
         });
         });
     });
     });
 });
 });

+ 16 - 2
test/runtime-tests/JavaScriptObfuscatorRuntime.spec.ts

@@ -8,6 +8,12 @@ import { readFileAsString } from '../helpers/readFileAsString';
 
 
 import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscatorFacade';
 import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscatorFacade';
 
 
+const getEnvironmentCode = () => `
+    global.document = {
+        domain: 'obfuscator.io'
+    };
+`;
+
 describe('JavaScriptObfuscator runtime eval', function () {
 describe('JavaScriptObfuscator runtime eval', function () {
     const options: TInputOptions = {
     const options: TInputOptions = {
         controlFlowFlattening: true,
         controlFlowFlattening: true,
@@ -15,12 +21,15 @@ describe('JavaScriptObfuscator runtime eval', function () {
         deadCodeInjection: true,
         deadCodeInjection: true,
         deadCodeInjectionThreshold: 1,
         deadCodeInjectionThreshold: 1,
         debugProtection: true,
         debugProtection: true,
+        disableConsoleOutput: true,
+        domainLock: ['obfuscator.io'],
+        rotateStringArray: true,
         selfDefending: true,
         selfDefending: true,
         splitStrings: true,
         splitStrings: true,
         splitStringsChunkLength: 5,
         splitStringsChunkLength: 5,
         stringArray: true,
         stringArray: true,
-        rotateStringArray: true,
         stringArrayEncoding: StringArrayEncoding.Rc4,
         stringArrayEncoding: StringArrayEncoding.Rc4,
+        stringArrayThreshold: 1,
         transformObjectKeys: true,
         transformObjectKeys: true,
         unicodeEscapeSequence: true
         unicodeEscapeSequence: true
     };
     };
@@ -42,6 +51,7 @@ describe('JavaScriptObfuscator runtime eval', function () {
         it('should obfuscate code without any runtime errors after obfuscation: Variant #1 astring', () => {
         it('should obfuscate code without any runtime errors after obfuscation: Variant #1 astring', () => {
             assert.equal(
             assert.equal(
                 eval(`
                 eval(`
+                    ${getEnvironmentCode()}
                     ${obfuscatedCode}
                     ${obfuscatedCode}
                     const code = generate({
                     const code = generate({
                         "type": "Program",
                         "type": "Program",
@@ -120,7 +130,11 @@ describe('JavaScriptObfuscator runtime eval', function () {
 
 
         it('should obfuscate code without any runtime errors after obfuscation: Variant #2 sha256', () => {
         it('should obfuscate code without any runtime errors after obfuscation: Variant #2 sha256', () => {
             assert.equal(
             assert.equal(
-                eval(`${obfuscatedCode} sha256('test');`),
+                eval(`
+                    ${getEnvironmentCode()}
+                    ${obfuscatedCode}
+                    sha256('test');
+                `),
                 '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'
                 '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'
             );
             );
         });
         });

Some files were not shown because too many files changed in this diff