Browse Source

Merge pull request #487 from javascript-obfuscator/declaration-kind-analyzer

Auto detection of prevailing kind of variables
Timofey Kachalov 5 năm trước cách đây
mục cha
commit
dcc489a148
100 tập tin đã thay đổi với 1219 bổ sung280 xóa
  1. 4 0
      CHANGELOG.md
  2. 8 0
      README.md
  3. 0 0
      dist/index.browser.js
  4. 0 0
      dist/index.cli.js
  5. 0 0
      dist/index.js
  6. 1 1
      package.json
  7. 61 0
      src/analyzers/prevailing-kind-of-variables-analyzer/PrevailingKindOfVariablesAnalyzer.ts
  8. 2 0
      src/container/ServiceIdentifiers.ts
  9. 7 0
      src/container/modules/analyzers/AnalyzersModule.ts
  10. 7 2
      src/container/modules/custom-nodes/CustomNodesModule.ts
  11. 7 0
      src/container/modules/utils/UtilsModule.ts
  12. 15 4
      src/custom-nodes/AbstractCustomNode.ts
  13. 5 4
      src/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.ts
  14. 7 2
      src/custom-nodes/console-output-nodes/group/ConsoleOutputCustomNodeGroup.ts
  15. 4 1
      src/custom-nodes/control-flow-flattening-nodes/BinaryExpressionFunctionNode.ts
  16. 37 20
      src/custom-nodes/control-flow-flattening-nodes/BlockStatementControlFlowFlatteningNode.ts
  17. 4 1
      src/custom-nodes/control-flow-flattening-nodes/CallExpressionFunctionNode.ts
  18. 4 1
      src/custom-nodes/control-flow-flattening-nodes/LogicalExpressionFunctionNode.ts
  19. 4 1
      src/custom-nodes/control-flow-flattening-nodes/StringLiteralNode.ts
  20. 4 1
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/CallExpressionControlFlowStorageCallNode.ts
  21. 25 8
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ControlFlowStorageNode.ts
  22. 4 1
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ExpressionWithOperatorControlFlowStorageCallNode.ts
  23. 4 1
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/StringLiteralControlFlowStorageCallNode.ts
  24. 4 1
      src/custom-nodes/dead-code-injection-nodes/BlockStatementDeadCodeInjectionNode.ts
  25. 5 4
      src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionCallNode.ts
  26. 5 4
      src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionIntervalNode.ts
  27. 5 4
      src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionNode.ts
  28. 13 4
      src/custom-nodes/debug-protection-nodes/group/DebugProtectionCustomNodeGroup.ts
  29. 8 7
      src/custom-nodes/domain-lock-nodes/DomainLockNode.ts
  30. 7 2
      src/custom-nodes/domain-lock-nodes/group/DomainLockCustomNodeGroup.ts
  31. 6 5
      src/custom-nodes/node-calls-controller-nodes/NodeCallsControllerFunctionNode.ts
  32. 29 10
      src/custom-nodes/object-expression-keys-transformer-nodes/BasePropertiesExtractorObjectExpressionHostNode.ts
  33. 8 7
      src/custom-nodes/self-defending-nodes/SelfDefendingUnicodeNode.ts
  34. 7 2
      src/custom-nodes/self-defending-nodes/group/SelfDefendingCustomNodeGroup.ts
  35. 12 11
      src/custom-nodes/string-array-nodes/StringArrayCallsWrapper.ts
  36. 5 4
      src/custom-nodes/string-array-nodes/StringArrayNode.ts
  37. 9 8
      src/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.ts
  38. 10 3
      src/custom-nodes/string-array-nodes/group/StringArrayCustomNodeGroup.ts
  39. 2 2
      src/interfaces/analyzers/IAnalyzer.d.ts
  40. 1 1
      src/interfaces/analyzers/calls-graph-analyzer/ICallsGraphAnalyzer.d.ts
  41. 15 0
      src/interfaces/analyzers/calls-graph-analyzer/IPrevailingKindOfVariablesAnalyzer.d.ts
  42. 3 1
      src/interfaces/custom-nodes/ICustomNode.d.ts
  43. 6 0
      src/interfaces/utils/IArrayUtils.d.ts
  44. 13 0
      src/interfaces/utils/ITemplateFormatter.d.ts
  45. 4 3
      src/node-transformers/control-flow-transformers/BlockStatementControlFlowTransformer.ts
  46. 4 3
      src/node-transformers/control-flow-transformers/FunctionControlFlowTransformer.ts
  47. 7 6
      src/node-transformers/control-flow-transformers/control-flow-replacers/BinaryExpressionControlFlowReplacer.ts
  48. 7 6
      src/node-transformers/control-flow-transformers/control-flow-replacers/CallExpressionControlFlowReplacer.ts
  49. 4 3
      src/node-transformers/control-flow-transformers/control-flow-replacers/ExpressionWithOperatorControlFlowReplacer.ts
  50. 7 6
      src/node-transformers/control-flow-transformers/control-flow-replacers/LogicalExpressionControlFlowReplacer.ts
  51. 7 6
      src/node-transformers/control-flow-transformers/control-flow-replacers/StringLiteralControlFlowReplacer.ts
  52. 6 3
      src/node-transformers/converting-transformers/properties-extractors/BasePropertiesExtractor.ts
  53. 4 3
      src/node-transformers/dead-code-injection-transformers/DeadCodeInjectionTransformer.ts
  54. 11 0
      src/node-transformers/preparing-transformers/CustomNodesTransformer.ts
  55. 4 1
      src/node/NodeUtils.ts
  56. 7 5
      src/templates/AtobTemplate.ts
  57. 1 1
      src/templates/GlobalVariableNoEvalTemplate.ts
  58. 2 2
      src/templates/GlobalVariableTemplate1.ts
  59. 3 3
      src/templates/GlobalVariableTemplate2.ts
  60. 7 5
      src/templates/Rc4Template.ts
  61. 4 4
      src/templates/SingleNodeCallControllerTemplate.ts
  62. 3 3
      src/templates/console-output-nodes/console-output-disable-expression-node/ConsoleOutputDisableExpressionTemplate.ts
  63. 14 11
      src/templates/debug-protection-nodes/debug-protection-function-call-node/DebugProtectionFunctionCallTemplate.ts
  64. 1 1
      src/templates/debug-protection-nodes/debug-protection-function-node/DebuggerTemplateNoEval.ts
  65. 23 23
      src/templates/domain-lock-nodes/domain-lock-node/DomainLockNodeTemplate.ts
  66. 10 10
      src/templates/self-defending-nodes/self-defending-unicode-node/SelfDefendingTemplate.ts
  67. 4 4
      src/templates/string-array-nodes/string-array-calls-wrapper/SelfDefendingTemplate.ts
  68. 4 4
      src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayBase64DecodeNodeTemplate.ts
  69. 2 2
      src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayCallsWrapperTemplate.ts
  70. 1 1
      src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayRC4DecodeNodeTemplate.ts
  71. 1 1
      src/templates/string-array-nodes/string-array-node/StringArrayTemplate.ts
  72. 13 14
      src/templates/string-array-nodes/string-array-rotate-function-node/SelfDefendingTemplate.ts
  73. 1 1
      src/templates/string-array-nodes/string-array-rotate-function-node/StringArrayRotateFunctionTemplate.ts
  74. 3 0
      src/types/TInitialData.d.ts
  75. 3 1
      src/types/container/custom-nodes/TControlFlowCustomNodeFactory.d.ts
  76. 3 1
      src/types/container/custom-nodes/TCustomNodeFactory.d.ts
  77. 3 1
      src/types/container/custom-nodes/TDeadNodeInjectionCustomNodeFactory.d.ts
  78. 3 1
      src/types/container/custom-nodes/TObjectExpressionKeysTransformerCustomNodeFactory.d.ts
  79. 31 0
      src/utils/ArrayUtils.ts
  80. 53 0
      src/utils/TemplateFormatter.ts
  81. 4 7
      test/dev/dev.ts
  82. 134 0
      test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts
  83. 32 0
      test/functional-tests/javascript-obfuscator/fixtures/prevailing-kind-of-variables-const.js
  84. 32 0
      test/functional-tests/javascript-obfuscator/fixtures/prevailing-kind-of-variables-let.js
  85. 32 0
      test/functional-tests/javascript-obfuscator/fixtures/prevailing-kind-of-variables-var.js
  86. 119 0
      test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/BlockStatementControlFlowTransformer.spec.ts
  87. 9 0
      test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/fixtures/prevailing-kind-of-variables-const.js
  88. 9 0
      test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/fixtures/prevailing-kind-of-variables-let.js
  89. 9 0
      test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/fixtures/prevailing-kind-of-variables-var.js
  90. 71 0
      test/functional-tests/node-transformers/control-flow-transformers/function-control-flow-transformer/FunctionControlFlowTransformer.spec.ts
  91. 3 0
      test/functional-tests/node-transformers/control-flow-transformers/function-control-flow-transformer/fixtures/prevailing-kind-of-variables-const.js
  92. 3 0
      test/functional-tests/node-transformers/control-flow-transformers/function-control-flow-transformer/fixtures/prevailing-kind-of-variables-let.js
  93. 3 0
      test/functional-tests/node-transformers/control-flow-transformers/function-control-flow-transformer/fixtures/prevailing-kind-of-variables-var.js
  94. 86 3
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/ObjectExpressionKeysTransformer.spec.ts
  95. 6 0
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/prevailing-kind-of-variables-const.js
  96. 6 0
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/prevailing-kind-of-variables-let.js
  97. 6 0
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/prevailing-kind-of-variables-var.js
  98. 1 1
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/variable-declarator-with-object-call-3.js
  99. 1 1
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/variable-declarator-with-object-call-4.js
  100. 1 1
      test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/variable-declarator-with-object-call-5.js

+ 4 - 0
CHANGELOG.md

@@ -1,5 +1,9 @@
 Change Log
 Change Log
 
 
+v0.22.0
+---
+* **Breaking:** auto-detection of kind of variables of inserted nodes, based on most prevailing kind of variables of source code
+
 v0.21.1
 v0.21.1
 ---
 ---
 * Fixed conditional comments in some rare cases
 * Fixed conditional comments in some rare cases

+ 8 - 0
README.md

@@ -263,6 +263,10 @@ For example:
 * Obfuscation of the variable's name at its declaration is called direct transformation;
 * Obfuscation of the variable's name at its declaration is called direct transformation;
 * Obfuscation of the variable's name beyond its declaration is called child transformation.
 * Obfuscation of the variable's name beyond its declaration is called child transformation.
 
 
+## Kind of variables
+
+Kind of variables of inserted nodes will auto-detected, based on most prevailing kind of variables of source code.
+
 ## Antiviruses false positive virus alerts
 ## Antiviruses false positive virus alerts
 
 
 Some input source code that will obfuscated with some obfuscation options can trigger false positive alerts in a few antiviruses. If you will get this false positive triggers, try to play with obfuscation options.
 Some input source code that will obfuscated with some obfuscation options can trigger false positive alerts in a few antiviruses. If you will get this false positive triggers, try to play with obfuscation options.
@@ -952,6 +956,10 @@ Likely this is `selfDefending` mechanism. Something is changing source code afte
 
 
 No. JSX support isn't planned.
 No. JSX support isn't planned.
 
 
+### How to change kind of variables of inserted nodes (`var`, `let` or `const`)?
+
+See: [`Kind of variables`](#kind-of-variables)
+
 ## Backers
 ## Backers
 
 
 Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/javascript-obfuscator#backer)]
 Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/javascript-obfuscator#backer)]

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/index.browser.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/index.cli.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/index.js


+ 1 - 1
package.json

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

+ 61 - 0
src/analyzers/prevailing-kind-of-variables-analyzer/PrevailingKindOfVariablesAnalyzer.ts

@@ -0,0 +1,61 @@
+import { inject, injectable, } from 'inversify';
+import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
+
+import * as estraverse from 'estraverse';
+import * as ESTree from 'estree';
+
+import { IArrayUtils } from '../../interfaces/utils/IArrayUtils';
+import { IPrevailingKindOfVariablesAnalyzer } from '../../interfaces/analyzers/calls-graph-analyzer/IPrevailingKindOfVariablesAnalyzer';
+
+import { NodeGuards } from '../../node/NodeGuards';
+
+@injectable()
+export class PrevailingKindOfVariablesAnalyzer implements IPrevailingKindOfVariablesAnalyzer {
+    /**
+     * @type {ESTree.VariableDeclaration['kind']}
+     */
+    private static readonly defaultKindOfVariables: ESTree.VariableDeclaration['kind'] = 'var';
+
+    /**
+     * @type {IArrayUtils}
+     */
+    private readonly arrayUtils: IArrayUtils;
+
+    /**
+     * @type {ESTree.VariableDeclaration['kind']}
+     */
+    private prevailingKindOfVariables: ESTree.VariableDeclaration['kind'] = PrevailingKindOfVariablesAnalyzer.defaultKindOfVariables;
+
+    constructor (
+        @inject(ServiceIdentifiers.IArrayUtils) arrayUtils: IArrayUtils
+    ) {
+        this.arrayUtils = arrayUtils;
+    }
+
+    /**
+     * @param {Program} astTree
+     */
+    public analyze (astTree: ESTree.Program): void {
+        const variableKinds: ESTree.VariableDeclaration['kind'][] = [];
+
+        estraverse.traverse(astTree, {
+            enter: (node: ESTree.Node): estraverse.VisitorOption | void => {
+                if (!NodeGuards.isVariableDeclarationNode(node)) {
+                    return;
+                }
+
+                variableKinds.push(node.kind);
+            }
+        });
+
+        this.prevailingKindOfVariables = this.arrayUtils.findMostOccurringElement(variableKinds)
+            || PrevailingKindOfVariablesAnalyzer.defaultKindOfVariables;
+    }
+
+    /**
+     * @returns {VariableDeclaration["kind"]}
+     */
+    public getPrevailingKind (): ESTree.VariableDeclaration['kind'] {
+        return this.prevailingKindOfVariables;
+    }
+}

+ 2 - 0
src/container/ServiceIdentifiers.ts

@@ -35,10 +35,12 @@ export enum ServiceIdentifiers {
     IOptions = 'IOptions',
     IOptions = 'IOptions',
     IOptionsNormalizer = 'IOptionsNormalizer',
     IOptionsNormalizer = 'IOptionsNormalizer',
     IObfuscatingReplacer = 'IObfuscatingReplacer',
     IObfuscatingReplacer = 'IObfuscatingReplacer',
+    IPrevailingKindOfVariablesAnalyzer = 'IPrevailingKindOfVariablesAnalyzer',
     IPropertiesExtractor = 'IPropertiesExtractor',
     IPropertiesExtractor = 'IPropertiesExtractor',
     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>',

+ 7 - 0
src/container/modules/analyzers/AnalyzersModule.ts

@@ -4,12 +4,14 @@ import { ServiceIdentifiers } from '../../ServiceIdentifiers';
 
 
 import { ICalleeDataExtractor } from '../../../interfaces/analyzers/calls-graph-analyzer/ICalleeDataExtractor';
 import { ICalleeDataExtractor } from '../../../interfaces/analyzers/calls-graph-analyzer/ICalleeDataExtractor';
 import { ICallsGraphAnalyzer } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphAnalyzer';
 import { ICallsGraphAnalyzer } from '../../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphAnalyzer';
+import { IPrevailingKindOfVariablesAnalyzer } from '../../../interfaces/analyzers/calls-graph-analyzer/IPrevailingKindOfVariablesAnalyzer';
 
 
 import { CalleeDataExtractor } from '../../../enums/analyzers/calls-graph-analyzer/CalleeDataExtractor';
 import { CalleeDataExtractor } from '../../../enums/analyzers/calls-graph-analyzer/CalleeDataExtractor';
 import { CallsGraphAnalyzer } from '../../../analyzers/calls-graph-analyzer/CallsGraphAnalyzer';
 import { CallsGraphAnalyzer } from '../../../analyzers/calls-graph-analyzer/CallsGraphAnalyzer';
 import { FunctionDeclarationCalleeDataExtractor } from '../../../analyzers/calls-graph-analyzer/callee-data-extractors/FunctionDeclarationCalleeDataExtractor';
 import { FunctionDeclarationCalleeDataExtractor } from '../../../analyzers/calls-graph-analyzer/callee-data-extractors/FunctionDeclarationCalleeDataExtractor';
 import { FunctionExpressionCalleeDataExtractor } from '../../../analyzers/calls-graph-analyzer/callee-data-extractors/FunctionExpressionCalleeDataExtractor';
 import { FunctionExpressionCalleeDataExtractor } from '../../../analyzers/calls-graph-analyzer/callee-data-extractors/FunctionExpressionCalleeDataExtractor';
 import { ObjectExpressionCalleeDataExtractor } from '../../../analyzers/calls-graph-analyzer/callee-data-extractors/ObjectExpressionCalleeDataExtractor';
 import { ObjectExpressionCalleeDataExtractor } from '../../../analyzers/calls-graph-analyzer/callee-data-extractors/ObjectExpressionCalleeDataExtractor';
+import { PrevailingKindOfVariablesAnalyzer } from '../../../analyzers/prevailing-kind-of-variables-analyzer/PrevailingKindOfVariablesAnalyzer';
 
 
 export const analyzersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
 export const analyzersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
     // calls graph analyzer
     // calls graph analyzer
@@ -17,6 +19,11 @@ export const analyzersModule: interfaces.ContainerModule = new ContainerModule((
         .to(CallsGraphAnalyzer)
         .to(CallsGraphAnalyzer)
         .inSingletonScope();
         .inSingletonScope();
 
 
+    // prevailing kind of variables analyzer
+    bind<IPrevailingKindOfVariablesAnalyzer>(ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer)
+        .to(PrevailingKindOfVariablesAnalyzer)
+        .inSingletonScope();
+
     // callee data extractors
     // callee data extractors
     bind<ICalleeDataExtractor>(ServiceIdentifiers.ICalleeDataExtractor)
     bind<ICalleeDataExtractor>(ServiceIdentifiers.ICalleeDataExtractor)
         .to(FunctionDeclarationCalleeDataExtractor)
         .to(FunctionDeclarationCalleeDataExtractor)

+ 7 - 2
src/container/modules/custom-nodes/CustomNodesModule.ts

@@ -160,8 +160,10 @@ 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.IRandomGenerator,
                 ServiceIdentifiers.IRandomGenerator,
-                ServiceIdentifiers.IOptions
+                ServiceIdentifiers.IOptions,
+                ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer
             ));
             ));
 
 
     // dead code injection customNode constructor factory
     // dead code injection customNode constructor factory
@@ -170,6 +172,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.IRandomGenerator,
                 ServiceIdentifiers.IRandomGenerator,
                 ServiceIdentifiers.IOptions
                 ServiceIdentifiers.IOptions
             ));
             ));
@@ -180,8 +183,10 @@ 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.IRandomGenerator,
                 ServiceIdentifiers.IRandomGenerator,
-                ServiceIdentifiers.IOptions
+                ServiceIdentifiers.IOptions,
+                ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer
             ));
             ));
 
 
     // customNodeGroup factory
     // customNodeGroup factory

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

@@ -7,6 +7,7 @@ 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';
@@ -14,6 +15,7 @@ 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
@@ -44,4 +46,9 @@ 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();
 });
 });

+ 15 - 4
src/custom-nodes/AbstractCustomNode.ts

@@ -8,12 +8,15 @@ 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 { GlobalVariableTemplate1 } from '../templates/GlobalVariableTemplate1';
 import { GlobalVariableTemplate1 } from '../templates/GlobalVariableTemplate1';
 import { GlobalVariableTemplate2 } from '../templates/GlobalVariableTemplate2';
 import { GlobalVariableTemplate2 } from '../templates/GlobalVariableTemplate2';
 
 
 @injectable()
 @injectable()
-export abstract class AbstractCustomNode implements ICustomNode {
+export abstract class AbstractCustomNode <
+    TInitialData extends any[] = any[]
+> implements ICustomNode <TInitialData> {
     /**
     /**
      * @type {string[]}
      * @type {string[]}
      */
      */
@@ -42,26 +45,34 @@ export abstract class AbstractCustomNode implements ICustomNode {
      */
      */
     protected readonly randomGenerator: IRandomGenerator;
     protected readonly randomGenerator: IRandomGenerator;
 
 
+    /**
+     * @type {ITemplateFormatter}
+     */
+    protected readonly templateFormatter: ITemplateFormatter;
+
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
      * @param {IOptions} options
      */
      */
-    constructor (
+    protected constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
+        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
         @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.randomGenerator = randomGenerator;
         this.randomGenerator = randomGenerator;
         this.options = options;
         this.options = options;
     }
     }
 
 
     /**
     /**
-     * @param {unknown[]} args
+     * @param {TInitialData} args
      */
      */
-    public abstract initialize (...args: unknown[]): void;
+    public abstract initialize (...args: TInitialData): void;
 
 
     /**
     /**
      * @returns {TStatement[]}
      * @returns {TStatement[]}

+ 5 - 4
src/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.ts

@@ -1,13 +1,12 @@
 import { inject, injectable, } from 'inversify';
 import { inject, injectable, } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 
-import format from 'string-template';
-
 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 { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
+import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
 
 
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 
 
@@ -29,16 +28,18 @@ export class ConsoleOutputDisableExpressionNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -63,7 +64,7 @@ export class ConsoleOutputDisableExpressionNode extends AbstractCustomNode {
             ? this.getGlobalVariableTemplate()
             ? this.getGlobalVariableTemplate()
             : GlobalVariableNoEvalTemplate();
             : GlobalVariableNoEvalTemplate();
 
 
-        return format(ConsoleOutputDisableExpressionTemplate(), {
+        return this.templateFormatter.format(ConsoleOutputDisableExpressionTemplate(), {
             consoleLogDisableFunctionName: this.identifierNamesGenerator.generate(),
             consoleLogDisableFunctionName: this.identifierNamesGenerator.generate(),
             globalVariableTemplate,
             globalVariableTemplate,
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName

+ 7 - 2
src/custom-nodes/console-output-nodes/group/ConsoleOutputCustomNodeGroup.ts

@@ -3,6 +3,7 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 
 import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
 import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
+import { TInitialData } from '../../../types/TInitialData';
 import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
 import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
 
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
@@ -16,7 +17,9 @@ import { CustomNode } from '../../../enums/custom-nodes/CustomNode';
 import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent';
 import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent';
 
 
 import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
 import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
+import { ConsoleOutputDisableExpressionNode } from '../ConsoleOutputDisableExpressionNode';
 import { NodeAppender } from '../../../node/NodeAppender';
 import { NodeAppender } from '../../../node/NodeAppender';
+import { NodeCallsControllerFunctionNode } from '../../node-calls-controller-nodes/NodeCallsControllerFunctionNode';
 
 
 @injectable()
 @injectable()
 export class ConsoleOutputCustomNodeGroup extends AbstractCustomNodeGroup {
 export class ConsoleOutputCustomNodeGroup extends AbstractCustomNodeGroup {
@@ -90,8 +93,10 @@ export class ConsoleOutputCustomNodeGroup extends AbstractCustomNodeGroup {
 
 
         const callsControllerFunctionName: string = this.identifierNamesGenerator.generate();
         const callsControllerFunctionName: string = this.identifierNamesGenerator.generate();
 
 
-        const consoleOutputDisableExpressionNode: ICustomNode = this.customNodeFactory(CustomNode.ConsoleOutputDisableExpressionNode);
-        const nodeCallsControllerFunctionNode: ICustomNode = this.customNodeFactory(CustomNode.NodeCallsControllerFunctionNode);
+        const consoleOutputDisableExpressionNode: ICustomNode<TInitialData<ConsoleOutputDisableExpressionNode>> =
+            this.customNodeFactory(CustomNode.ConsoleOutputDisableExpressionNode);
+        const nodeCallsControllerFunctionNode: ICustomNode<TInitialData<NodeCallsControllerFunctionNode>> =
+            this.customNodeFactory(CustomNode.NodeCallsControllerFunctionNode);
 
 
         consoleOutputDisableExpressionNode.initialize(callsControllerFunctionName);
         consoleOutputDisableExpressionNode.initialize(callsControllerFunctionName);
         nodeCallsControllerFunctionNode.initialize(this.appendEvent, callsControllerFunctionName);
         nodeCallsControllerFunctionNode.initialize(this.appendEvent, callsControllerFunctionName);

+ 4 - 1
src/custom-nodes/control-flow-flattening-nodes/BinaryExpressionFunctionNode.ts

@@ -8,6 +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 { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -25,16 +26,18 @@ export class BinaryExpressionFunctionNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**

+ 37 - 20
src/custom-nodes/control-flow-flattening-nodes/BlockStatementControlFlowFlatteningNode.ts

@@ -7,7 +7,9 @@ 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 { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -30,6 +32,11 @@ 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[]}
      */
      */
@@ -38,16 +45,23 @@ export class BlockStatementControlFlowFlatteningNode extends AbstractCustomNode
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions
+        @inject(ServiceIdentifiers.IOptions) options: IOptions,
+        @inject(ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer)
+            prevailingKindOfVariablesAnalyzer: IPrevailingKindOfVariablesAnalyzer,
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+
+        this.prevailingKindOfVariables = prevailingKindOfVariablesAnalyzer.getPrevailingKind();
     }
     }
 
 
     /**
     /**
@@ -72,26 +86,29 @@ export class BlockStatementControlFlowFlatteningNode extends AbstractCustomNode
         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([
-            NodeFactory.variableDeclarationNode([
-                NodeFactory.variableDeclaratorNode(
-                    NodeFactory.identifierNode(controllerIdentifierName),
-                    NodeFactory.callExpressionNode(
-                        NodeFactory.memberExpressionNode(
-                            NodeFactory.literalNode(
-                                this.originalKeysIndexesInShuffledArray.join('|')
+            NodeFactory.variableDeclarationNode(
+                [
+                    NodeFactory.variableDeclaratorNode(
+                        NodeFactory.identifierNode(controllerIdentifierName),
+                        NodeFactory.callExpressionNode(
+                            NodeFactory.memberExpressionNode(
+                                NodeFactory.literalNode(
+                                    this.originalKeysIndexesInShuffledArray.join('|')
+                                ),
+                                NodeFactory.identifierNode('split')
                             ),
                             ),
-                            NodeFactory.identifierNode('split')
-                        ),
-                        [
-                            NodeFactory.literalNode('|')
-                        ]
+                            [
+                                NodeFactory.literalNode('|')
+                            ]
+                        )
+                    ),
+                    NodeFactory.variableDeclaratorNode(
+                        NodeFactory.identifierNode(indexIdentifierName),
+                        NodeFactory.literalNode(0)
                     )
                     )
-                ),
-                NodeFactory.variableDeclaratorNode(
-                    NodeFactory.identifierNode(indexIdentifierName),
-                    NodeFactory.literalNode(0)
-                )
-            ]),
+                ],
+                this.prevailingKindOfVariables
+            ),
             NodeFactory.whileStatementNode(
             NodeFactory.whileStatementNode(
                 NodeFactory.literalNode(true),
                 NodeFactory.literalNode(true),
                 NodeFactory.blockStatementNode([
                 NodeFactory.blockStatementNode([

+ 4 - 1
src/custom-nodes/control-flow-flattening-nodes/CallExpressionFunctionNode.ts

@@ -8,6 +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 { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -25,16 +26,18 @@ export class CallExpressionFunctionNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**

+ 4 - 1
src/custom-nodes/control-flow-flattening-nodes/LogicalExpressionFunctionNode.ts

@@ -8,6 +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 { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -25,16 +26,18 @@ export class LogicalExpressionFunctionNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**

+ 4 - 1
src/custom-nodes/control-flow-flattening-nodes/StringLiteralNode.ts

@@ -6,6 +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 { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -22,16 +23,18 @@ export class StringLiteralNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**

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

@@ -12,6 +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 { initializable } from '../../../decorators/Initializable';
 import { initializable } from '../../../decorators/Initializable';
 
 
@@ -47,16 +48,18 @@ export class CallExpressionControlFlowStorageCallNode extends AbstractCustomNode
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**

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

@@ -9,7 +9,9 @@ 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 { initializable } from '../../../decorators/Initializable';
 import { initializable } from '../../../decorators/Initializable';
 
 
@@ -26,18 +28,30 @@ 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 {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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions
+        @inject(ServiceIdentifiers.IOptions) options: IOptions,
+        @inject(ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer)
+            prevailingKindOfVariablesAnalyzer: IPrevailingKindOfVariablesAnalyzer
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+
+        this.prevailingKindOfVariables = prevailingKindOfVariablesAnalyzer.getPrevailingKind();
     }
     }
 
 
     /**
     /**
@@ -66,12 +80,15 @@ export class ControlFlowStorageNode extends AbstractCustomNode {
                 );
                 );
             });
             });
 
 
-        let structure: ESTree.Node = NodeFactory.variableDeclarationNode([
-            NodeFactory.variableDeclaratorNode(
-                NodeFactory.identifierNode(this.controlFlowStorage.getStorageId()),
-                NodeFactory.objectExpressionNode(propertyNodes)
-            )
-        ]);
+        let structure: ESTree.Node = NodeFactory.variableDeclarationNode(
+            [
+                NodeFactory.variableDeclaratorNode(
+                    NodeFactory.identifierNode(this.controlFlowStorage.getStorageId()),
+                    NodeFactory.objectExpressionNode(propertyNodes)
+                )
+            ],
+            this.prevailingKindOfVariables
+        );
 
 
         structure = NodeUtils.parentizeAst(structure);
         structure = NodeUtils.parentizeAst(structure);
 
 

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

@@ -8,6 +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 { initializable } from '../../../decorators/Initializable';
 import { initializable } from '../../../decorators/Initializable';
 
 
@@ -43,16 +44,18 @@ export class ExpressionWithOperatorControlFlowStorageCallNode extends AbstractCu
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**

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

@@ -6,6 +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 { initializable } from '../../../decorators/Initializable';
 import { initializable } from '../../../decorators/Initializable';
 
 
@@ -29,16 +30,18 @@ export class StringLiteralControlFlowStorageCallNode extends AbstractCustomNode
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**

+ 4 - 1
src/custom-nodes/dead-code-injection-nodes/BlockStatementDeadCodeInjectionNode.ts

@@ -8,6 +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 { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -31,16 +32,18 @@ export class BlockStatementDeadCodeInjectionNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**

+ 5 - 4
src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionCallNode.ts

@@ -1,13 +1,12 @@
 import { inject, injectable, } from 'inversify';
 import { inject, injectable, } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 
-import format from 'string-template';
-
 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 { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
+import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
 
 
 import { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -32,16 +31,18 @@ export class DebugProtectionFunctionCallNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -64,7 +65,7 @@ export class DebugProtectionFunctionCallNode extends AbstractCustomNode {
      * @returns {string}
      * @returns {string}
      */
      */
     protected getTemplate (): string {
     protected getTemplate (): string {
-        return format(DebugProtectionFunctionCallTemplate(), {
+        return this.templateFormatter.format(DebugProtectionFunctionCallTemplate(), {
             debugProtectionFunctionName: this.debugProtectionFunctionName,
             debugProtectionFunctionName: this.debugProtectionFunctionName,
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName
         });
         });

+ 5 - 4
src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionIntervalNode.ts

@@ -1,13 +1,12 @@
 import { inject, injectable, } from 'inversify';
 import { inject, injectable, } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 
-import format from 'string-template';
-
 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 { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
+import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
 
 
 import { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -26,16 +25,18 @@ export class DebugProtectionFunctionIntervalNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -56,7 +57,7 @@ export class DebugProtectionFunctionIntervalNode extends AbstractCustomNode {
      * @returns {string}
      * @returns {string}
      */
      */
     protected getTemplate (): string {
     protected getTemplate (): string {
-        return format(DebugProtectionFunctionIntervalTemplate(), {
+        return this.templateFormatter.format(DebugProtectionFunctionIntervalTemplate(), {
             debugProtectionFunctionName: this.debugProtectionFunctionName
             debugProtectionFunctionName: this.debugProtectionFunctionName
         });
         });
     }
     }

+ 5 - 4
src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionNode.ts

@@ -1,13 +1,12 @@
 import { inject, injectable, } from 'inversify';
 import { inject, injectable, } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 
-import format from 'string-template';
-
 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 { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
+import { ITemplateFormatter } from '../../interfaces/utils/ITemplateFormatter';
 
 
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 
 
@@ -30,16 +29,18 @@ export class DebugProtectionFunctionNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -64,7 +65,7 @@ export class DebugProtectionFunctionNode extends AbstractCustomNode {
             ? DebuggerTemplate()
             ? DebuggerTemplate()
             : DebuggerTemplateNoEval();
             : DebuggerTemplateNoEval();
 
 
-        return format(DebugProtectionFunctionTemplate(), {
+        return this.templateFormatter.format(DebugProtectionFunctionTemplate(), {
             debuggerTemplate,
             debuggerTemplate,
             debugProtectionFunctionName: this.debugProtectionFunctionName
             debugProtectionFunctionName: this.debugProtectionFunctionName
         });
         });

+ 13 - 4
src/custom-nodes/debug-protection-nodes/group/DebugProtectionCustomNodeGroup.ts

@@ -3,6 +3,7 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 
 import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
 import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
+import { TInitialData } from '../../../types/TInitialData';
 import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
 import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
 
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
@@ -16,7 +17,11 @@ import { CustomNode } from '../../../enums/custom-nodes/CustomNode';
 import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent';
 import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent';
 
 
 import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
 import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
+import { DebugProtectionFunctionNode } from '../DebugProtectionFunctionNode';
+import { DebugProtectionFunctionCallNode } from '../DebugProtectionFunctionCallNode';
+import { DebugProtectionFunctionIntervalNode } from '../DebugProtectionFunctionIntervalNode';
 import { NodeAppender } from '../../../node/NodeAppender';
 import { NodeAppender } from '../../../node/NodeAppender';
+import { NodeCallsControllerFunctionNode } from '../../node-calls-controller-nodes/NodeCallsControllerFunctionNode';
 import { NodeGuards } from '../../../node/NodeGuards';
 import { NodeGuards } from '../../../node/NodeGuards';
 
 
 @injectable()
 @injectable()
@@ -107,10 +112,14 @@ export class DebugProtectionCustomNodeGroup extends AbstractCustomNodeGroup {
         const debugProtectionFunctionName: string = this.identifierNamesGenerator.generate();
         const debugProtectionFunctionName: string = this.identifierNamesGenerator.generate();
         const callsControllerFunctionName: string = this.identifierNamesGenerator.generate();
         const callsControllerFunctionName: string = this.identifierNamesGenerator.generate();
 
 
-        const debugProtectionFunctionNode: ICustomNode = this.customNodeFactory(CustomNode.DebugProtectionFunctionNode);
-        const debugProtectionFunctionCallNode: ICustomNode = this.customNodeFactory(CustomNode.DebugProtectionFunctionCallNode);
-        const debugProtectionFunctionIntervalNode: ICustomNode = this.customNodeFactory(CustomNode.DebugProtectionFunctionIntervalNode);
-        const nodeCallsControllerFunctionNode: ICustomNode = this.customNodeFactory(CustomNode.NodeCallsControllerFunctionNode);
+        const debugProtectionFunctionNode: ICustomNode<TInitialData<DebugProtectionFunctionNode>> =
+            this.customNodeFactory(CustomNode.DebugProtectionFunctionNode);
+        const debugProtectionFunctionCallNode: ICustomNode<TInitialData<DebugProtectionFunctionCallNode>> =
+            this.customNodeFactory(CustomNode.DebugProtectionFunctionCallNode);
+        const debugProtectionFunctionIntervalNode: ICustomNode<TInitialData<DebugProtectionFunctionIntervalNode>> =
+            this.customNodeFactory(CustomNode.DebugProtectionFunctionIntervalNode);
+        const nodeCallsControllerFunctionNode: ICustomNode<TInitialData<NodeCallsControllerFunctionNode>> =
+            this.customNodeFactory(CustomNode.NodeCallsControllerFunctionNode);
 
 
         debugProtectionFunctionNode.initialize(debugProtectionFunctionName);
         debugProtectionFunctionNode.initialize(debugProtectionFunctionName);
         debugProtectionFunctionCallNode.initialize(debugProtectionFunctionName, callsControllerFunctionName);
         debugProtectionFunctionCallNode.initialize(debugProtectionFunctionName, callsControllerFunctionName);

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

@@ -1,14 +1,13 @@
 import { inject, injectable, } from 'inversify';
 import { inject, injectable, } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 
-import format from 'string-template';
-
 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 { 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 { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 
 
@@ -35,18 +34,20 @@ export class DomainLockNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
-     * @param {ICryptUtils} cryptUtils
      * @param {IOptions} options
      * @param {IOptions} options
+     * @param {ICryptUtils} cryptUtils
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
+        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.ICryptUtils) cryptUtils: ICryptUtils,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions
+        @inject(ServiceIdentifiers.IOptions) options: IOptions,
+        @inject(ServiceIdentifiers.ICryptUtils) cryptUtils: ICryptUtils
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
 
 
         this.cryptUtils = cryptUtils;
         this.cryptUtils = cryptUtils;
     }
     }
@@ -78,7 +79,7 @@ export class DomainLockNode extends AbstractCustomNode {
             ? this.getGlobalVariableTemplate()
             ? this.getGlobalVariableTemplate()
             : GlobalVariableNoEvalTemplate();
             : GlobalVariableNoEvalTemplate();
 
 
-        return format(DomainLockNodeTemplate(), {
+        return this.templateFormatter.format(DomainLockNodeTemplate(), {
             domainLockFunctionName: this.identifierNamesGenerator.generate(),
             domainLockFunctionName: this.identifierNamesGenerator.generate(),
             diff: diff,
             diff: diff,
             domains: hiddenDomainsString,
             domains: hiddenDomainsString,

+ 7 - 2
src/custom-nodes/domain-lock-nodes/group/DomainLockCustomNodeGroup.ts

@@ -3,6 +3,7 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 
 import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
 import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
+import { TInitialData } from '../../../types/TInitialData';
 import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
 import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
 
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
@@ -16,7 +17,9 @@ import { CustomNode } from '../../../enums/custom-nodes/CustomNode';
 import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent';
 import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent';
 
 
 import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
 import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
+import { DomainLockNode } from '../DomainLockNode';
 import { NodeAppender } from '../../../node/NodeAppender';
 import { NodeAppender } from '../../../node/NodeAppender';
+import { NodeCallsControllerFunctionNode } from '../../node-calls-controller-nodes/NodeCallsControllerFunctionNode';
 
 
 @injectable()
 @injectable()
 export class DomainLockCustomNodeGroup extends AbstractCustomNodeGroup {
 export class DomainLockCustomNodeGroup extends AbstractCustomNodeGroup {
@@ -90,8 +93,10 @@ export class DomainLockCustomNodeGroup extends AbstractCustomNodeGroup {
 
 
         const callsControllerFunctionName: string = this.identifierNamesGenerator.generate();
         const callsControllerFunctionName: string = this.identifierNamesGenerator.generate();
 
 
-        const domainLockNode: ICustomNode = this.customNodeFactory(CustomNode.DomainLockNode);
-        const nodeCallsControllerFunctionNode: ICustomNode = this.customNodeFactory(CustomNode.NodeCallsControllerFunctionNode);
+        const domainLockNode: ICustomNode<TInitialData<DomainLockNode>> =
+            this.customNodeFactory(CustomNode.DomainLockNode);
+        const nodeCallsControllerFunctionNode: ICustomNode<TInitialData<NodeCallsControllerFunctionNode>> =
+            this.customNodeFactory(CustomNode.NodeCallsControllerFunctionNode);
 
 
         domainLockNode.initialize(callsControllerFunctionName);
         domainLockNode.initialize(callsControllerFunctionName);
         nodeCallsControllerFunctionNode.initialize(this.appendEvent, callsControllerFunctionName);
         nodeCallsControllerFunctionNode.initialize(this.appendEvent, callsControllerFunctionName);

+ 6 - 5
src/custom-nodes/node-calls-controller-nodes/NodeCallsControllerFunctionNode.ts

@@ -1,8 +1,6 @@
 import { inject, injectable, } from 'inversify';
 import { inject, injectable, } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 
-import format from 'string-template';
-
 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';
 
 
@@ -20,6 +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';
 
 
 @injectable()
 @injectable()
 export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
 export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
@@ -37,16 +36,18 @@ export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -71,7 +72,7 @@ export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
     protected getTemplate (): string {
     protected getTemplate (): string {
         if (this.appendEvent === ObfuscationEvent.AfterObfuscation) {
         if (this.appendEvent === ObfuscationEvent.AfterObfuscation) {
             return JavaScriptObfuscator.obfuscate(
             return JavaScriptObfuscator.obfuscate(
-                format(SingleNodeCallControllerTemplate(), {
+                this.templateFormatter.format(SingleNodeCallControllerTemplate(), {
                     singleNodeCallControllerFunctionName: this.callsControllerFunctionName
                     singleNodeCallControllerFunctionName: this.callsControllerFunctionName
                 }),
                 }),
                 {
                 {
@@ -83,7 +84,7 @@ export class NodeCallsControllerFunctionNode extends AbstractCustomNode {
             ).getObfuscatedCode();
             ).getObfuscatedCode();
         }
         }
 
 
-        return format(SingleNodeCallControllerTemplate(), {
+        return this.templateFormatter.format(SingleNodeCallControllerTemplate(), {
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName
         });
         });
     }
     }

+ 29 - 10
src/custom-nodes/object-expression-keys-transformer-nodes/BasePropertiesExtractorObjectExpressionHostNode.ts

@@ -1,29 +1,45 @@
 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 { 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 {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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions
+        @inject(ServiceIdentifiers.IOptions) options: IOptions,
+        @inject(ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer)
+            prevailingKindOfVariablesAnalyzer: IPrevailingKindOfVariablesAnalyzer,
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
+
+        this.prevailingKindOfVariables = prevailingKindOfVariablesAnalyzer.getPrevailingKind();
     }
     }
 
 
     public initialize (): void {}
     public initialize (): void {}
@@ -32,14 +48,17 @@ export class BasePropertiesExtractorObjectExpressionHostNode extends AbstractCus
      * @returns {TStatement[]}
      * @returns {TStatement[]}
      */
      */
     protected getNodeStructure (): TStatement[] {
     protected getNodeStructure (): TStatement[] {
-        const structure: TStatement = NodeFactory.variableDeclarationNode([
-            NodeFactory.variableDeclaratorNode(
-                NodeFactory.identifierNode(
-                    this.identifierNamesGenerator.generate()
-                ),
-                NodeFactory.objectExpressionNode([])
-            )
-        ]);
+        const structure: TStatement = NodeFactory.variableDeclarationNode(
+            [
+                NodeFactory.variableDeclaratorNode(
+                    NodeFactory.identifierNode(
+                        this.identifierNamesGenerator.generate()
+                    ),
+                    NodeFactory.objectExpressionNode([])
+                )
+            ],
+            this.prevailingKindOfVariables
+        );
 
 
         return [structure];
         return [structure];
     }
     }

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

@@ -1,14 +1,13 @@
 import { inject, injectable, } from 'inversify';
 import { inject, injectable, } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 
-import format from 'string-template';
-
 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 { 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 { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -35,18 +34,20 @@ export class SelfDefendingUnicodeNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
-     * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
      * @param {IOptions} options
      * @param {IOptions} options
+     * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
+        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions
+        @inject(ServiceIdentifiers.IOptions) options: IOptions,
+        @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
 
 
         this.escapeSequenceEncoder = escapeSequenceEncoder;
         this.escapeSequenceEncoder = escapeSequenceEncoder;
     }
     }
@@ -70,7 +71,7 @@ export class SelfDefendingUnicodeNode extends AbstractCustomNode {
      */
      */
     protected getTemplate (): string {
     protected getTemplate (): string {
         return JavaScriptObfuscator.obfuscate(
         return JavaScriptObfuscator.obfuscate(
-            format(SelfDefendingTemplate(this.escapeSequenceEncoder), {
+            this.templateFormatter.format(SelfDefendingTemplate(this.escapeSequenceEncoder), {
                 selfDefendingFunctionName: this.identifierNamesGenerator.generate(),
                 selfDefendingFunctionName: this.identifierNamesGenerator.generate(),
                 singleNodeCallControllerFunctionName: this.callsControllerFunctionName
                 singleNodeCallControllerFunctionName: this.callsControllerFunctionName
             }),
             }),

+ 7 - 2
src/custom-nodes/self-defending-nodes/group/SelfDefendingCustomNodeGroup.ts

@@ -3,6 +3,7 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 
 import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
 import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
+import { TInitialData } from '../../../types/TInitialData';
 import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
 import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
 
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
@@ -17,6 +18,8 @@ import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent
 
 
 import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
 import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
 import { NodeAppender } from '../../../node/NodeAppender';
 import { NodeAppender } from '../../../node/NodeAppender';
+import { NodeCallsControllerFunctionNode } from '../../node-calls-controller-nodes/NodeCallsControllerFunctionNode';
+import { SelfDefendingUnicodeNode } from '../SelfDefendingUnicodeNode';
 
 
 @injectable()
 @injectable()
 export class SelfDefendingCustomNodeGroup extends AbstractCustomNodeGroup {
 export class SelfDefendingCustomNodeGroup extends AbstractCustomNodeGroup {
@@ -90,8 +93,10 @@ export class SelfDefendingCustomNodeGroup extends AbstractCustomNodeGroup {
 
 
         const callsControllerFunctionName: string = this.identifierNamesGenerator.generate();
         const callsControllerFunctionName: string = this.identifierNamesGenerator.generate();
 
 
-        const selfDefendingUnicodeNode: ICustomNode = this.customNodeFactory(CustomNode.SelfDefendingUnicodeNode);
-        const nodeCallsControllerFunctionNode: ICustomNode = this.customNodeFactory(CustomNode.NodeCallsControllerFunctionNode);
+        const selfDefendingUnicodeNode: ICustomNode<TInitialData<SelfDefendingUnicodeNode>> =
+            this.customNodeFactory(CustomNode.SelfDefendingUnicodeNode);
+        const nodeCallsControllerFunctionNode: ICustomNode<TInitialData<NodeCallsControllerFunctionNode>> =
+            this.customNodeFactory(CustomNode.NodeCallsControllerFunctionNode);
 
 
         selfDefendingUnicodeNode.initialize(callsControllerFunctionName);
         selfDefendingUnicodeNode.initialize(callsControllerFunctionName);
         nodeCallsControllerFunctionNode.initialize(this.appendEvent, callsControllerFunctionName);
         nodeCallsControllerFunctionNode.initialize(this.appendEvent, callsControllerFunctionName);

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

@@ -1,14 +1,13 @@
 import { inject, injectable, } from 'inversify';
 import { inject, injectable, } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 
-import format from 'string-template';
-
 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 { 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 { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
 import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
 import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
@@ -50,18 +49,20 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
-     * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
      * @param {IOptions} options
      * @param {IOptions} options
+     * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
+        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions
+        @inject(ServiceIdentifiers.IOptions) options: IOptions,
+        @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
 
 
         this.escapeSequenceEncoder = escapeSequenceEncoder;
         this.escapeSequenceEncoder = escapeSequenceEncoder;
     }
     }
@@ -92,7 +93,7 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
         const decodeNodeTemplate: string = this.getDecodeStringArrayTemplate();
         const decodeNodeTemplate: string = this.getDecodeStringArrayTemplate();
 
 
         return JavaScriptObfuscator.obfuscate(
         return JavaScriptObfuscator.obfuscate(
-            format(StringArrayCallsWrapperTemplate(), {
+            this.templateFormatter.format(StringArrayCallsWrapperTemplate(), {
                 decodeNodeTemplate,
                 decodeNodeTemplate,
                 stringArrayCallsWrapperName: this.stringArrayCallsWrapperName,
                 stringArrayCallsWrapperName: this.stringArrayCallsWrapperName,
                 stringArrayName: this.stringArrayName
                 stringArrayName: this.stringArrayName
@@ -113,13 +114,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 = format(AtobTemplate(), { globalVariableTemplate });
+        const atobPolyfill: string = this.templateFormatter.format(AtobTemplate(), { globalVariableTemplate });
 
 
         let decodeStringArrayTemplate: string = '';
         let decodeStringArrayTemplate: string = '';
         let selfDefendingCode: string = '';
         let selfDefendingCode: string = '';
 
 
         if (this.options.selfDefending) {
         if (this.options.selfDefending) {
-            selfDefendingCode = format(
+            selfDefendingCode = this.templateFormatter.format(
                 SelfDefendingTemplate(
                 SelfDefendingTemplate(
                     this.randomGenerator,
                     this.randomGenerator,
                     this.escapeSequenceEncoder
                     this.escapeSequenceEncoder
@@ -133,7 +134,7 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
 
 
         switch (this.options.stringArrayEncoding) {
         switch (this.options.stringArrayEncoding) {
             case StringArrayEncoding.Rc4:
             case StringArrayEncoding.Rc4:
-                decodeStringArrayTemplate = format(
+                decodeStringArrayTemplate = this.templateFormatter.format(
                     StringArrayRc4DecodeNodeTemplate(this.randomGenerator),
                     StringArrayRc4DecodeNodeTemplate(this.randomGenerator),
                     {
                     {
                         atobPolyfill,
                         atobPolyfill,
@@ -146,7 +147,7 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
                 break;
                 break;
 
 
             case StringArrayEncoding.Base64:
             case StringArrayEncoding.Base64:
-                decodeStringArrayTemplate = format(
+                decodeStringArrayTemplate = this.templateFormatter.format(
                     StringArrayBase64DecodeNodeTemplate(this.randomGenerator),
                     StringArrayBase64DecodeNodeTemplate(this.randomGenerator),
                     {
                     {
                         atobPolyfill,
                         atobPolyfill,

+ 5 - 4
src/custom-nodes/string-array-nodes/StringArrayNode.ts

@@ -1,14 +1,13 @@
 import { inject, injectable, } from 'inversify';
 import { inject, injectable, } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 
-import format from 'string-template';
-
 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 { TStringArrayStorage } from '../../types/storages/TStringArrayStorage';
 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 { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -40,16 +39,18 @@ export class StringArrayNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @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.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
     }
     }
 
 
     /**
     /**
@@ -87,7 +88,7 @@ export class StringArrayNode extends AbstractCustomNode {
      * @returns {string}
      * @returns {string}
      */
      */
     protected getTemplate (): string {
     protected getTemplate (): string {
-        return format(StringArrayTemplate(), {
+        return this.templateFormatter.format(StringArrayTemplate(), {
             stringArrayName: this.stringArrayName,
             stringArrayName: this.stringArrayName,
             stringArray: this.stringArrayStorage.toString()
             stringArray: this.stringArrayStorage.toString()
         });
         });

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

@@ -1,14 +1,13 @@
 import { inject, injectable, } from 'inversify';
 import { inject, injectable, } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 
-import format from 'string-template';
-
 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 { 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 { initializable } from '../../decorators/Initializable';
 import { initializable } from '../../decorators/Initializable';
 
 
@@ -43,18 +42,20 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
 
 
     /**
     /**
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
      * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
+     * @param {ITemplateFormatter} templateFormatter
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
-     * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
      * @param {IOptions} options
      * @param {IOptions} options
+     * @param {IEscapeSequenceEncoder} escapeSequenceEncoder
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
         @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
             identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
+        @inject(ServiceIdentifiers.ITemplateFormatter) templateFormatter: ITemplateFormatter,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions
+        @inject(ServiceIdentifiers.IOptions) options: IOptions,
+        @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
     ) {
     ) {
-        super(identifierNamesGeneratorFactory, randomGenerator, options);
+        super(identifierNamesGeneratorFactory, templateFormatter, randomGenerator, options);
 
 
         this.escapeSequenceEncoder = escapeSequenceEncoder;
         this.escapeSequenceEncoder = escapeSequenceEncoder;
     }
     }
@@ -88,7 +89,7 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
         let code: string = '';
         let code: string = '';
 
 
         if (this.options.selfDefending) {
         if (this.options.selfDefending) {
-            code = format(SelfDefendingTemplate(this.escapeSequenceEncoder), {
+            code = this.templateFormatter.format(SelfDefendingTemplate(this.escapeSequenceEncoder), {
                 timesName,
                 timesName,
                 whileFunctionName
                 whileFunctionName
             });
             });
@@ -97,7 +98,7 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
         }
         }
 
 
         return JavaScriptObfuscator.obfuscate(
         return JavaScriptObfuscator.obfuscate(
-            format(StringArrayRotateFunctionTemplate(), {
+            this.templateFormatter.format(StringArrayRotateFunctionTemplate(), {
                 code,
                 code,
                 timesName,
                 timesName,
                 stringArrayName: this.stringArrayName,
                 stringArrayName: this.stringArrayName,

+ 10 - 3
src/custom-nodes/string-array-nodes/group/StringArrayCustomNodeGroup.ts

@@ -3,6 +3,7 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 
 import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
 import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
 import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
+import { TInitialData } from '../../../types/TInitialData';
 import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
 import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
 import { TStringArrayStorage } from '../../../types/storages/TStringArrayStorage';
 import { TStringArrayStorage } from '../../../types/storages/TStringArrayStorage';
 
 
@@ -18,6 +19,9 @@ import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent
 
 
 import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
 import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
 import { NodeAppender } from '../../../node/NodeAppender';
 import { NodeAppender } from '../../../node/NodeAppender';
+import { StringArrayNode } from '../StringArrayNode';
+import { StringArrayCallsWrapper } from '../StringArrayCallsWrapper';
+import { StringArrayRotateFunctionNode } from '../StringArrayRotateFunctionNode';
 
 
 @injectable()
 @injectable()
 export class StringArrayCustomNodeGroup extends AbstractCustomNodeGroup {
 export class StringArrayCustomNodeGroup extends AbstractCustomNodeGroup {
@@ -95,9 +99,12 @@ export class StringArrayCustomNodeGroup extends AbstractCustomNodeGroup {
             return;
             return;
         }
         }
 
 
-        const stringArrayNode: ICustomNode = this.customNodeFactory(CustomNode.StringArrayNode);
-        const stringArrayCallsWrapper: ICustomNode = this.customNodeFactory(CustomNode.StringArrayCallsWrapper);
-        const stringArrayRotateFunctionNode: ICustomNode = this.customNodeFactory(CustomNode.StringArrayRotateFunctionNode);
+        const stringArrayNode: ICustomNode<TInitialData<StringArrayNode>> =
+            this.customNodeFactory(CustomNode.StringArrayNode);
+        const stringArrayCallsWrapper: ICustomNode<TInitialData<StringArrayCallsWrapper>> =
+            this.customNodeFactory(CustomNode.StringArrayCallsWrapper);
+        const stringArrayRotateFunctionNode: ICustomNode<TInitialData<StringArrayRotateFunctionNode>> =
+            this.customNodeFactory(CustomNode.StringArrayRotateFunctionNode);
 
 
         const stringArrayStorageId: string = this.stringArrayStorage.getStorageId();
         const stringArrayStorageId: string = this.stringArrayStorage.getStorageId();
 
 

+ 2 - 2
src/interfaces/analyzers/IAnalyzer.d.ts

@@ -3,7 +3,7 @@ import * as ESTree from 'estree';
 export interface IAnalyzer <T> {
 export interface IAnalyzer <T> {
     /**
     /**
      * @param {Program} astTree
      * @param {Program} astTree
-     * @returns {T[]}
+     * @returns {T}
      */
      */
-    analyze (astTree: ESTree.Program): T[];
+    analyze (astTree: ESTree.Program): T;
 }
 }

+ 1 - 1
src/interfaces/analyzers/calls-graph-analyzer/ICallsGraphAnalyzer.d.ts

@@ -3,7 +3,7 @@ import * as ESTree from 'estree';
 import { IAnalyzer } from '../IAnalyzer';
 import { IAnalyzer } from '../IAnalyzer';
 import { ICallsGraphData } from './ICallsGraphData';
 import { ICallsGraphData } from './ICallsGraphData';
 
 
-export interface ICallsGraphAnalyzer extends IAnalyzer<ICallsGraphData> {
+export interface ICallsGraphAnalyzer extends IAnalyzer<ICallsGraphData[]> {
     /**
     /**
      * @param {Program} astTree
      * @param {Program} astTree
      * @returns {ICallsGraphData[]}
      * @returns {ICallsGraphData[]}

+ 15 - 0
src/interfaces/analyzers/calls-graph-analyzer/IPrevailingKindOfVariablesAnalyzer.d.ts

@@ -0,0 +1,15 @@
+import * as ESTree from 'estree';
+
+import { IAnalyzer } from '../IAnalyzer';
+
+export interface IPrevailingKindOfVariablesAnalyzer extends IAnalyzer<void> {
+    /**
+     * @param {Program} astTree
+     */
+    analyze (astTree: ESTree.Program): void;
+
+    /**
+     * @returns {ESTree.VariableDeclaration['kind']}
+     */
+    getPrevailingKind (): ESTree.VariableDeclaration['kind'];
+}

+ 3 - 1
src/interfaces/custom-nodes/ICustomNode.d.ts

@@ -2,7 +2,9 @@ import { TStatement } from '../../types/node/TStatement';
 
 
 import { IInitializable } from '../IInitializable';
 import { IInitializable } from '../IInitializable';
 
 
-export interface ICustomNode extends IInitializable<any[]> {
+export interface ICustomNode <
+    TInitialData extends any[] = any[]
+> extends IInitializable<TInitialData> {
     /**
     /**
      * @returns ESTree.Node[]
      * @returns ESTree.Node[]
      */
      */

+ 6 - 0
src/interfaces/utils/IArrayUtils.d.ts

@@ -5,6 +5,12 @@ export interface IArrayUtils {
      */
      */
     createWithRange (length: number): number[];
     createWithRange (length: number): number[];
 
 
+    /**
+     * @param {T[]} array
+     * @returns {T | null}
+     */
+    findMostOccurringElement <T extends string | number> (array: T[]): T | null;
+
     /**
     /**
      * @param array
      * @param array
      * @param times
      * @param times

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

@@ -0,0 +1,13 @@
+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;
+}

+ 4 - 3
src/node-transformers/control-flow-transformers/BlockStatementControlFlowTransformer.ts

@@ -5,6 +5,7 @@ import * as estraverse from 'estraverse';
 import * as ESTree from 'estree';
 import * as ESTree from 'estree';
 
 
 import { TControlFlowCustomNodeFactory } from '../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 import { TControlFlowCustomNodeFactory } from '../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
+import { TInitialData } from '../../types/TInitialData';
 import { TStatement } from '../../types/node/TStatement';
 import { TStatement } from '../../types/node/TStatement';
 
 
 import { IArrayUtils } from '../../interfaces/utils/IArrayUtils';
 import { IArrayUtils } from '../../interfaces/utils/IArrayUtils';
@@ -17,6 +18,7 @@ import { ControlFlowCustomNode } from '../../enums/custom-nodes/ControlFlowCusto
 import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
+import { BlockStatementControlFlowFlatteningNode } from '../../custom-nodes/control-flow-flattening-nodes/BlockStatementControlFlowFlatteningNode';
 import { NodeGuards } from '../../node/NodeGuards';
 import { NodeGuards } from '../../node/NodeGuards';
 import { NodeUtils } from '../../node/NodeUtils';
 import { NodeUtils } from '../../node/NodeUtils';
 
 
@@ -131,9 +133,8 @@ export class BlockStatementControlFlowTransformer extends AbstractNodeTransforme
         const originalKeys: number[] = this.arrayUtils.createWithRange(blockStatementBody.length);
         const originalKeys: number[] = this.arrayUtils.createWithRange(blockStatementBody.length);
         const shuffledKeys: number[] = this.arrayUtils.shuffle(originalKeys);
         const shuffledKeys: number[] = this.arrayUtils.shuffle(originalKeys);
         const originalKeysIndexesInShuffledArray: number[] = originalKeys.map((key: number) => shuffledKeys.indexOf(key));
         const originalKeysIndexesInShuffledArray: number[] = originalKeys.map((key: number) => shuffledKeys.indexOf(key));
-        const blockStatementControlFlowFlatteningCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
-            ControlFlowCustomNode.BlockStatementControlFlowFlatteningNode
-        );
+        const blockStatementControlFlowFlatteningCustomNode: ICustomNode<TInitialData<BlockStatementControlFlowFlatteningNode>> =
+            this.controlFlowCustomNodeFactory(ControlFlowCustomNode.BlockStatementControlFlowFlatteningNode);
 
 
         blockStatementControlFlowFlatteningCustomNode.initialize(
         blockStatementControlFlowFlatteningCustomNode.initialize(
             blockStatementBody,
             blockStatementBody,

+ 4 - 3
src/node-transformers/control-flow-transformers/FunctionControlFlowTransformer.ts

@@ -8,6 +8,7 @@ import { TControlFlowCustomNodeFactory } from '../../types/container/custom-node
 import { TControlFlowReplacerFactory } from '../../types/container/node-transformers/TControlFlowReplacerFactory';
 import { TControlFlowReplacerFactory } from '../../types/container/node-transformers/TControlFlowReplacerFactory';
 import { TControlFlowStorage } from '../../types/storages/TControlFlowStorage';
 import { TControlFlowStorage } from '../../types/storages/TControlFlowStorage';
 import { TControlFlowStorageFactory } from '../../types/container/node-transformers/TControlFlowStorageFactory';
 import { TControlFlowStorageFactory } from '../../types/container/node-transformers/TControlFlowStorageFactory';
+import { TInitialData } from '../../types/TInitialData';
 import { TNodeWithStatements } from '../../types/node/TNodeWithStatements';
 import { TNodeWithStatements } from '../../types/node/TNodeWithStatements';
 
 
 import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
 import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
@@ -21,6 +22,7 @@ import { NodeType } from '../../enums/node/NodeType';
 import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
+import { ControlFlowStorageNode } from '../../custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ControlFlowStorageNode';
 import { NodeAppender } from '../../node/NodeAppender';
 import { NodeAppender } from '../../node/NodeAppender';
 import { NodeGuards } from '../../node/NodeGuards';
 import { NodeGuards } from '../../node/NodeGuards';
 import { NodeMetadata } from '../../node/NodeMetadata';
 import { NodeMetadata } from '../../node/NodeMetadata';
@@ -151,9 +153,8 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
             return functionNode;
             return functionNode;
         }
         }
 
 
-        const controlFlowStorageCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
-            ControlFlowCustomNode.ControlFlowStorageNode
-        );
+        const controlFlowStorageCustomNode: ICustomNode<TInitialData<ControlFlowStorageNode>> =
+            this.controlFlowCustomNodeFactory(ControlFlowCustomNode.ControlFlowStorageNode);
 
 
         controlFlowStorageCustomNode.initialize(controlFlowStorage);
         controlFlowStorageCustomNode.initialize(controlFlowStorage);
         NodeAppender.prepend(hostNode, controlFlowStorageCustomNode.getNode());
         NodeAppender.prepend(hostNode, controlFlowStorageCustomNode.getNode());

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

@@ -5,6 +5,7 @@ import * as ESTree from 'estree';
 
 
 import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
 import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
+import { TInitialData } from '../../../types/TInitialData';
 
 
 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';
@@ -12,6 +13,7 @@ import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 
 
 import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCustomNode';
 import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCustomNode';
 
 
+import { BinaryExpressionFunctionNode } from '../../../custom-nodes/control-flow-flattening-nodes/BinaryExpressionFunctionNode';
 import { ExpressionWithOperatorControlFlowReplacer } from './ExpressionWithOperatorControlFlowReplacer';
 import { ExpressionWithOperatorControlFlowReplacer } from './ExpressionWithOperatorControlFlowReplacer';
 
 
 @injectable()
 @injectable()
@@ -46,17 +48,16 @@ export class BinaryExpressionControlFlowReplacer extends ExpressionWithOperatorC
         parentNode: ESTree.Node,
         parentNode: ESTree.Node,
         controlFlowStorage: TControlFlowStorage
         controlFlowStorage: TControlFlowStorage
     ): ESTree.Node {
     ): ESTree.Node {
-        const replacerId: string = binaryExpressionNode.operator;
-        const binaryExpressionFunctionCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
-            ControlFlowCustomNode.BinaryExpressionFunctionNode
-        );
+        const operator: ESTree.BinaryOperator = binaryExpressionNode.operator;
+        const binaryExpressionFunctionCustomNode: ICustomNode<TInitialData<BinaryExpressionFunctionNode>> =
+            this.controlFlowCustomNodeFactory(ControlFlowCustomNode.BinaryExpressionFunctionNode);
 
 
-        binaryExpressionFunctionCustomNode.initialize(replacerId);
+        binaryExpressionFunctionCustomNode.initialize(operator);
 
 
         const storageKey: string = this.insertCustomNodeToControlFlowStorage(
         const storageKey: string = this.insertCustomNodeToControlFlowStorage(
             binaryExpressionFunctionCustomNode,
             binaryExpressionFunctionCustomNode,
             controlFlowStorage,
             controlFlowStorage,
-            replacerId,
+            operator,
             BinaryExpressionControlFlowReplacer.usingExistingIdentifierChance
             BinaryExpressionControlFlowReplacer.usingExistingIdentifierChance
         );
         );
 
 

+ 7 - 6
src/node-transformers/control-flow-transformers/control-flow-replacers/CallExpressionControlFlowReplacer.ts

@@ -5,6 +5,7 @@ import * as ESTree from 'estree';
 
 
 import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
 import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
+import { TInitialData } from '../../../types/TInitialData';
 import { TStatement } from '../../../types/node/TStatement';
 import { TStatement } from '../../../types/node/TStatement';
 
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
@@ -14,6 +15,8 @@ import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCustomNode';
 import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCustomNode';
 
 
 import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
 import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
+import { CallExpressionFunctionNode } from '../../../custom-nodes/control-flow-flattening-nodes/CallExpressionFunctionNode';
+import { CallExpressionControlFlowStorageCallNode } from '../../../custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/CallExpressionControlFlowStorageCallNode';
 import { NodeGuards } from '../../../node/NodeGuards';
 import { NodeGuards } from '../../../node/NodeGuards';
 
 
 @injectable()
 @injectable()
@@ -55,9 +58,8 @@ export class CallExpressionControlFlowReplacer extends AbstractControlFlowReplac
         }
         }
 
 
         const replacerId: string = String(callExpressionNode.arguments.length);
         const replacerId: string = String(callExpressionNode.arguments.length);
-        const callExpressionFunctionCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
-            ControlFlowCustomNode.CallExpressionFunctionNode
-        );
+        const callExpressionFunctionCustomNode: ICustomNode<TInitialData<CallExpressionFunctionNode>> =
+            this.controlFlowCustomNodeFactory(ControlFlowCustomNode.CallExpressionFunctionNode);
         const expressionArguments: (ESTree.Expression | ESTree.SpreadElement)[] = callExpressionNode.arguments;
         const expressionArguments: (ESTree.Expression | ESTree.SpreadElement)[] = callExpressionNode.arguments;
 
 
         callExpressionFunctionCustomNode.initialize(expressionArguments);
         callExpressionFunctionCustomNode.initialize(expressionArguments);
@@ -90,9 +92,8 @@ export class CallExpressionControlFlowReplacer extends AbstractControlFlowReplac
         callee: ESTree.Expression,
         callee: ESTree.Expression,
         expressionArguments: (ESTree.Expression | ESTree.SpreadElement)[]
         expressionArguments: (ESTree.Expression | ESTree.SpreadElement)[]
     ): ESTree.Node {
     ): ESTree.Node {
-        const controlFlowStorageCallCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
-            ControlFlowCustomNode.CallExpressionControlFlowStorageCallNode
-        );
+        const controlFlowStorageCallCustomNode: ICustomNode<TInitialData<CallExpressionControlFlowStorageCallNode>> =
+            this.controlFlowCustomNodeFactory(ControlFlowCustomNode.CallExpressionControlFlowStorageCallNode);
 
 
         controlFlowStorageCallCustomNode.initialize(controlFlowStorageId, storageKey, callee, expressionArguments);
         controlFlowStorageCallCustomNode.initialize(controlFlowStorageId, storageKey, callee, expressionArguments);
 
 

+ 4 - 3
src/node-transformers/control-flow-transformers/control-flow-replacers/ExpressionWithOperatorControlFlowReplacer.ts

@@ -4,6 +4,7 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 import * as ESTree from 'estree';
 import * as ESTree from 'estree';
 
 
 import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
+import { TInitialData } from '../../../types/TInitialData';
 import { TStatement } from '../../../types/node/TStatement';
 import { TStatement } from '../../../types/node/TStatement';
 
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
@@ -13,6 +14,7 @@ import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCustomNode';
 import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCustomNode';
 
 
 import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
 import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
+import { ExpressionWithOperatorControlFlowStorageCallNode } from '../../../custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ExpressionWithOperatorControlFlowStorageCallNode';
 import { NodeGuards } from '../../../node/NodeGuards';
 import { NodeGuards } from '../../../node/NodeGuards';
 
 
 @injectable()
 @injectable()
@@ -44,9 +46,8 @@ export abstract class ExpressionWithOperatorControlFlowReplacer extends Abstract
         leftExpression: ESTree.Expression,
         leftExpression: ESTree.Expression,
         rightExpression: ESTree.Expression
         rightExpression: ESTree.Expression
     ): ESTree.Node {
     ): ESTree.Node {
-        const controlFlowStorageCallCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
-            ControlFlowCustomNode.ExpressionWithOperatorControlFlowStorageCallNode
-        );
+        const controlFlowStorageCallCustomNode: ICustomNode<TInitialData<ExpressionWithOperatorControlFlowStorageCallNode>> =
+            this.controlFlowCustomNodeFactory(ControlFlowCustomNode.ExpressionWithOperatorControlFlowStorageCallNode);
 
 
         controlFlowStorageCallCustomNode.initialize(controlFlowStorageId, storageKey, leftExpression, rightExpression);
         controlFlowStorageCallCustomNode.initialize(controlFlowStorageId, storageKey, leftExpression, rightExpression);
 
 

+ 7 - 6
src/node-transformers/control-flow-transformers/control-flow-replacers/LogicalExpressionControlFlowReplacer.ts

@@ -5,6 +5,7 @@ import * as ESTree from 'estree';
 
 
 import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
 import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
+import { TInitialData } from '../../../types/TInitialData';
 
 
 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';
@@ -13,6 +14,7 @@ import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCustomNode';
 import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCustomNode';
 
 
 import { ExpressionWithOperatorControlFlowReplacer } from './ExpressionWithOperatorControlFlowReplacer';
 import { ExpressionWithOperatorControlFlowReplacer } from './ExpressionWithOperatorControlFlowReplacer';
+import { LogicalExpressionFunctionNode } from '../../../custom-nodes/control-flow-flattening-nodes/LogicalExpressionFunctionNode';
 import { NodeGuards } from '../../../node/NodeGuards';
 import { NodeGuards } from '../../../node/NodeGuards';
 import { NodeUtils } from '../../../node/NodeUtils';
 import { NodeUtils } from '../../../node/NodeUtils';
 
 
@@ -52,17 +54,16 @@ export class LogicalExpressionControlFlowReplacer extends ExpressionWithOperator
             return logicalExpressionNode;
             return logicalExpressionNode;
         }
         }
 
 
-        const replacerId: string = logicalExpressionNode.operator;
-        const logicalExpressionFunctionCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
-            ControlFlowCustomNode.LogicalExpressionFunctionNode
-        );
+        const operator: ESTree.LogicalOperator = logicalExpressionNode.operator;
+        const logicalExpressionFunctionCustomNode: ICustomNode<TInitialData<LogicalExpressionFunctionNode>> =
+            this.controlFlowCustomNodeFactory(ControlFlowCustomNode.LogicalExpressionFunctionNode);
 
 
-        logicalExpressionFunctionCustomNode.initialize(replacerId);
+        logicalExpressionFunctionCustomNode.initialize(operator);
 
 
         const storageKey: string = this.insertCustomNodeToControlFlowStorage(
         const storageKey: string = this.insertCustomNodeToControlFlowStorage(
             logicalExpressionFunctionCustomNode,
             logicalExpressionFunctionCustomNode,
             controlFlowStorage,
             controlFlowStorage,
-            replacerId,
+            operator,
             LogicalExpressionControlFlowReplacer.usingExistingIdentifierChance
             LogicalExpressionControlFlowReplacer.usingExistingIdentifierChance
         );
         );
 
 

+ 7 - 6
src/node-transformers/control-flow-transformers/control-flow-replacers/StringLiteralControlFlowReplacer.ts

@@ -5,6 +5,7 @@ import * as ESTree from 'estree';
 
 
 import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
 import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage';
+import { TInitialData } from '../../../types/TInitialData';
 import { TStatement } from '../../../types/node/TStatement';
 import { TStatement } from '../../../types/node/TStatement';
 
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
@@ -15,6 +16,8 @@ import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCu
 
 
 import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
 import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
 import { NodeGuards } from '../../../node/NodeGuards';
 import { NodeGuards } from '../../../node/NodeGuards';
+import { StringLiteralControlFlowStorageCallNode } from '../../../custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/StringLiteralControlFlowStorageCallNode';
+import { StringLiteralNode } from '../../../custom-nodes/control-flow-flattening-nodes/StringLiteralNode';
 
 
 @injectable()
 @injectable()
 export class StringLiteralControlFlowReplacer extends AbstractControlFlowReplacer {
 export class StringLiteralControlFlowReplacer extends AbstractControlFlowReplacer {
@@ -57,9 +60,8 @@ export class StringLiteralControlFlowReplacer extends AbstractControlFlowReplace
         }
         }
 
 
         const replacerId: string = String(literalNode.value);
         const replacerId: string = String(literalNode.value);
-        const literalFunctionCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
-            ControlFlowCustomNode.StringLiteralNode
-        );
+        const literalFunctionCustomNode: ICustomNode<TInitialData<StringLiteralNode>> =
+            this.controlFlowCustomNodeFactory(ControlFlowCustomNode.StringLiteralNode);
 
 
         literalFunctionCustomNode.initialize(literalNode.value);
         literalFunctionCustomNode.initialize(literalNode.value);
 
 
@@ -82,9 +84,8 @@ export class StringLiteralControlFlowReplacer extends AbstractControlFlowReplace
         controlFlowStorageId: string,
         controlFlowStorageId: string,
         storageKey: string
         storageKey: string
     ): ESTree.Node {
     ): ESTree.Node {
-        const controlFlowStorageCallCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
-            ControlFlowCustomNode.StringLiteralControlFlowStorageCallNode
-        );
+        const controlFlowStorageCallCustomNode: ICustomNode<TInitialData<StringLiteralControlFlowStorageCallNode>> =
+            this.controlFlowCustomNodeFactory(ControlFlowCustomNode.StringLiteralControlFlowStorageCallNode);
 
 
         controlFlowStorageCallCustomNode.initialize(controlFlowStorageId, storageKey);
         controlFlowStorageCallCustomNode.initialize(controlFlowStorageId, storageKey);
 
 

+ 6 - 3
src/node-transformers/converting-transformers/properties-extractors/BasePropertiesExtractor.ts

@@ -8,12 +8,14 @@ import { TObjectExpressionKeysTransformerCustomNodeFactory } from '../../../type
 import { TStatement } from '../../../types/node/TStatement';
 import { TStatement } from '../../../types/node/TStatement';
 
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
+import { TInitialData } from '../../../types/TInitialData';
 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 { ObjectExpressionKeysTransformerCustomNode } from '../../../enums/custom-nodes/ObjectExpressionKeysTransformerCustomNode';
 import { ObjectExpressionKeysTransformerCustomNode } from '../../../enums/custom-nodes/ObjectExpressionKeysTransformerCustomNode';
 
 
 import { AbstractPropertiesExtractor } from './AbstractPropertiesExtractor';
 import { AbstractPropertiesExtractor } from './AbstractPropertiesExtractor';
+import { BasePropertiesExtractorObjectExpressionHostNode } from '../../../custom-nodes/object-expression-keys-transformer-nodes/BasePropertiesExtractorObjectExpressionHostNode';
 import { NodeAppender } from '../../../node/NodeAppender';
 import { NodeAppender } from '../../../node/NodeAppender';
 import { NodeGuards } from '../../../node/NodeGuards';
 import { NodeGuards } from '../../../node/NodeGuards';
 
 
@@ -92,9 +94,10 @@ export class BasePropertiesExtractor extends AbstractPropertiesExtractor {
      * @returns {VariableDeclaration}
      * @returns {VariableDeclaration}
      */
      */
     private getObjectExpressionHostNode (): ESTree.VariableDeclaration {
     private getObjectExpressionHostNode (): ESTree.VariableDeclaration {
-        const objectExpressionHostCustomNode: ICustomNode = this.objectExpressionKeysTransformerCustomNodeFactory(
-            ObjectExpressionKeysTransformerCustomNode.BasePropertiesExtractorObjectExpressionHostNode
-        );
+        const objectExpressionHostCustomNode: ICustomNode<TInitialData<BasePropertiesExtractorObjectExpressionHostNode>> =
+            this.objectExpressionKeysTransformerCustomNodeFactory(
+                ObjectExpressionKeysTransformerCustomNode.BasePropertiesExtractorObjectExpressionHostNode
+            );
 
 
         objectExpressionHostCustomNode.initialize();
         objectExpressionHostCustomNode.initialize();
 
 

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

@@ -5,6 +5,7 @@ import * as estraverse from 'estraverse';
 import * as ESTree from 'estree';
 import * as ESTree from 'estree';
 
 
 import { TDeadNodeInjectionCustomNodeFactory } from '../../types/container/custom-nodes/TDeadNodeInjectionCustomNodeFactory';
 import { TDeadNodeInjectionCustomNodeFactory } from '../../types/container/custom-nodes/TDeadNodeInjectionCustomNodeFactory';
+import { TInitialData } from '../../types/TInitialData';
 import { TNodeWithStatements } from '../../types/node/TNodeWithStatements';
 import { TNodeWithStatements } from '../../types/node/TNodeWithStatements';
 
 
 import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
 import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
@@ -19,6 +20,7 @@ import { NodeType } from '../../enums/node/NodeType';
 import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
+import { BlockStatementDeadCodeInjectionNode } from '../../custom-nodes/dead-code-injection-nodes/BlockStatementDeadCodeInjectionNode';
 import { NodeFactory } from '../../node/NodeFactory';
 import { NodeFactory } from '../../node/NodeFactory';
 import { NodeGuards } from '../../node/NodeGuards';
 import { NodeGuards } from '../../node/NodeGuards';
 import { NodeStatementUtils } from '../../node/NodeStatementUtils';
 import { NodeStatementUtils } from '../../node/NodeStatementUtils';
@@ -389,9 +391,8 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
          */
          */
         this.deadCodeInjectionRootAstHostNodeSet.add(deadCodeInjectionRootAstHostNode);
         this.deadCodeInjectionRootAstHostNodeSet.add(deadCodeInjectionRootAstHostNode);
 
 
-        const blockStatementDeadCodeInjectionCustomNode: ICustomNode = this.deadCodeInjectionCustomNodeFactory(
-            DeadCodeInjectionCustomNode.BlockStatementDeadCodeInjectionNode
-        );
+        const blockStatementDeadCodeInjectionCustomNode: ICustomNode<TInitialData<BlockStatementDeadCodeInjectionNode>> =
+            this.deadCodeInjectionCustomNodeFactory(DeadCodeInjectionCustomNode.BlockStatementDeadCodeInjectionNode);
 
 
         blockStatementDeadCodeInjectionCustomNode.initialize(blockStatementNode, deadCodeInjectionRootAstHostNode);
         blockStatementDeadCodeInjectionCustomNode.initialize(blockStatementNode, deadCodeInjectionRootAstHostNode);
 
 

+ 11 - 0
src/node-transformers/preparing-transformers/CustomNodesTransformer.ts

@@ -11,6 +11,7 @@ import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { ICallsGraphAnalyzer } from '../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphAnalyzer';
 import { ICallsGraphAnalyzer } from '../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphAnalyzer';
 import { ICallsGraphData } from '../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
 import { ICallsGraphData } from '../../interfaces/analyzers/calls-graph-analyzer/ICallsGraphData';
+import { IPrevailingKindOfVariablesAnalyzer } from '../../interfaces/analyzers/calls-graph-analyzer/IPrevailingKindOfVariablesAnalyzer';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
 
 import { ObfuscationEvent } from '../../enums/event-emitters/ObfuscationEvent';
 import { ObfuscationEvent } from '../../enums/event-emitters/ObfuscationEvent';
@@ -44,8 +45,14 @@ export class CustomNodesTransformer extends AbstractNodeTransformer {
      */
      */
     private callsGraphData: ICallsGraphData[] = [];
     private callsGraphData: ICallsGraphData[] = [];
 
 
+    /**
+     * @type {IPrevailingKindOfVariablesAnalyzer}
+     */
+    private readonly prevailingKindOfVariablesAnalyzer: IPrevailingKindOfVariablesAnalyzer;
+
     /**
     /**
      * @param {ICallsGraphAnalyzer} callsGraphAnalyzer
      * @param {ICallsGraphAnalyzer} callsGraphAnalyzer
+     * @param {IPrevailingKindOfVariablesAnalyzer} prevailingKindOfVariablesAnalyzer
      * @param {IObfuscationEventEmitter} obfuscationEventEmitter
      * @param {IObfuscationEventEmitter} obfuscationEventEmitter
      * @param {TCustomNodeGroupStorage} customNodeGroupStorage
      * @param {TCustomNodeGroupStorage} customNodeGroupStorage
      * @param {IRandomGenerator} randomGenerator
      * @param {IRandomGenerator} randomGenerator
@@ -53,6 +60,8 @@ export class CustomNodesTransformer extends AbstractNodeTransformer {
      */
      */
     constructor (
     constructor (
         @inject(ServiceIdentifiers.ICallsGraphAnalyzer) callsGraphAnalyzer: ICallsGraphAnalyzer,
         @inject(ServiceIdentifiers.ICallsGraphAnalyzer) callsGraphAnalyzer: ICallsGraphAnalyzer,
+        @inject(ServiceIdentifiers.IPrevailingKindOfVariablesAnalyzer)
+            prevailingKindOfVariablesAnalyzer: IPrevailingKindOfVariablesAnalyzer,
         @inject(ServiceIdentifiers.IObfuscationEventEmitter) obfuscationEventEmitter: IObfuscationEventEmitter,
         @inject(ServiceIdentifiers.IObfuscationEventEmitter) obfuscationEventEmitter: IObfuscationEventEmitter,
         @inject(ServiceIdentifiers.TCustomNodeGroupStorage) customNodeGroupStorage: TCustomNodeGroupStorage,
         @inject(ServiceIdentifiers.TCustomNodeGroupStorage) customNodeGroupStorage: TCustomNodeGroupStorage,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@@ -61,6 +70,7 @@ export class CustomNodesTransformer extends AbstractNodeTransformer {
         super(randomGenerator, options);
         super(randomGenerator, options);
 
 
         this.callsGraphAnalyzer = callsGraphAnalyzer;
         this.callsGraphAnalyzer = callsGraphAnalyzer;
+        this.prevailingKindOfVariablesAnalyzer = prevailingKindOfVariablesAnalyzer;
         this.obfuscationEventEmitter = obfuscationEventEmitter;
         this.obfuscationEventEmitter = obfuscationEventEmitter;
         this.customNodeGroupStorage = customNodeGroupStorage;
         this.customNodeGroupStorage = customNodeGroupStorage;
     }
     }
@@ -103,6 +113,7 @@ export class CustomNodesTransformer extends AbstractNodeTransformer {
      */
      */
     public analyzeNode (node: ESTree.Program, parentNode: ESTree.Node | null): void {
     public analyzeNode (node: ESTree.Program, parentNode: ESTree.Node | null): void {
         this.callsGraphData = this.callsGraphAnalyzer.analyze(node);
         this.callsGraphData = this.callsGraphAnalyzer.analyze(node);
+        this.prevailingKindOfVariablesAnalyzer.analyze(node);
     }
     }
 
 
     /**
     /**

+ 4 - 1
src/node/NodeUtils.ts

@@ -33,7 +33,10 @@ export class NodeUtils {
      * @returns {Statement[]}
      * @returns {Statement[]}
      */
      */
     public static convertCodeToStructure (code: string): ESTree.Statement[] {
     public static convertCodeToStructure (code: string): ESTree.Statement[] {
-        const structure: ESTree.Program = espree.parse(code, { sourceType: 'script' });
+        const structure: ESTree.Program = espree.parse(code, {
+            ecmaVersion: 10,
+            sourceType: 'script'
+        });
 
 
         estraverse.replace(structure, {
         estraverse.replace(structure, {
             enter: (node: ESTree.Node, parentNode: ESTree.Node | null): ESTree.Node => {
             enter: (node: ESTree.Node, parentNode: ESTree.Node | null): ESTree.Node => {

+ 7 - 5
src/templates/AtobTemplate.ts

@@ -6,21 +6,23 @@ export function AtobTemplate (): string {
         (function () {
         (function () {
             {globalVariableTemplate}
             {globalVariableTemplate}
             
             
-            var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+            const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
 
 
             that.atob || (
             that.atob || (
                 that.atob = function(input) {
                 that.atob = function(input) {
-                    var str = String(input).replace(/=+$/, '');
+                    const str = String(input).replace(/=+$/, '');
+                    let output = '';
                     for (
                     for (
-                        var bc = 0, bs, buffer, idx = 0, output = '';
+                        let bc = 0, bs, buffer, idx = 0;
                         buffer = str.charAt(idx++);
                         buffer = str.charAt(idx++);
                         ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
                         ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
                             bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
                             bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
                     ) {
                     ) {
                         buffer = chars.indexOf(buffer);
                         buffer = chars.indexOf(buffer);
                     }
                     }
-                return output;
-            });
+                    return output;
+                }
+            );
         })();
         })();
     `;
     `;
 }
 }

+ 1 - 1
src/templates/GlobalVariableNoEvalTemplate.ts

@@ -3,7 +3,7 @@
  */
  */
 export function GlobalVariableNoEvalTemplate (): string {
 export function GlobalVariableNoEvalTemplate (): string {
     return `
     return `
-        var that = (typeof window !== 'undefined'
+        const that = (typeof window !== 'undefined'
            ? window
            ? window
            : (typeof process === 'object' &&
            : (typeof process === 'object' &&
               typeof require === 'function' &&
               typeof require === 'function' &&

+ 2 - 2
src/templates/GlobalVariableTemplate1.ts

@@ -3,10 +3,10 @@
  */
  */
 export function GlobalVariableTemplate1 (): string {
 export function GlobalVariableTemplate1 (): string {
     return `
     return `
-        var that;
+        let that;
         
         
         try {
         try {
-            var getGlobal = Function('return (function() ' + '{}.constructor("return this")( )' + ');');
+            const getGlobal = Function('return (function() ' + '{}.constructor("return this")( )' + ');');
             
             
             that = getGlobal();
             that = getGlobal();
         } catch (e) {
         } catch (e) {

+ 3 - 3
src/templates/GlobalVariableTemplate2.ts

@@ -3,8 +3,8 @@
  */
  */
 export function GlobalVariableTemplate2 (): string {
 export function GlobalVariableTemplate2 (): string {
     return `
     return `
-        var getGlobal = function () {
-            var globalObject;
+        const getGlobal = function () {
+            let globalObject;
         
         
             try {
             try {
                 globalObject = Function('return (function() ' + '{}.constructor("return this")( )' + ');')();
                 globalObject = Function('return (function() ' + '{}.constructor("return this")( )' + ');')();
@@ -14,6 +14,6 @@ export function GlobalVariableTemplate2 (): string {
             
             
             return globalObject;
             return globalObject;
         };
         };
-        var that = getGlobal();
+        const that = getGlobal();
     `;
     `;
 }
 }

+ 7 - 5
src/templates/Rc4Template.ts

@@ -3,18 +3,20 @@
  */
  */
 export function Rc4Template (): string {
 export function Rc4Template (): string {
     return `
     return `
-        var rc4 = function (str, key) {
-            var s = [], j = 0, x, res = '', newStr = '';
+        const rc4 = function (str, key) {
+            let s = [], j = 0, x, res = '', newStr = '';
            
            
             str = atob(str);
             str = atob(str);
                 
                 
-            for (var k = 0, length = str.length; k < length; k++) {
+            for (let k = 0, length = str.length; k < length; k++) {
                 newStr += '%' + ('00' + str.charCodeAt(k).toString(16)).slice(-2);
                 newStr += '%' + ('00' + str.charCodeAt(k).toString(16)).slice(-2);
             }
             }
         
         
             str = decodeURIComponent(newStr);
             str = decodeURIComponent(newStr);
+                    	     
+            let i;
                     	        
                     	        
-	        for (var i = 0; i < 256; i++) {
+	        for (i = 0; i < 256; i++) {
                 s[i] = i;
                 s[i] = i;
             }
             }
  
  
@@ -28,7 +30,7 @@ export function Rc4Template (): string {
             i = 0;
             i = 0;
             j = 0;
             j = 0;
             
             
-            for (var y = 0; y < str.length; y++) {
+            for (let y = 0; y < str.length; y++) {
                 i = (i + 1) % 256;
                 i = (i + 1) % 256;
                 j = (j + s[i]) % 256;
                 j = (j + s[i]) % 256;
                 x = s[i];
                 x = s[i];

+ 4 - 4
src/templates/SingleNodeCallControllerTemplate.ts

@@ -3,13 +3,13 @@
  */
  */
 export function SingleNodeCallControllerTemplate (): string {
 export function SingleNodeCallControllerTemplate (): string {
     return `
     return `
-        var {singleNodeCallControllerFunctionName} = (function(){
-            var firstCall = true;
+        const {singleNodeCallControllerFunctionName} = (function(){
+            let firstCall = true;
             
             
             return function (context, fn){
             return function (context, fn){
-                var rfn = firstCall ? function(){
+                const rfn = firstCall ? function(){
                     if(fn){
                     if(fn){
-                        var res = fn.apply(context, arguments);
+                        const res = fn.apply(context, arguments);
                         fn = null;
                         fn = null;
                         return res;
                         return res;
                     }
                     }

+ 3 - 3
src/templates/console-output-nodes/console-output-disable-expression-node/ConsoleOutputDisableExpressionTemplate.ts

@@ -3,14 +3,14 @@
  */
  */
 export function ConsoleOutputDisableExpressionTemplate (): string {
 export function ConsoleOutputDisableExpressionTemplate (): string {
     return `
     return `
-        var {consoleLogDisableFunctionName} = {singleNodeCallControllerFunctionName}(this, function () {
-            var func = function () {};
+        const {consoleLogDisableFunctionName} = {singleNodeCallControllerFunctionName}(this, function () {
+            const func = function () {};
             
             
             {globalVariableTemplate}
             {globalVariableTemplate}
                         
                         
             if (!that.console) {
             if (!that.console) {
                 that.console = (function (func){
                 that.console = (function (func){
-                    var c = {};
+                    const c = {};
                     
                     
                     c.log = func;
                     c.log = func;
                     c.warn = func;
                     c.warn = func;

+ 14 - 11
src/templates/debug-protection-nodes/debug-protection-function-call-node/DebugProtectionFunctionCallTemplate.ts

@@ -4,18 +4,21 @@
 export function DebugProtectionFunctionCallTemplate (): string {
 export function DebugProtectionFunctionCallTemplate (): string {
     return `
     return `
         (function () {
         (function () {
-            {singleNodeCallControllerFunctionName}(this, function () {
-                var regExp1 = new RegExp('function *\\\\( *\\\\)');
-                var regExp2 = new RegExp('\\\\+\\\\+ *\\(?:[a-zA-Z_$][0-9a-zA-Z_$]*\\)', 'i');
-       
-                var result = {debugProtectionFunctionName}('init');
-                
-                if (!regExp1.test(result + 'chain') || !regExp2.test(result + 'input')) {
-                    result('0');
-                } else {
-                    {debugProtectionFunctionName}();
+            {singleNodeCallControllerFunctionName}(
+                this,
+                function () {
+                    const regExp1 = new RegExp('function *\\\\( *\\\\)');
+                    const regExp2 = new RegExp('\\\\+\\\\+ *\\(?:[a-zA-Z_$][0-9a-zA-Z_$]*\\)', 'i');
+           
+                    const result = {debugProtectionFunctionName}('init');
+                    
+                    if (!regExp1.test(result + 'chain') || !regExp2.test(result + 'input')) {
+                        result('0');
+                    } else {
+                        {debugProtectionFunctionName}();
+                    }
                 }
                 }
-            })();
+            )();
         })();
         })();
     `;
     `;
 }
 }

+ 1 - 1
src/templates/debug-protection-nodes/debug-protection-function-node/DebuggerTemplateNoEval.ts

@@ -4,7 +4,7 @@
 export function DebuggerTemplateNoEval (): string {
 export function DebuggerTemplateNoEval (): string {
     return `
     return `
         if (typeof counter === 'string') {
         if (typeof counter === 'string') {
-            var func = function () {
+            const func = function () {
                 while (true) {}
                 while (true) {}
             };
             };
             
             

+ 23 - 23
src/templates/domain-lock-nodes/domain-lock-node/DomainLockNodeTemplate.ts

@@ -3,17 +3,17 @@
  */
  */
 export function DomainLockNodeTemplate (): string {
 export function DomainLockNodeTemplate (): string {
     return `
     return `
-        var {domainLockFunctionName} = {singleNodeCallControllerFunctionName}(this, function () {
+        const {domainLockFunctionName} = {singleNodeCallControllerFunctionName}(this, function () {
             
             
             {globalVariableTemplate}
             {globalVariableTemplate}
             
             
-            var func = function () {
+            const func = function () {
                 return {
                 return {
                     key: 'item',
                     key: 'item',
                     value: 'attribute',
                     value: 'attribute',
                     getAttribute: function () {
                     getAttribute: function () {
-                        for (var i = 0; i < 1000; i--) {
-                            var isPositive = i > 0;
+                        for (let i = 0; i < 1000; i--) {
+                            const isPositive = i > 0;
                             
                             
                             switch (isPositive) {
                             switch (isPositive) {
                                 case true:
                                 case true:
@@ -26,14 +26,14 @@ export function DomainLockNodeTemplate (): string {
                 };
                 };
             };
             };
                         
                         
-            var regExp = new RegExp("[{diff}]", "g");
-            var domains = "{domains}".replace(regExp, "").split(";");
-            var document;
-            var domain;
-            var location;
-            var hostname;
+            const regExp = new RegExp("[{diff}]", "g");
+            const domains = "{domains}".replace(regExp, "").split(";");
+            let document;
+            let domain;
+            let location;
+            let hostname;
 
 
-            for (var d in that) {
+            for (let d in that) {
                 if (d.length == 8 && d.charCodeAt(7) == 116 && d.charCodeAt(5) == 101 && d.charCodeAt(3) == 117 && d.charCodeAt(0) == 100) {
                 if (d.length == 8 && d.charCodeAt(7) == 116 && d.charCodeAt(5) == 101 && d.charCodeAt(3) == 117 && d.charCodeAt(0) == 100) {
                     document = d;
                     document = d;
                 
                 
@@ -41,7 +41,7 @@ export function DomainLockNodeTemplate (): string {
                 }
                 }
             }
             }
 
 
-            for (var d1 in that[document]) {
+            for (let d1 in that[document]) {
                 if (d1.length == 6 && d1.charCodeAt(5) == 110 && d1.charCodeAt(0) == 100) {
                 if (d1.length == 6 && d1.charCodeAt(5) == 110 && d1.charCodeAt(0) == 100) {
                     domain = d1;
                     domain = d1;
                     
                     
@@ -50,7 +50,7 @@ export function DomainLockNodeTemplate (): string {
             }
             }
 
 
             if (!("~" > domain)) {
             if (!("~" > domain)) {
-                for (var d2 in that[document]) {
+                for (let d2 in that[document]) {
                     if (d2.length == 8 && d2.charCodeAt(7) == 110 && d2.charCodeAt(0) == 108) {
                     if (d2.length == 8 && d2.charCodeAt(7) == 110 && d2.charCodeAt(0) == 108) {
                         location = d2;
                         location = d2;
                         
                         
@@ -58,7 +58,7 @@ export function DomainLockNodeTemplate (): string {
                     }
                     }
                 }
                 }
 
 
-                for (var d3 in that[document][location]) {
+                for (let d3 in that[document][location]) {
                     if (d3.length == 8 && d3.charCodeAt(7) == 101 && d3.charCodeAt(0) == 104) {
                     if (d3.length == 8 && d3.charCodeAt(7) == 101 && d3.charCodeAt(0) == 104) {
                         hostname = d3;
                         hostname = d3;
                         
                         
@@ -71,21 +71,21 @@ export function DomainLockNodeTemplate (): string {
                 return;
                 return;
             }
             }
             
             
-            var documentDomain = that[document][domain];
-            var documentLocationHostName = !!that[document][location] && that[document][location][hostname];
-            var currentDomain = documentDomain || documentLocationHostName;
+            const documentDomain = that[document][domain];
+            const documentLocationHostName = !!that[document][location] && that[document][location][hostname];
+            const currentDomain = documentDomain || documentLocationHostName;
           
           
             if (!currentDomain) {
             if (!currentDomain) {
                 return;
                 return;
             }
             }
           
           
-            var ok = false;
+            let ok = false;
                         
                         
-            for (var i = 0; i < domains.length; i++) {
-                var domain = domains[i];
-                var position = currentDomain.length - domain.length;
-                var lastIndex = currentDomain.indexOf(domain, position);
-                var endsWith = lastIndex !== -1 && lastIndex === position;
+            for (let i = 0; i < domains.length; i++) {
+                const domain = domains[i];
+                const position = currentDomain.length - domain.length;
+                const lastIndex = currentDomain.indexOf(domain, position);
+                const endsWith = lastIndex !== -1 && lastIndex === position;
                 
                 
                 if (endsWith) {
                 if (endsWith) {
                     if (currentDomain.length == domain.length || domain.indexOf(".") === 0) {
                     if (currentDomain.length == domain.length || domain.indexOf(".") === 0) {

+ 10 - 10
src/templates/self-defending-nodes/self-defending-unicode-node/SelfDefendingTemplate.ts

@@ -9,38 +9,38 @@ import { IEscapeSequenceEncoder } from '../../../interfaces/utils/IEscapeSequenc
  */
  */
 export function SelfDefendingTemplate (escapeSequenceEncoder: IEscapeSequenceEncoder): string {
 export function SelfDefendingTemplate (escapeSequenceEncoder: IEscapeSequenceEncoder): string {
     return `
     return `
-        var {selfDefendingFunctionName} = {singleNodeCallControllerFunctionName}(this, function () {
-            var func1 = function(){return 'dev';},
+        const {selfDefendingFunctionName} = {singleNodeCallControllerFunctionName}(this, function () {
+            const func1 = function(){return 'dev';},
                 func2 = function () {
                 func2 = function () {
                     return 'window';
                     return 'window';
                 };
                 };
                 
                 
-            var test1 = function () {
-                var regExp = new RegExp('${
+            const test1 = function () {
+                const regExp = new RegExp('${
                     escapeSequenceEncoder.encode(`\\w+ *\\(\\) *{\\w+ *['|"].+['|"];? *}`, true)
                     escapeSequenceEncoder.encode(`\\w+ *\\(\\) *{\\w+ *['|"].+['|"];? *}`, true)
                 }');
                 }');
                 
                 
                 return !regExp.test(func1.toString());
                 return !regExp.test(func1.toString());
             };
             };
             
             
-            var test2 = function () {
-                var regExp = new RegExp('${
+            const test2 = function () {
+                const regExp = new RegExp('${
                     escapeSequenceEncoder.encode(`(\\\\[x|u](\\w){2,4})+`, true)
                     escapeSequenceEncoder.encode(`(\\\\[x|u](\\w){2,4})+`, true)
                 }');
                 }');
                 
                 
                 return regExp.test(func2.toString());
                 return regExp.test(func2.toString());
             };
             };
             
             
-            var recursiveFunc1 = function (string) {
-                var i = ~-1 >> 1 + 255 % 0;
+            const recursiveFunc1 = function (string) {
+                const i = ~-1 >> 1 + 255 % 0;
                                 
                                 
                 if (string.indexOf('i' === i)) {
                 if (string.indexOf('i' === i)) {
                     recursiveFunc2(string)
                     recursiveFunc2(string)
                 }
                 }
             };
             };
             
             
-            var recursiveFunc2 = function (string) {
-                var i = ~-4 >> 1 + 255 % 0;
+            const recursiveFunc2 = function (string) {
+                const i = ~-4 >> 1 + 255 % 0;
                 
                 
                 if (string.indexOf((true+"")[3]) !== i) {
                 if (string.indexOf((true+"")[3]) !== i) {
                     recursiveFunc1(string)
                     recursiveFunc1(string)

+ 4 - 4
src/templates/string-array-nodes/string-array-calls-wrapper/SelfDefendingTemplate.ts

@@ -23,7 +23,7 @@ export function SelfDefendingTemplate (
     const stateResultIdentifier: string = randomGenerator.getRandomString(identifierLength);
     const stateResultIdentifier: string = randomGenerator.getRandomString(identifierLength);
     
     
     return `
     return `
-        var StatesClass = function (${rc4BytesIdentifier}) {
+        const StatesClass = function (${rc4BytesIdentifier}) {
             this.${rc4BytesIdentifier} = ${rc4BytesIdentifier};
             this.${rc4BytesIdentifier} = ${rc4BytesIdentifier};
             this.${statesIdentifier} = [1, 0, 0];
             this.${statesIdentifier} = [1, 0, 0];
             this.${newStateIdentifier} = function(){return 'newState';};
             this.${newStateIdentifier} = function(){return 'newState';};
@@ -36,8 +36,8 @@ export function SelfDefendingTemplate (
         };
         };
         
         
         StatesClass.prototype.${checkStateIdentifier} = function () {
         StatesClass.prototype.${checkStateIdentifier} = function () {
-            var regExp = new RegExp(this.${firstStateIdentifier} + this.${secondStateIdentifier});
-            var expression = regExp.test(this.${newStateIdentifier}.toString())
+            const regExp = new RegExp(this.${firstStateIdentifier} + this.${secondStateIdentifier});
+            const expression = regExp.test(this.${newStateIdentifier}.toString())
                 ? --this.${statesIdentifier}[1]
                 ? --this.${statesIdentifier}[1]
                 : --this.${statesIdentifier}[0];
                 : --this.${statesIdentifier}[0];
             
             
@@ -53,7 +53,7 @@ export function SelfDefendingTemplate (
         };
         };
 
 
         StatesClass.prototype.${getStateIdentifier} = function (${rc4BytesIdentifier}) {
         StatesClass.prototype.${getStateIdentifier} = function (${rc4BytesIdentifier}) {
-            for (var i = 0, len = this.${statesIdentifier}.length; i < len; i++) {
+            for (let i = 0, len = this.${statesIdentifier}.length; i < len; i++) {
                 this.${statesIdentifier}.push(Math.round(Math.random()));
                 this.${statesIdentifier}.push(Math.round(Math.random()));
                 len = this.${statesIdentifier}.length;
                 len = this.${statesIdentifier}.length;
             }
             }

+ 4 - 4
src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayBase64DecodeNodeTemplate.ts

@@ -18,10 +18,10 @@ export function StringArrayBase64DecodeNodeTemplate (
             {atobPolyfill}
             {atobPolyfill}
             
             
             {stringArrayCallsWrapperName}.${base64DecodeFunctionIdentifier} = function (str) {
             {stringArrayCallsWrapperName}.${base64DecodeFunctionIdentifier} = function (str) {
-                var string = atob(str);
-                var newStringChars = [];
+                const string = atob(str);
+                let newStringChars = [];
                 
                 
-                for (var i = 0, length = string.length; i < length; i++) {
+                for (let i = 0, length = string.length; i < length; i++) {
                     newStringChars += '%' + ('00' + string.charCodeAt(i).toString(16)).slice(-2);
                     newStringChars += '%' + ('00' + string.charCodeAt(i).toString(16)).slice(-2);
                 }
                 }
                 
                 
@@ -33,7 +33,7 @@ export function StringArrayBase64DecodeNodeTemplate (
             {stringArrayCallsWrapperName}.${initializedIdentifier} = true;
             {stringArrayCallsWrapperName}.${initializedIdentifier} = true;
         }
         }
                   
                   
-        var cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[index];
+        const cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[index];
                         
                         
         if (cachedValue === undefined) {
         if (cachedValue === undefined) {
             {selfDefendingCode}
             {selfDefendingCode}

+ 2 - 2
src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayCallsWrapperTemplate.ts

@@ -3,10 +3,10 @@
  */
  */
 export function StringArrayCallsWrapperTemplate (): string {
 export function StringArrayCallsWrapperTemplate (): string {
     return `
     return `
-        var {stringArrayCallsWrapperName} = function (index, key) {
+        const {stringArrayCallsWrapperName} = function (index, key) {
             index = index - 0;
             index = index - 0;
             
             
-            var value = {stringArrayName}[index];
+            let value = {stringArrayName}[index];
             
             
             {decodeNodeTemplate}
             {decodeNodeTemplate}
         
         

+ 1 - 1
src/templates/string-array-nodes/string-array-calls-wrapper/StringArrayRC4DecodeNodeTemplate.ts

@@ -26,7 +26,7 @@ export function StringArrayRc4DecodeNodeTemplate (
             {stringArrayCallsWrapperName}.${initializedIdentifier} = true;
             {stringArrayCallsWrapperName}.${initializedIdentifier} = true;
         }
         }
   
   
-        var cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[index];
+        const cachedValue = {stringArrayCallsWrapperName}.${dataIdentifier}[index];
 
 
         if (cachedValue === undefined) {
         if (cachedValue === undefined) {
             if ({stringArrayCallsWrapperName}.${onceIdentifier} === undefined) {
             if ({stringArrayCallsWrapperName}.${onceIdentifier} === undefined) {

+ 1 - 1
src/templates/string-array-nodes/string-array-node/StringArrayTemplate.ts

@@ -3,6 +3,6 @@
  */
  */
 export function StringArrayTemplate (): string {
 export function StringArrayTemplate (): string {
     return `
     return `
-        var {stringArrayName} = [{stringArray}];
+        const {stringArrayName} = [{stringArray}];
     `;
     `;
 }
 }

+ 13 - 14
src/templates/string-array-nodes/string-array-rotate-function-node/SelfDefendingTemplate.ts

@@ -8,8 +8,8 @@ import { IEscapeSequenceEncoder } from '../../../interfaces/utils/IEscapeSequenc
  */
  */
 export function SelfDefendingTemplate (escapeSequenceEncoder: IEscapeSequenceEncoder): string {
 export function SelfDefendingTemplate (escapeSequenceEncoder: IEscapeSequenceEncoder): string {
     return `
     return `
-        var selfDefendingFunc = function () {
-            var object = {
+        const selfDefendingFunc = function () {
+            const object = {
                 data: {
                 data: {
                     key: 'cookie',
                     key: 'cookie',
                     value: 'timeout'
                     value: 'timeout'
@@ -17,16 +17,15 @@ export function SelfDefendingTemplate (escapeSequenceEncoder: IEscapeSequenceEnc
                 setCookie: function (options, name, value, document) {
                 setCookie: function (options, name, value, document) {
                     document = document || {};
                     document = document || {};
                     
                     
-                    var updatedCookie = name + "=" + value;
-
-                    var i = 0;
+                    let updatedCookie = name + "=" + value;
+                    let i = 0;
                                                             
                                                             
-                    for (var i = 0, len = options.length; i < len; i++) {
-                        var propName = options[i];
+                    for (let i = 0, len = options.length; i < len; i++) {
+                        const propName = options[i];
                                      
                                      
                         updatedCookie += "; " + propName;
                         updatedCookie += "; " + propName;
                         
                         
-                        var propValue = options[propName];
+                        const propValue = options[propName];
                         
                         
                         options.push(propValue);
                         options.push(propValue);
                         len = options.length;
                         len = options.length;
@@ -41,11 +40,11 @@ export function SelfDefendingTemplate (escapeSequenceEncoder: IEscapeSequenceEnc
                 removeCookie: function(){return 'dev';},
                 removeCookie: function(){return 'dev';},
                 getCookie: function (document, name) {
                 getCookie: function (document, name) {
                     document = document || function (value) { return value };
                     document = document || function (value) { return value };
-                    var matches = document(new RegExp(
+                    const matches = document(new RegExp(
                         "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
                         "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
                     ));
                     ));
                     
                     
-                    var func = function (param1, param2) {
+                    const func = function (param1, param2) {
                         param1(++param2);
                         param1(++param2);
                     };
                     };
                     
                     
@@ -55,8 +54,8 @@ export function SelfDefendingTemplate (escapeSequenceEncoder: IEscapeSequenceEnc
                 }
                 }
             };
             };
             
             
-            var test1 = function () {
-                var regExp = new RegExp('${
+            const test1 = function () {
+                const regExp = new RegExp('${
                     escapeSequenceEncoder.encode(`\\w+ *\\(\\) *{\\w+ *['|"].+['|"];? *}`, true)
                     escapeSequenceEncoder.encode(`\\w+ *\\(\\) *{\\w+ *['|"].+['|"];? *}`, true)
                 }');
                 }');
                 
                 
@@ -65,8 +64,8 @@ export function SelfDefendingTemplate (escapeSequenceEncoder: IEscapeSequenceEnc
             
             
             object['updateCookie'] = test1;
             object['updateCookie'] = test1;
             
             
-            var cookie = '';
-            var result = object['updateCookie']();
+            let cookie = '';
+            const result = object['updateCookie']();
                                     
                                     
             if (!result) {
             if (!result) {
                 object['setCookie'](['*'], 'counter', 1);
                 object['setCookie'](['*'], 'counter', 1);

+ 1 - 1
src/templates/string-array-nodes/string-array-rotate-function-node/StringArrayRotateFunctionTemplate.ts

@@ -4,7 +4,7 @@
 export function StringArrayRotateFunctionTemplate (): string {
 export function StringArrayRotateFunctionTemplate (): string {
     return `
     return `
         (function (array, {timesName}) {
         (function (array, {timesName}) {
-            var {whileFunctionName} = function (times) {
+            const {whileFunctionName} = function (times) {
                 while (--times) {
                 while (--times) {
                     array['push'](array['shift']());
                     array['push'](array['shift']());
                 }
                 }

+ 3 - 0
src/types/TInitialData.d.ts

@@ -0,0 +1,3 @@
+import { IInitializable } from '../interfaces/IInitializable';
+
+export type TInitialData <TClass extends IInitializable> = Parameters<TClass['initialize']>;

+ 3 - 1
src/types/container/custom-nodes/TControlFlowCustomNodeFactory.d.ts

@@ -2,4 +2,6 @@ import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 
 
 import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCustomNode';
 import { ControlFlowCustomNode } from '../../../enums/custom-nodes/ControlFlowCustomNode';
 
 
-export type TControlFlowCustomNodeFactory = (controlFlowCustomNodeName: ControlFlowCustomNode) => ICustomNode;
+export type TControlFlowCustomNodeFactory = <
+    TInitialData extends any[] = any[]
+> (controlFlowCustomNodeName: ControlFlowCustomNode) => ICustomNode<TInitialData>;

+ 3 - 1
src/types/container/custom-nodes/TCustomNodeFactory.d.ts

@@ -2,4 +2,6 @@ import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 
 
 import { CustomNode } from '../../../enums/custom-nodes/CustomNode';
 import { CustomNode } from '../../../enums/custom-nodes/CustomNode';
 
 
-export type TCustomNodeFactory = (customNodeName: CustomNode) => ICustomNode;
+export type TCustomNodeFactory = <
+    TInitialData extends any[] = any[]
+> (customNodeName: CustomNode) => ICustomNode<TInitialData>;

+ 3 - 1
src/types/container/custom-nodes/TDeadNodeInjectionCustomNodeFactory.d.ts

@@ -2,4 +2,6 @@ import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 
 
 import { DeadCodeInjectionCustomNode } from '../../../enums/custom-nodes/DeadCodeInjectionCustomNode';
 import { DeadCodeInjectionCustomNode } from '../../../enums/custom-nodes/DeadCodeInjectionCustomNode';
 
 
-export type TDeadNodeInjectionCustomNodeFactory = (deadCodeInjectionCustomNodeName: DeadCodeInjectionCustomNode) => ICustomNode;
+export type TDeadNodeInjectionCustomNodeFactory = <
+    TInitialData extends any[] = any[]
+> (deadCodeInjectionCustomNodeName: DeadCodeInjectionCustomNode) => ICustomNode <TInitialData>;

+ 3 - 1
src/types/container/custom-nodes/TObjectExpressionKeysTransformerCustomNodeFactory.d.ts

@@ -2,4 +2,6 @@ import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 
 
 import { ObjectExpressionKeysTransformerCustomNode } from '../../../enums/custom-nodes/ObjectExpressionKeysTransformerCustomNode';
 import { ObjectExpressionKeysTransformerCustomNode } from '../../../enums/custom-nodes/ObjectExpressionKeysTransformerCustomNode';
 
 
-export type TObjectExpressionKeysTransformerCustomNodeFactory = (objectExpressionKeysTransformerNodeName: ObjectExpressionKeysTransformerCustomNode) => ICustomNode;
+export type TObjectExpressionKeysTransformerCustomNodeFactory = <
+    TInitialData extends any[] = any[]
+> (objectExpressionKeysTransformerNodeName: ObjectExpressionKeysTransformerCustomNode) => ICustomNode <TInitialData>;

+ 31 - 0
src/utils/ArrayUtils.ts

@@ -34,6 +34,37 @@ export class ArrayUtils implements IArrayUtils {
         return range;
         return range;
     }
     }
 
 
+    /**
+     * @param {T[]} array
+     * @returns {T | null}
+     */
+    public findMostOccurringElement <T extends string | number> (array: T[]): T | null {
+        const arrayLength: number = array.length;
+
+        if (!arrayLength) {
+            return null;
+        }
+
+        const elementsMap: Partial<{[key in T]: number}> = {};
+
+        let mostOccurringElement: T = array[0];
+        let mostOccurringElementCount: number = 1;
+
+        for (const element of array) {
+            const currentElementCount: number = elementsMap[element] ?? 0;
+            const updatedElementCount: number = currentElementCount + 1;
+
+            if (updatedElementCount > mostOccurringElementCount) {
+                mostOccurringElement = element;
+                mostOccurringElementCount = updatedElementCount;
+            }
+
+            elementsMap[element] = updatedElementCount;
+        }
+
+        return mostOccurringElement;
+    }
+
     /**
     /**
      * @param {T[]} array
      * @param {T[]} array
      * @param {number} times
      * @param {number} times

+ 53 - 0
src/utils/TemplateFormatter.ts

@@ -0,0 +1,53 @@
+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;
+    }
+}

+ 4 - 7
test/dev/dev.ts

@@ -7,16 +7,13 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
 
 
     let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
     let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
         `
         `
-            (function () {
-                var a = 'a', b = 'b';
-                ({[a]: a, [b]: b} = {a: 1, b: 2});
-            
-                console.log(a, b);
-            })();
+            var foo = 'abcd'
+            var bar = 'abcde'
         `,
         `,
         {
         {
             ...NO_ADDITIONAL_NODES_PRESET,
             ...NO_ADDITIONAL_NODES_PRESET,
-            transformObjectKeys: true
+            stringArray: true,
+            stringArrayThreshold: 1
         }
         }
     ).getObfuscatedCode();
     ).getObfuscatedCode();
 
 

+ 134 - 0
test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts

@@ -15,6 +15,7 @@ import { IdentifierNamesGenerator } from '../../../src/enums/generators/identifi
 import { buildLargeCode } from '../../helpers/buildLargeCode';
 import { buildLargeCode } from '../../helpers/buildLargeCode';
 import { getRegExpMatch } from '../../helpers/getRegExpMatch';
 import { getRegExpMatch } from '../../helpers/getRegExpMatch';
 import { readFileAsString } from '../../helpers/readFileAsString';
 import { readFileAsString } from '../../helpers/readFileAsString';
+import { TInputOptions } from '../../../src/types/options/TInputOptions';
 
 
 describe('JavaScriptObfuscator', () => {
 describe('JavaScriptObfuscator', () => {
     describe('obfuscate', () => {
     describe('obfuscate', () => {
@@ -710,5 +711,138 @@ describe('JavaScriptObfuscator', () => {
                 assert.equal(areCollisionsExists, false);
                 assert.equal(areCollisionsExists, false);
             });
             });
         });
         });
+
+        describe('Prevailing kind of variables', () => {
+            const baseParams: TInputOptions = {
+                compact: true,
+                controlFlowFlattening: true,
+                controlFlowFlatteningThreshold: 1,
+                deadCodeInjection: true,
+                deadCodeInjectionThreshold: 1,
+                debugProtection: true,
+                debugProtectionInterval: true,
+                disableConsoleOutput: false,
+                rotateStringArray: true,
+                selfDefending: true,
+                stringArray: true,
+                stringArrayThreshold: 1,
+                transformObjectKeys: true,
+                unicodeEscapeSequence: false
+            };
+
+            describe('`var` kind', function () {
+                let obfuscatedCode: string;
+
+                before(() => {
+                    const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-var.js');
+
+                    obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                        code,
+                        {
+                            ...NO_ADDITIONAL_NODES_PRESET,
+                            ...baseParams,
+                            stringArrayEncoding: StringArrayEncoding.Rc4
+                        }
+                    ).getObfuscatedCode();
+
+                });
+
+                it('does not break on run', () => {
+                    assert.doesNotThrow(() => eval(obfuscatedCode));
+                });
+            });
+
+            describe('`const` kind', function () {
+                describe('Variant #1: StringArrayEncoding: rc4', () => {
+                    let obfuscatedCode: string;
+
+                    before(() => {
+                        const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-const.js');
+
+                        obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                            code,
+                            {
+                                ...NO_ADDITIONAL_NODES_PRESET,
+                                ...baseParams,
+                                stringArrayEncoding: StringArrayEncoding.Rc4
+                            }
+                        ).getObfuscatedCode();
+
+                    });
+
+                    it('does not break on run', () => {
+                        assert.doesNotThrow(() => eval(obfuscatedCode));
+                    });
+                });
+
+                describe('Variant #2: StringArrayEncoding: base64', () => {
+                    let obfuscatedCode: string;
+
+                    before(() => {
+                        const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-const.js');
+
+                        obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                            code,
+                            {
+                                ...NO_ADDITIONAL_NODES_PRESET,
+                                ...baseParams,
+                                stringArrayEncoding: StringArrayEncoding.Rc4
+                            }
+                        ).getObfuscatedCode();
+
+                    });
+
+                    it('does not break on run', () => {
+                        assert.doesNotThrow(() => eval(obfuscatedCode));
+                    });
+                });
+            });
+
+            describe('`let` kind', function () {
+                describe('Variant #1: StringArrayEncoding: rc4', () => {
+                    let obfuscatedCode: string;
+
+                    before(() => {
+                        const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-let.js');
+
+                        obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                            code,
+                            {
+                                ...NO_ADDITIONAL_NODES_PRESET,
+                                ...baseParams,
+                                stringArrayEncoding: StringArrayEncoding.Rc4
+                            }
+                        ).getObfuscatedCode();
+
+                    });
+
+                    it('does not break on run', () => {
+                        assert.doesNotThrow(() => eval(obfuscatedCode));
+                    });
+                });
+
+                describe('Variant #2: StringArrayEncoding: base64', () => {
+                    let obfuscatedCode: string;
+
+                    before(() => {
+                        const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-let.js');
+
+                        obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                            code,
+                            {
+                                ...NO_ADDITIONAL_NODES_PRESET,
+                                ...baseParams,
+                                stringArrayEncoding: StringArrayEncoding.Rc4
+                            }
+                        ).getObfuscatedCode();
+
+                    });
+
+                    it('does not break on run', () => {
+                        assert.doesNotThrow(() => eval(obfuscatedCode));
+                    });
+                });
+            });
+        });
     });
     });
 });
 });

+ 32 - 0
test/functional-tests/javascript-obfuscator/fixtures/prevailing-kind-of-variables-const.js

@@ -0,0 +1,32 @@
+const foo = 'foo';
+const bar = 'bar';
+const baz = 'baz';
+const bark = 'bark';
+const hawk = 'hawk';
+
+function test() {
+    var foo = 'foo';
+
+    if (true) {
+        foo += 'o';
+    }
+
+    if (true) {
+        foo += 'o';
+    }
+
+    if (true) {
+        foo += 'o';
+    }
+
+    if (true) {
+        foo += 'o';
+    }
+
+    if (true) {
+        foo += 'o';
+    }
+
+    return foo;
+}
+test();

+ 32 - 0
test/functional-tests/javascript-obfuscator/fixtures/prevailing-kind-of-variables-let.js

@@ -0,0 +1,32 @@
+let foo = 'foo';
+let bar = 'bar';
+let baz = 'baz';
+let bark = 'bark';
+let hawk = 'hawk';
+
+function test() {
+    var foo = 'foo';
+
+    if (true) {
+        foo += 'o';
+    }
+
+    if (true) {
+        foo += 'o';
+    }
+
+    if (true) {
+        foo += 'o';
+    }
+
+    if (true) {
+        foo += 'o';
+    }
+
+    if (true) {
+        foo += 'o';
+    }
+
+    return foo;
+}
+test();

+ 32 - 0
test/functional-tests/javascript-obfuscator/fixtures/prevailing-kind-of-variables-var.js

@@ -0,0 +1,32 @@
+var foo = 'foo';
+var bar = 'bar';
+var baz = 'baz';
+var bark = 'bark';
+var hawk = 'hawk';
+
+function test() {
+    var foo = 'foo';
+
+    if (true) {
+        foo += 'o';
+    }
+
+    if (true) {
+        foo += 'o';
+    }
+
+    if (true) {
+        foo += 'o';
+    }
+
+    if (true) {
+        foo += 'o';
+    }
+
+    if (true) {
+        foo += 'o';
+    }
+
+    return foo;
+}
+test();

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

@@ -650,5 +650,124 @@ describe('BlockStatementControlFlowTransformer', function () {
                 assert.match(obfuscatedCode, returnStatementRegExp);
                 assert.match(obfuscatedCode, returnStatementRegExp);
             });
             });
         });
         });
+
+        describe('Prevailing kind of variables', () => {
+            describe('`var` kind', () => {
+                let obfuscatedCode: string;
+
+                before(() => {
+                    const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-var.js');
+
+                    obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                        code,
+                        {
+                            ...NO_ADDITIONAL_NODES_PRESET,
+                            controlFlowFlattening: true,
+                            controlFlowFlatteningThreshold: 1
+                        }
+                    ).getObfuscatedCode();
+                });
+
+                describe('switch-case map', () => {
+                    const switchCaseMapVariableRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *_0x(?:[a-f0-9]){4,6}\['.*'\]\['split'\]\('\|'\)/;
+                    const switchCaseMapStringRegExp: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *\{'.*' *: *'(.*)'\};/;
+                    const expectedSwitchCasesSequence: string[] = ['0', '1', '2', '3', '4'];
+
+                    let switchCaseMap: string[];
+
+                    before(() => {
+                        const switchCaseMapMatch: string = getRegExpMatch(obfuscatedCode, switchCaseMapStringRegExp);
+
+                        switchCaseMap = switchCaseMapMatch.split('|').sort();
+                    });
+
+                    it('should use correct kind of variable for switch-case map', () => {
+                        assert.match(obfuscatedCode, switchCaseMapVariableRegExp);
+                    });
+
+                    it('should use correct kind of variable for switch cases sequence', () => {
+                        assert.deepEqual(switchCaseMap, expectedSwitchCasesSequence);
+                    });
+                });
+            });
+
+            describe('`const` kind', () => {
+                let obfuscatedCode: string;
+
+                before(() => {
+                    const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-const.js');
+
+                    obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                        code,
+                        {
+                            ...NO_ADDITIONAL_NODES_PRESET,
+                            controlFlowFlattening: true,
+                            controlFlowFlatteningThreshold: 1
+                        }
+                    ).getObfuscatedCode();
+                });
+
+                describe('switch-case map', () => {
+                    const switchCaseMapVariableRegExp: RegExp = /const *_0x(?:[a-f0-9]){4,6} *= *_0x(?:[a-f0-9]){4,6}\['.*'\]\['split'\]\('\|'\)/;
+                    const switchCaseMapStringRegExp: RegExp = /const *_0x(?:[a-f0-9]){4,6} *= *\{'.*' *: *'(.*)'\};/;
+                    const expectedSwitchCasesSequence: string[] = ['0', '1', '2', '3', '4'];
+
+                    let switchCaseMap: string[];
+
+                    before(() => {
+                        const switchCaseMapMatch: string = getRegExpMatch(obfuscatedCode, switchCaseMapStringRegExp);
+
+                        switchCaseMap = switchCaseMapMatch.split('|').sort();
+                    });
+
+                    it('should use correct kind of variable for switch-case map', () => {
+                        assert.match(obfuscatedCode, switchCaseMapVariableRegExp);
+                    });
+
+                    it('should use correct kind of variable for switch cases sequence', () => {
+                        assert.deepEqual(switchCaseMap, expectedSwitchCasesSequence);
+                    });
+                });
+            });
+
+            describe('`let` kind', () => {
+                let obfuscatedCode: string;
+
+                before(() => {
+                    const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-let.js');
+
+                    obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                        code,
+                        {
+                            ...NO_ADDITIONAL_NODES_PRESET,
+                            controlFlowFlattening: true,
+                            controlFlowFlatteningThreshold: 1
+                        }
+                    ).getObfuscatedCode();
+                });
+
+                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 expectedSwitchCasesSequence: string[] = ['0', '1', '2', '3', '4'];
+
+                    let switchCaseMap: string[];
+
+                    before(() => {
+                        const switchCaseMapMatch: string = getRegExpMatch(obfuscatedCode, switchCaseMapStringRegExp);
+
+                        switchCaseMap = switchCaseMapMatch.split('|').sort();
+                    });
+
+                    it('should use correct kind of variable for switch-case map', () => {
+                        assert.match(obfuscatedCode, switchCaseMapVariableRegExp);
+                    });
+
+                    it('should use correct kind of variable for switch cases sequence', () => {
+                        assert.deepEqual(switchCaseMap, expectedSwitchCasesSequence);
+                    });
+                });
+            });
+        });
     });
     });
 });
 });

+ 9 - 0
test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/fixtures/prevailing-kind-of-variables-const.js

@@ -0,0 +1,9 @@
+const test = 0;
+
+(function () {
+    console.log(1);
+    console.log(2);
+    console.log(3);
+    console.log(4);
+    console.log(5);
+})();

+ 9 - 0
test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/fixtures/prevailing-kind-of-variables-let.js

@@ -0,0 +1,9 @@
+let test = 0;
+
+(function () {
+    console.log(1);
+    console.log(2);
+    console.log(3);
+    console.log(4);
+    console.log(5);
+})();

+ 9 - 0
test/functional-tests/node-transformers/control-flow-transformers/block-statement-control-flow-transformer/fixtures/prevailing-kind-of-variables-var.js

@@ -0,0 +1,9 @@
+var test = 0;
+
+(function () {
+    console.log(1);
+    console.log(2);
+    console.log(3);
+    console.log(4);
+    console.log(5);
+})();

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

@@ -268,5 +268,76 @@ describe('FunctionControlFlowTransformer', function () {
                 });
                 });
             });
             });
         });
         });
+
+        describe('prevailing kind of variables', () => {
+            describe('Variant #1 - `var` kind', () => {
+                const regexp: RegExp = new RegExp(`var *${variableMatch} *= *\\{`);
+
+                let obfuscatedCode: string;
+
+                before(() => {
+                    const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-var.js');
+
+                    obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                        code,
+                        {
+                            ...NO_ADDITIONAL_NODES_PRESET,
+                            controlFlowFlattening: true,
+                            controlFlowFlatteningThreshold: 1
+                        }
+                    ).getObfuscatedCode();
+                });
+
+                it('should use correct kind of variables for `control flow storage`', () => {
+                    assert.match(obfuscatedCode, regexp);
+                });
+            });
+
+            describe('Variant #2 - `const` kind', () => {
+                const regexp: RegExp = new RegExp(`const *${variableMatch} *= *\\{`);
+
+                let obfuscatedCode: string;
+
+                before(() => {
+                    const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-const.js');
+
+                    obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                        code,
+                        {
+                            ...NO_ADDITIONAL_NODES_PRESET,
+                            controlFlowFlattening: true,
+                            controlFlowFlatteningThreshold: 1
+                        }
+                    ).getObfuscatedCode();
+                });
+
+                it('should use correct kind of variables for `control flow storage`', () => {
+                    assert.match(obfuscatedCode, regexp);
+                });
+            });
+
+            describe('Variant #3 - `let` kind', () => {
+                const regexp: RegExp = new RegExp(`let *${variableMatch} *= *\\{`);
+
+                let obfuscatedCode: string;
+
+                before(() => {
+                    const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-let.js');
+
+                    obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                        code,
+                        {
+                            ...NO_ADDITIONAL_NODES_PRESET,
+                            controlFlowFlattening: true,
+                            controlFlowFlatteningThreshold: 1
+                        }
+                    ).getObfuscatedCode();
+                });
+
+                it('should use correct kind of variables for `control flow storage`', () => {
+                    assert.match(obfuscatedCode, regexp);
+                });
+            });
+        });
     });
     });
 });
 });

+ 3 - 0
test/functional-tests/node-transformers/control-flow-transformers/function-control-flow-transformer/fixtures/prevailing-kind-of-variables-const.js

@@ -0,0 +1,3 @@
+(function () {
+    const variable = 1 + 2;
+})();

+ 3 - 0
test/functional-tests/node-transformers/control-flow-transformers/function-control-flow-transformer/fixtures/prevailing-kind-of-variables-let.js

@@ -0,0 +1,3 @@
+(function () {
+    let variable = 1 + 2;
+})();

+ 3 - 0
test/functional-tests/node-transformers/control-flow-transformers/function-control-flow-transformer/fixtures/prevailing-kind-of-variables-var.js

@@ -0,0 +1,3 @@
+(function () {
+    var variable = 1 + 2;
+})();

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

@@ -316,7 +316,7 @@ describe('ObjectExpressionKeysTransformer', () => {
                 const match: string = `` +
                 const match: string = `` +
                     `var *${variableMatch} *= *{};` +
                     `var *${variableMatch} *= *{};` +
                     `${variableMatch}\\['foo'] *= *'foo';` +
                     `${variableMatch}\\['foo'] *= *'foo';` +
-                    `const *${variableMatch} *= *${variableMatch}, *` +
+                    `var *${variableMatch} *= *${variableMatch}, *` +
                     `${variableMatch} *= *${variableMatch}\\['foo'];` +
                     `${variableMatch} *= *${variableMatch}\\['foo'];` +
                 ``;
                 ``;
                 const regExp: RegExp = new RegExp(match);
                 const regExp: RegExp = new RegExp(match);
@@ -344,7 +344,7 @@ describe('ObjectExpressionKeysTransformer', () => {
                 const match: string = `` +
                 const match: string = `` +
                     `var *${variableMatch} *= *{};` +
                     `var *${variableMatch} *= *{};` +
                     `${variableMatch}\\['foo'] *= *'foo';` +
                     `${variableMatch}\\['foo'] *= *'foo';` +
-                    `const *${variableMatch} *= *${variableMatch}, *` +
+                    `var *${variableMatch} *= *${variableMatch}, *` +
                     `${variableMatch} *= *\\[${variableMatch}\\['foo']];` +
                     `${variableMatch} *= *\\[${variableMatch}\\['foo']];` +
                 ``;
                 ``;
                 const regExp: RegExp = new RegExp(match);
                 const regExp: RegExp = new RegExp(match);
@@ -959,7 +959,7 @@ describe('ObjectExpressionKeysTransformer', () => {
                 const match: string = `` +
                 const match: string = `` +
                     `var *${variableMatch} *= *{};` +
                     `var *${variableMatch} *= *{};` +
                     `${variableMatch}\\['bar'] *= *'bar';` +
                     `${variableMatch}\\['bar'] *= *'bar';` +
-                    `const *${variableMatch} *= *{}, *` +
+                    `var *${variableMatch} *= *{}, *` +
                         `${variableMatch} *= *${variableMatch}, *` +
                         `${variableMatch} *= *${variableMatch}, *` +
                         `${variableMatch} *= *${variableMatch}\\['bar']; *` +
                         `${variableMatch} *= *${variableMatch}\\['bar']; *` +
                     `${variableMatch}\\['foo'] *= *'foo';` +
                     `${variableMatch}\\['foo'] *= *'foo';` +
@@ -988,6 +988,89 @@ describe('ObjectExpressionKeysTransformer', () => {
         });
         });
     });
     });
 
 
+    describe('prevailing kind of variables', () => {
+        describe('Variant #1: `var` kind`', () => {
+            const match: string = `` +
+                `var *${variableMatch} *= *{};` +
+                `${variableMatch}\\['foo'] *= *'bar';` +
+                `${variableMatch}\\['baz'] *= *'bark';` +
+            ``;
+            const regExp: RegExp = new RegExp(match);
+
+            let obfuscatedCode: string;
+
+            before(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-var.js');
+
+                obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_ADDITIONAL_NODES_PRESET,
+                        transformObjectKeys: true
+                    }
+                ).getObfuscatedCode();
+            });
+
+            it('should use correct kind of variables', () => {
+                assert.match(obfuscatedCode,  regExp);
+            });
+        });
+
+        describe('Variant #2: `const` kind`', () => {
+            const match: string = `` +
+                `const *${variableMatch} *= *{};` +
+                `${variableMatch}\\['foo'] *= *'bar';` +
+                `${variableMatch}\\['baz'] *= *'bark';` +
+            ``;
+            const regExp: RegExp = new RegExp(match);
+
+            let obfuscatedCode: string;
+
+            before(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-const.js');
+
+                obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_ADDITIONAL_NODES_PRESET,
+                        transformObjectKeys: true
+                    }
+                ).getObfuscatedCode();
+            });
+
+            it('should use correct kind of variables', () => {
+                assert.match(obfuscatedCode,  regExp);
+            });
+        });
+
+        describe('Variant #3: `let` kind`', () => {
+            const match: string = `` +
+                `let *${variableMatch} *= *{};` +
+                `${variableMatch}\\['foo'] *= *'bar';` +
+                `${variableMatch}\\['baz'] *= *'bark';` +
+            ``;
+            const regExp: RegExp = new RegExp(match);
+
+            let obfuscatedCode: string;
+
+            before(() => {
+                const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-let.js');
+
+                obfuscatedCode = JavaScriptObfuscator.obfuscate(
+                    code,
+                    {
+                        ...NO_ADDITIONAL_NODES_PRESET,
+                        transformObjectKeys: true
+                    }
+                ).getObfuscatedCode();
+            });
+
+            it('should use correct kind of variables', () => {
+                assert.match(obfuscatedCode,  regExp);
+            });
+        });
+    });
+
     describe('Ignore transformation', () => {
     describe('Ignore transformation', () => {
         describe('Variant #1: disabled option', () => {
         describe('Variant #1: disabled option', () => {
             const match: string = `` +
             const match: string = `` +

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

@@ -0,0 +1,6 @@
+(function(){
+    const object = {
+        foo: 'bar',
+        baz: 'bark'
+    };
+})();

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

@@ -0,0 +1,6 @@
+(function(){
+    let object = {
+        foo: 'bar',
+        baz: 'bark'
+    };
+})();

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

@@ -0,0 +1,6 @@
+(function(){
+    var object = {
+        foo: 'bar',
+        baz: 'bark'
+    };
+})();

+ 1 - 1
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/variable-declarator-with-object-call-3.js

@@ -1,5 +1,5 @@
 (function () {
 (function () {
-    const object1 = {foo: 'foo'},
+    var object1 = {foo: 'foo'},
         object2 = {bar: 'bar'},
         object2 = {bar: 'bar'},
         variable = object2.bar;
         variable = object2.bar;
     console.log(variable);
     console.log(variable);

+ 1 - 1
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/variable-declarator-with-object-call-4.js

@@ -1,4 +1,4 @@
 (function () {
 (function () {
-    const object = {foo: 'foo'},
+    var object = {foo: 'foo'},
         variable = object.foo;
         variable = object.foo;
 })();
 })();

+ 1 - 1
test/functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/fixtures/variable-declarator-with-object-call-5.js

@@ -1,4 +1,4 @@
 (function () {
 (function () {
-    const object = {foo: 'foo'},
+    var object = {foo: 'foo'},
         variable = [object.foo];
         variable = [object.foo];
 })();
 })();

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác