Explorar el Código

Utility classes with state now are non-static

sanex3339 hace 8 años
padre
commit
d21c5afa8a
Se han modificado 93 ficheros con 1695 adiciones y 995 borrados
  1. 1 0
      CHANGELOG.md
  2. 0 0
      dist/index.js
  3. 8 8
      package.json
  4. 3 6
      src/JavaScriptObfuscator.ts
  5. 11 1
      src/JavaScriptObfuscatorInternal.ts
  6. 10 3
      src/SourceMapCorrector.ts
  7. 100 57
      src/container/InversifyContainerFacade.ts
  8. 35 29
      src/container/ServiceIdentifiers.ts
  9. 61 74
      src/container/modules/custom-nodes/CustomNodesModule.ts
  10. 5 1
      src/container/modules/storages/StoragesModule.ts
  11. 34 0
      src/container/modules/utils/UtilsModule.ts
  12. 16 0
      src/custom-nodes/AbstractCustomNodeGroup.ts
  13. 11 2
      src/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.ts
  14. 6 4
      src/custom-nodes/console-output-nodes/group/ConsoleOutputCustomNodeGroup.ts
  15. 11 2
      src/custom-nodes/control-flow-flattening-nodes/BinaryExpressionFunctionNode.ts
  16. 12 3
      src/custom-nodes/control-flow-flattening-nodes/BlockStatementControlFlowFlatteningNode.ts
  17. 11 2
      src/custom-nodes/control-flow-flattening-nodes/CallExpressionFunctionNode.ts
  18. 11 2
      src/custom-nodes/control-flow-flattening-nodes/LogicalExpressionFunctionNode.ts
  19. 10 0
      src/custom-nodes/control-flow-flattening-nodes/StringLiteralNode.ts
  20. 10 0
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/CallExpressionControlFlowStorageCallNode.ts
  21. 10 0
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ControlFlowStorageNode.ts
  22. 10 0
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/ExpressionWithOperatorControlFlowStorageCallNode.ts
  23. 10 0
      src/custom-nodes/control-flow-flattening-nodes/control-flow-storage-nodes/StringLiteralControlFlowStorageCallNode.ts
  24. 6 4
      src/custom-nodes/debug-protection-nodes/group/DebugProtectionCustomNodeGroup.ts
  25. 24 4
      src/custom-nodes/domain-lock-nodes/DomainLockNode.ts
  26. 6 4
      src/custom-nodes/domain-lock-nodes/group/DomainLockCustomNodeGroup.ts
  27. 22 4
      src/custom-nodes/self-defending-nodes/SelfDefendingUnicodeNode.ts
  28. 6 4
      src/custom-nodes/self-defending-nodes/group/SelfDefendingCustomNodeGroup.ts
  29. 11 1
      src/custom-nodes/string-array-nodes/StringArrayCallsWrapper.ts
  30. 22 4
      src/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.ts
  31. 5 3
      src/custom-nodes/string-array-nodes/group/StringArrayCustomNodeGroup.ts
  32. 11 0
      src/enums/container/custom-nodes/ControlFlowCustomNode.ts
  33. 1 10
      src/enums/container/custom-nodes/CustomNode.ts
  34. 9 0
      src/interfaces/container/IInversifyContainerFacade.d.ts
  35. 20 0
      src/interfaces/utils/IArrayUtils.d.ts
  36. 21 0
      src/interfaces/utils/ICryptUtils.d.ts
  37. 7 0
      src/interfaces/utils/IEscapeSequenceEncoder.d.ts
  38. 40 0
      src/interfaces/utils/IRandomGenerator.d.ts
  39. 12 3
      src/node-transformers/AbstractNodeTransformer.ts
  40. 26 15
      src/node-transformers/control-flow-transformers/BlockStatementControlFlowTransformer.ts
  41. 45 38
      src/node-transformers/control-flow-transformers/FunctionControlFlowTransformer.ts
  42. 19 11
      src/node-transformers/control-flow-transformers/control-flow-replacers/AbstractControlFlowReplacer.ts
  43. 12 6
      src/node-transformers/control-flow-transformers/control-flow-replacers/BinaryExpressionControlFlowReplacer.ts
  44. 14 8
      src/node-transformers/control-flow-transformers/control-flow-replacers/CallExpressionControlFlowReplacer.ts
  45. 12 12
      src/node-transformers/control-flow-transformers/control-flow-replacers/ExpressionWithOperatorControlFlowReplacer.ts
  46. 12 6
      src/node-transformers/control-flow-transformers/control-flow-replacers/LogicalExpressionControlFlowReplacer.ts
  47. 14 8
      src/node-transformers/control-flow-transformers/control-flow-replacers/StringLiteralControlFlowReplacer.ts
  48. 4 1
      src/node-transformers/converting-transformers/MemberExpressionTransformer.ts
  49. 4 1
      src/node-transformers/converting-transformers/MethodDefinitionTransformer.ts
  50. 4 1
      src/node-transformers/converting-transformers/TemplateLiteralTransformer.ts
  51. 39 37
      src/node-transformers/dead-code-injection-transformers/DeadCodeInjectionTransformer.ts
  52. 4 1
      src/node-transformers/obfuscating-transformers/CatchClauseTransformer.ts
  53. 4 1
      src/node-transformers/obfuscating-transformers/FunctionDeclarationTransformer.ts
  54. 4 1
      src/node-transformers/obfuscating-transformers/FunctionTransformer.ts
  55. 4 1
      src/node-transformers/obfuscating-transformers/LabeledStatementTransformer.ts
  56. 4 1
      src/node-transformers/obfuscating-transformers/LiteralTransformer.ts
  57. 4 1
      src/node-transformers/obfuscating-transformers/ObjectExpressionTransformer.ts
  58. 5 2
      src/node-transformers/obfuscating-transformers/VariableDeclarationTransformer.ts
  59. 11 2
      src/node-transformers/obfuscating-transformers/obfuscating-replacers/identifier-obfuscating-replacers/BaseIdentifierObfuscatingReplacer.ts
  60. 36 14
      src/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/StringLiteralObfuscatingReplacer.ts
  61. 0 9
      src/node/NodeAppender.ts
  62. 18 4
      src/storages/ArrayStorage.ts
  63. 18 4
      src/storages/MapStorage.ts
  64. 12 2
      src/storages/control-flow/ControlFlowStorage.ts
  65. 5 3
      src/storages/custom-node-group/CustomNodeGroupStorage.ts
  66. 24 7
      src/storages/string-array/StringArrayStorage.ts
  67. 4 4
      src/templates/custom-nodes/self-defending-nodes/self-defending-unicode-node/SelfDefendingTemplate.ts
  68. 4 4
      src/templates/custom-nodes/string-array-nodes/string-array-calls-wrapper/SelfDefendingTemplate.ts
  69. 3 3
      src/templates/custom-nodes/string-array-nodes/string-array-rotate-function-node/SelfDefendingTemplate.ts
  70. 6 0
      src/types/container/custom-nodes/TControlFlowCustomNodeFactory.d.ts
  71. 78 0
      src/utils/ArrayUtils.ts
  72. 31 10
      src/utils/CryptUtils.ts
  73. 52 0
      src/utils/EscapeSequenceEncoder.ts
  74. 125 0
      src/utils/RandomGenerator.ts
  75. 0 127
      src/utils/RandomGeneratorUtils.ts
  76. 0 112
      src/utils/Utils.ts
  77. 7 4
      test/functional-tests/javascript-obfuscator-internal/JavaScriptObfuscatorInternal.spec.ts
  78. 0 10
      test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts
  79. 10 5
      test/functional-tests/stack-trace-analyzer/stack-trace-analyzer/StackTraceAnalyzer.spec.ts
  80. 18 4
      test/functional-tests/templates/custom-nodes/domain-lock-nodes/DomainLockNodeTemplate.spec.ts
  81. 35 55
      test/functional-tests/templates/custom-nodes/string-array-nodes/StringArrayCallsWrapperNodeTemplate.spec.ts
  82. 5 3
      test/index.spec.ts
  83. 11 19
      test/unit-tests/node/node-appender/NodeAppender.spec.ts
  84. 4 1
      test/unit-tests/source-map-corrector/SourceMapCorrector.spec.ts
  85. 10 1
      test/unit-tests/storages/ArrayStorage.spec.ts
  86. 10 1
      test/unit-tests/storages/MapStorage.spec.ts
  87. 117 0
      test/unit-tests/utils/ArrayUtils.spec.ts
  88. 19 5
      test/unit-tests/utils/CryptUtils.spec.ts
  89. 52 0
      test/unit-tests/utils/EscapeSequenceEncoder.spec.ts
  90. 45 0
      test/unit-tests/utils/RandomGeneratorUtils.spec.ts
  91. 2 132
      test/unit-tests/utils/Utils.spec.ts
  92. 0 32
      test/unit-tests/utils/random-generator-utils/RandomGeneratorUtils.spec.ts
  93. 70 31
      yarn.lock

+ 1 - 0
CHANGELOG.md

@@ -10,6 +10,7 @@ v0.10.0
 * increased runtime performance with `rc4` `stringArrayEncoding`.
 * added support for async functions
 * fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/57
+* fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/54
 
 v0.9.3
 ---

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
dist/index.js


+ 8 - 8
package.json

@@ -1,6 +1,6 @@
 {
   "name": "javascript-obfuscator",
-  "version": "0.10.0-beta.4",
+  "version": "0.10.0-beta.5",
   "description": "JavaScript obfuscator",
   "keywords": [
     "obfuscator",
@@ -21,7 +21,7 @@
   "dependencies": {
     "chance": "1.0.10",
     "class-validator": "0.7.1",
-    "commander": "2.9.0",
+    "commander": "2.10.0",
     "escodegen-wallaby": "1.6.11",
     "esmangle": "1.0.1",
     "esprima": "4.0.0",
@@ -35,7 +35,7 @@
     "tslib": "1.7.1"
   },
   "devDependencies": {
-    "@types/chai": "4.0.0",
+    "@types/chai": "4.0.1",
     "@types/chance": "0.7.33",
     "@types/commander": "2.9.1",
     "@types/escodegen": "0.0.6",
@@ -44,12 +44,12 @@
     "@types/estree": "0.0.35",
     "@types/mkdirp": "0.3.29",
     "@types/mocha": "2.2.41",
-    "@types/node": "8.0.0",
-    "@types/sinon": "2.3.1",
+    "@types/node": "8.0.3",
+    "@types/sinon": "2.3.2",
     "@types/string-template": "1.0.2",
     "awesome-typescript-loader": "3.1.3",
     "babel-cli": "6.24.1",
-    "babel-loader": "7.0.0",
+    "babel-loader": "7.1.0",
     "babel-plugin-array-includes": "2.0.3",
     "babel-preset-es2015": "6.24.1",
     "chai": "4.0.2",
@@ -57,8 +57,8 @@
     "istanbul": "1.1.0-alpha.1",
     "mocha": "3.4.2",
     "pre-commit": "1.2.2",
-    "sinon": "2.3.4",
-    "ts-node": "3.0.6",
+    "sinon": "2.3.5",
+    "ts-node": "3.1.0",
     "tslint": "5.4.3",
     "tslint-loader": "3.5.3",
     "typescript": "2.4.0",

+ 3 - 6
src/JavaScriptObfuscator.ts

@@ -7,11 +7,9 @@ import { TInputOptions } from './types/options/TInputOptions';
 import { IInversifyContainerFacade } from './interfaces/container/IInversifyContainerFacade';
 import { IJavaScriptObfuscator } from './interfaces/IJavaScriptObfsucator';
 import { IObfuscationResult } from './interfaces/IObfuscationResult';
-import { IOptions } from './interfaces/options/IOptions';
 
 import { InversifyContainerFacade } from './container/InversifyContainerFacade';
 import { JavaScriptObfuscatorCLI } from './cli/JavaScriptObfuscatorCLI';
-import { RandomGeneratorUtils } from './utils/RandomGeneratorUtils';
 
 export class JavaScriptObfuscator {
     /**
@@ -20,16 +18,15 @@ export class JavaScriptObfuscator {
      * @returns {string}
      */
     public static obfuscate (sourceCode: string, inputOptions: TInputOptions = {}): IObfuscationResult {
-        const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade(inputOptions);
-        const options: IOptions = inversifyContainerFacade.get<IOptions>(ServiceIdentifiers.IOptions);
+        const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
 
-        RandomGeneratorUtils.initializeRandomGenerator(options.seed);
+        inversifyContainerFacade.load(inputOptions);
 
         const javaScriptObfuscator: IJavaScriptObfuscator = inversifyContainerFacade
             .get<IJavaScriptObfuscator>(ServiceIdentifiers.IJavaScriptObfuscator);
         const obfuscationResult: IObfuscationResult = javaScriptObfuscator.obfuscate(sourceCode);
 
-        RandomGeneratorUtils.clearRandomGenerator();
+        inversifyContainerFacade.unload();
 
         return obfuscationResult;
     }

+ 11 - 1
src/JavaScriptObfuscatorInternal.ts

@@ -59,7 +59,7 @@ export class JavaScriptObfuscatorInternal implements IJavaScriptObfuscator {
      */
     public obfuscate (sourceCode: string): IObfuscationResult {
         // parse AST tree
-        const astTree: ESTree.Program = esprima.parse(sourceCode, { loc: this.options.sourceMap });
+        const astTree: ESTree.Program = this.parseCode(sourceCode);
 
         // obfuscate AST tree
         const obfuscatedAstTree: ESTree.Program = this.obfuscator.obfuscateAstTree(astTree);
@@ -70,6 +70,16 @@ export class JavaScriptObfuscatorInternal implements IJavaScriptObfuscator {
         return this.getObfuscationResult(generatorOutput);
     }
 
+    /**
+     * @param sourceCode
+     * @return {ESTree.Program}
+     */
+    private parseCode (sourceCode: string): ESTree.Program {
+        return esprima.parse(sourceCode, {
+            loc: this.options.sourceMap
+        });
+    }
+
     /**
      * @param sourceCode
      * @param astTree

+ 10 - 3
src/SourceMapCorrector.ts

@@ -3,16 +3,20 @@ import { ServiceIdentifiers } from './container/ServiceIdentifiers';
 
 import { TObfuscationResultFactory } from './types/container/TObfuscationResultFactory';
 
+import { ICryptUtils } from './interfaces/utils/ICryptUtils';
 import { IObfuscationResult } from './interfaces/IObfuscationResult';
 import { IOptions } from './interfaces/options/IOptions';
 import { ISourceMapCorrector } from './interfaces/ISourceMapCorrector';
 
 import { SourceMapMode } from './enums/SourceMapMode';
 
-import { CryptUtils } from './utils/CryptUtils';
-
 @injectable()
 export class SourceMapCorrector implements ISourceMapCorrector {
+    /**
+     * @type {ICryptUtils}
+     */
+    private readonly cryptUtils: ICryptUtils;
+
     /**
      * @type {TObfuscationResultFactory}
      */
@@ -25,13 +29,16 @@ export class SourceMapCorrector implements ISourceMapCorrector {
 
     /**
      * @param obfuscationResultFactory
+     * @param cryptUtils
      * @param options
      */
     constructor (
         @inject(ServiceIdentifiers.Factory__IObfuscationResult) obfuscationResultFactory: TObfuscationResultFactory,
+        @inject(ServiceIdentifiers.ICryptUtils) cryptUtils: ICryptUtils,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         this.obfuscationResultFactory = obfuscationResultFactory;
+        this.cryptUtils = cryptUtils;
         this.options = options;
     }
 
@@ -63,7 +70,7 @@ export class SourceMapCorrector implements ISourceMapCorrector {
 
         switch (this.options.sourceMapMode) {
             case SourceMapMode.Inline:
-                sourceMappingUrl += `data:application/json;base64,${CryptUtils.btoa(sourceMap)}`;
+                sourceMappingUrl += `data:application/json;base64,${this.cryptUtils.btoa(sourceMap)}`;
 
                 break;
 

+ 100 - 57
src/container/InversifyContainerFacade.ts

@@ -7,6 +7,7 @@ import { obfuscatingTransformersModule } from './modules/node-transformers/Obfus
 import { nodeTransformersModule } from './modules/node-transformers/NodeTransformersModule';
 import { stackTraceAnalyzerModule } from './modules/stack-trace-analyzer/StackTraceAnalyzerModule';
 import { storagesModule } from './modules/storages/StoragesModule';
+import { utilsModule } from './modules/utils/UtilsModule';
 
 import { TInputOptions } from '../types/options/TInputOptions';
 
@@ -31,64 +32,8 @@ export class InversifyContainerFacade implements IInversifyContainerFacade {
      */
     private readonly container: interfaces.Container;
 
-    /**
-     * @param options
-     */
-    constructor (options: TInputOptions) {
+    constructor () {
         this.container = new Container();
-
-        this.container
-            .bind<IOptions>(ServiceIdentifiers.IOptions)
-            .toDynamicValue(() => {
-                return new Options(options);
-            })
-            .inSingletonScope();
-
-        this.container
-            .bind<IJavaScriptObfuscator>(ServiceIdentifiers.IJavaScriptObfuscator)
-            .to(JavaScriptObfuscatorInternal)
-            .inSingletonScope();
-
-        this.container
-            .bind<IObfuscator>(ServiceIdentifiers.IObfuscator)
-            .to(Obfuscator)
-            .inSingletonScope();
-
-        this.container
-            .bind<IObfuscationResult>(ServiceIdentifiers.IObfuscationResult)
-            .to(ObfuscationResult)
-            .inSingletonScope();
-
-        this.container
-            .bind<IObfuscationResult>(ServiceIdentifiers.Factory__IObfuscationResult)
-            .toFactory<IObfuscationResult>((context: interfaces.Context) => {
-                return (obfuscatedCode: string, sourceMap: string) => {
-                    const obfuscationResult: IObfuscationResult = context.container
-                        .get<IObfuscationResult>(ServiceIdentifiers.IObfuscationResult);
-
-                    obfuscationResult.initialize(obfuscatedCode, sourceMap);
-
-                    return obfuscationResult;
-                };
-            });
-
-        this.container
-            .bind<ISourceMapCorrector>(ServiceIdentifiers.ISourceMapCorrector)
-            .to(SourceMapCorrector)
-            .inSingletonScope();
-
-        this.container
-            .bind<IObfuscationEventEmitter>(ServiceIdentifiers.IObfuscationEventEmitter)
-            .to(ObfuscationEventEmitter)
-            .inSingletonScope();
-
-        // modules
-        this.container.load(storagesModule);
-        this.container.load(stackTraceAnalyzerModule);
-        this.container.load(customNodesModule);
-        this.container.load(nodeTransformersModule);
-        this.container.load(controlFlowTransformersModule);
-        this.container.load(obfuscatingTransformersModule);
     }
 
     /**
@@ -129,6 +74,43 @@ export class InversifyContainerFacade implements IInversifyContainerFacade {
         };
     }
 
+    /**
+     * @param serviceIdentifier
+     * @param dependencies
+     * @return {(context: interfaces.Context) => (bindingName: T) => U}
+     */
+    public static getConstructorFactory <T extends number, U> (
+        serviceIdentifier: interfaces.ServiceIdentifier<interfaces.Newable<U>>,
+        ...dependencies: any[]
+    ): (context: interfaces.Context) => (bindingName: T) => U {
+        return (context: interfaces.Context): (bindingName: T) => U => {
+            const cache: Map<T, interfaces.Newable<U>> = new Map();
+            const cachedDependencies: any[] = [];
+
+            return (bindingName: T) => {
+                dependencies.forEach((dependency: any, index: number) => {
+                    if (!cachedDependencies[index]) {
+                        cachedDependencies[index] = context.container.get<any>(dependency);
+                    }
+                });
+
+                if (cache.has(bindingName)) {
+                    return new (<interfaces.Newable<U>>cache.get(bindingName))(...cachedDependencies);
+                }
+
+                const constructor: interfaces.Newable<U> = context.container
+                    .getNamed<interfaces.Newable<U>>(
+                        serviceIdentifier,
+                        bindingName
+                    );
+
+                cache.set(bindingName, constructor);
+
+                return new constructor(...cachedDependencies);
+            };
+        };
+    }
+
     /**
      * @param serviceIdentifier
      * @returns {T}
@@ -145,4 +127,65 @@ export class InversifyContainerFacade implements IInversifyContainerFacade {
     public getNamed <T> (serviceIdentifier: interfaces.ServiceIdentifier<T>, named: string | number | symbol): T {
         return this.container.getNamed<T>(serviceIdentifier, named);
     }
+
+    /**
+     * @param options
+     */
+    public load (options: TInputOptions): void {
+        this.container
+            .bind<IOptions>(ServiceIdentifiers.IOptions)
+            .toDynamicValue(() => new Options(options))
+            .inSingletonScope();
+
+        this.container
+            .bind<IJavaScriptObfuscator>(ServiceIdentifiers.IJavaScriptObfuscator)
+            .to(JavaScriptObfuscatorInternal)
+            .inSingletonScope();
+
+        this.container
+            .bind<IObfuscator>(ServiceIdentifiers.IObfuscator)
+            .to(Obfuscator)
+            .inSingletonScope();
+
+        this.container
+            .bind<IObfuscationResult>(ServiceIdentifiers.IObfuscationResult)
+            .to(ObfuscationResult)
+            .inSingletonScope();
+
+        this.container
+            .bind<IObfuscationResult>(ServiceIdentifiers.Factory__IObfuscationResult)
+            .toFactory<IObfuscationResult>((context: interfaces.Context) => {
+                return (obfuscatedCode: string, sourceMap: string) => {
+                    const obfuscationResult: IObfuscationResult = context.container
+                        .get<IObfuscationResult>(ServiceIdentifiers.IObfuscationResult);
+
+                    obfuscationResult.initialize(obfuscatedCode, sourceMap);
+
+                    return obfuscationResult;
+                };
+            });
+
+        this.container
+            .bind<ISourceMapCorrector>(ServiceIdentifiers.ISourceMapCorrector)
+            .to(SourceMapCorrector)
+            .inSingletonScope();
+
+        this.container
+            .bind<IObfuscationEventEmitter>(ServiceIdentifiers.IObfuscationEventEmitter)
+            .to(ObfuscationEventEmitter)
+            .inSingletonScope();
+
+        // modules
+        this.container.load(utilsModule);
+        this.container.load(storagesModule);
+        this.container.load(stackTraceAnalyzerModule);
+        this.container.load(customNodesModule);
+        this.container.load(nodeTransformersModule);
+        this.container.load(controlFlowTransformersModule);
+        this.container.load(obfuscatingTransformersModule);
+    }
+
+    public unload (): void {
+        this.container.unbindAll();
+    }
 }

+ 35 - 29
src/container/ServiceIdentifiers.ts

@@ -1,29 +1,35 @@
-export const ServiceIdentifiers: any = {
-    Factory__ICalleeDataExtractor: Symbol('Factory<ICalleeDataExtractor>'),
-    Factory__IControlFlowReplacer: Symbol('Factory<IControlFlowReplacer>'),
-    Factory__ICustomNode: Symbol('Factory<ICustomNode>'),
-    Factory__ICustomNodeGroup: Symbol('Factory<ICustomNodeGroup>'),
-    Factory__IIdentifierObfuscatingReplacer: Symbol('Factory<IIdentifierObfuscatingReplacer>'),
-    Factory__INodeTransformer: Symbol('Factory<INodeTransformer[]>'),
-    Factory__IObfuscationResult: Symbol('Factory<IObfuscationResult>'),
-    Factory__IObfuscatingReplacer: Symbol('Factory<IObfuscatingReplacer>'),
-    Factory__TControlFlowStorage: Symbol('Factory<TControlFlowStorage>'),
-    ICalleeDataExtractor: Symbol('ICalleeDataExtractor'),
-    ICustomNodeGroup: Symbol('ICustomNodeGroup'),
-    IControlFlowReplacer: Symbol('IControlFlowReplacer'),
-    IDeadCodeInjectionReplacer: Symbol('IDeadCodeInjectionReplacer'),
-    IIdentifierObfuscatingReplacer: Symbol('IIdentifierObfuscatingReplacer'),
-    IJavaScriptObfuscator: Symbol('IJavaScriptObfuscator'),
-    INodeTransformer: Symbol('INodeTransformer'),
-    IObfuscationEventEmitter: Symbol('IObfuscationEventEmitter'),
-    IObfuscationResult: Symbol('IObfuscationResult'),
-    IObfuscator: Symbol('IObfuscator'),
-    IOptions: Symbol('IOptions'),
-    IObfuscatingReplacer: Symbol('IObfuscatingReplacer'),
-    ISourceMapCorrector: Symbol('ISourceMapCorrector'),
-    IStackTraceAnalyzer: Symbol('IStackTraceAnalyzer'),
-    Newable__ICustomNode: Symbol('Newable<ICustomNode>'),
-    Newable__TControlFlowStorage: Symbol('Newable<TControlFlowStorage>'),
-    TCustomNodeGroupStorage: Symbol('TCustomNodeGroupStorage'),
-    TStringArrayStorage: Symbol('TStringArrayStorage')
-};
+export enum ServiceIdentifiers {
+    Factory__ICalleeDataExtractor = 'Factory<ICalleeDataExtractor>',
+    Factory__IControlFlowCustomNode = 'Factory<IControlFlowCustomNode>',
+    Factory__IControlFlowReplacer = 'Factory<IControlFlowReplacer>',
+    Factory__ICustomNode = 'Factory<ICustomNode>',
+    Factory__ICustomNodeGroup = 'Factory<ICustomNodeGroup>',
+    Factory__IIdentifierObfuscatingReplacer = 'Factory<IIdentifierObfuscatingReplacer>',
+    Factory__INodeTransformer = 'Factory<INodeTransformer[]>',
+    Factory__IObfuscationResult = 'Factory<IObfuscationResult>',
+    Factory__IObfuscatingReplacer = 'Factory<IObfuscatingReplacer>',
+    Factory__TControlFlowStorage = 'Factory<TControlFlowStorage>',
+    IArrayUtils = 'IArrayUtils',
+    ICalleeDataExtractor = 'ICalleeDataExtractor',
+    ICryptUtils = 'ICryptUtils',
+    ICustomNode = 'ICustomNode',
+    ICustomNodeGroup = 'ICustomNodeGroup',
+    IControlFlowReplacer = 'IControlFlowReplacer',
+    IDeadCodeInjectionReplacer = 'IDeadCodeInjectionReplacer',
+    IEscapeSequenceEncoder = 'IEscapeSequenceEncoder',
+    IIdentifierObfuscatingReplacer = 'IIdentifierObfuscatingReplacer',
+    IJavaScriptObfuscator = 'IJavaScriptObfuscator',
+    INodeTransformer = 'INodeTransformer',
+    IObfuscationEventEmitter = 'IObfuscationEventEmitter',
+    IObfuscationResult = 'IObfuscationResult',
+    IObfuscator = 'IObfuscator',
+    IOptions = 'IOptions',
+    IObfuscatingReplacer = 'IObfuscatingReplacer',
+    IRandomGenerator = 'IRandomGenerator',
+    ISourceMapCorrector = 'ISourceMapCorrector',
+    IStackTraceAnalyzer = 'IStackTraceAnalyzer',
+    Newable__ICustomNode = 'Newable<ICustomNode>',
+    Newable__TControlFlowStorage = 'Newable<TControlFlowStorage>',
+    TCustomNodeGroupStorage = 'TCustomNodeGroupStorage',
+    TStringArrayStorage = 'TStringArrayStorage'
+}

+ 61 - 74
src/container/modules/custom-nodes/CustomNodesModule.ts

@@ -4,8 +4,8 @@ import { ServiceIdentifiers } from '../../ServiceIdentifiers';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { ICustomNodeGroup } from '../../../interfaces/custom-nodes/ICustomNodeGroup';
-import { IOptions } from '../../../interfaces/options/IOptions';
 
+import { ControlFlowCustomNode } from "../../../enums/container/custom-nodes/ControlFlowCustomNode";
 import { CustomNode } from '../../../enums/container/custom-nodes/CustomNode';
 import { CustomNodeGroup } from '../../../enums/container/custom-nodes/CustomNodeGroup';
 
@@ -37,81 +37,82 @@ import { StringLiteralNode } from '../../../custom-nodes/control-flow-flattening
 
 export const customNodesModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
     // custom nodes
-    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(BinaryExpressionFunctionNode)
-        .whenTargetNamed(CustomNode.BinaryExpressionFunctionNode);
-
-    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(BlockStatementControlFlowFlatteningNode)
-        .whenTargetNamed(CustomNode.BlockStatementControlFlowFlatteningNode);
-
-    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(CallExpressionControlFlowStorageCallNode)
-        .whenTargetNamed(CustomNode.CallExpressionControlFlowStorageCallNode);
-
-    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(CallExpressionFunctionNode)
-        .whenTargetNamed(CustomNode.CallExpressionFunctionNode);
-
-    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(ControlFlowStorageNode)
-        .whenTargetNamed(CustomNode.ControlFlowStorageNode);
-
-    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(ConsoleOutputDisableExpressionNode)
+    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
+        .to(ConsoleOutputDisableExpressionNode)
         .whenTargetNamed(CustomNode.ConsoleOutputDisableExpressionNode);
 
-    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(DebugProtectionFunctionCallNode)
+    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
+        .to(DebugProtectionFunctionCallNode)
         .whenTargetNamed(CustomNode.DebugProtectionFunctionCallNode);
 
-    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(DebugProtectionFunctionIntervalNode)
+    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
+        .to(DebugProtectionFunctionIntervalNode)
         .whenTargetNamed(CustomNode.DebugProtectionFunctionIntervalNode);
 
-    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(DebugProtectionFunctionNode)
+    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
+        .to(DebugProtectionFunctionNode)
         .whenTargetNamed(CustomNode.DebugProtectionFunctionNode);
 
-    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(DomainLockNode)
+    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
+        .to(DomainLockNode)
         .whenTargetNamed(CustomNode.DomainLockNode);
 
-    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(ExpressionWithOperatorControlFlowStorageCallNode)
-        .whenTargetNamed(CustomNode.ExpressionWithOperatorControlFlowStorageCallNode);
+    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
+        .to(NodeCallsControllerFunctionNode)
+        .whenTargetNamed(CustomNode.NodeCallsControllerFunctionNode);
+
+    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
+        .to(SelfDefendingUnicodeNode)
+        .whenTargetNamed(CustomNode.SelfDefendingUnicodeNode);
+
+    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
+        .to(StringArrayCallsWrapper)
+        .whenTargetNamed(CustomNode.StringArrayCallsWrapper);
 
+    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
+        .to(StringArrayNode)
+        .whenTargetNamed(CustomNode.StringArrayNode);
+
+    bind<ICustomNode>(ServiceIdentifiers.ICustomNode)
+        .to(StringArrayRotateFunctionNode)
+        .whenTargetNamed(CustomNode.StringArrayRotateFunctionNode);
+
+    // control flow custom nodes
     bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(LogicalExpressionFunctionNode)
-        .whenTargetNamed(CustomNode.LogicalExpressionFunctionNode);
+        .toConstructor(BinaryExpressionFunctionNode)
+        .whenTargetNamed(ControlFlowCustomNode.BinaryExpressionFunctionNode);
 
     bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(NodeCallsControllerFunctionNode)
-        .whenTargetNamed(CustomNode.NodeCallsControllerFunctionNode);
+        .toConstructor(BlockStatementControlFlowFlatteningNode)
+        .whenTargetNamed(ControlFlowCustomNode.BlockStatementControlFlowFlatteningNode);
 
     bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(SelfDefendingUnicodeNode)
-        .whenTargetNamed(CustomNode.SelfDefendingUnicodeNode);
+        .toConstructor(CallExpressionControlFlowStorageCallNode)
+        .whenTargetNamed(ControlFlowCustomNode.CallExpressionControlFlowStorageCallNode);
 
     bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(StringArrayCallsWrapper)
-        .whenTargetNamed(CustomNode.StringArrayCallsWrapper);
+        .toConstructor(CallExpressionFunctionNode)
+        .whenTargetNamed(ControlFlowCustomNode.CallExpressionFunctionNode);
 
     bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(StringArrayNode)
-        .whenTargetNamed(CustomNode.StringArrayNode);
+        .toConstructor(ControlFlowStorageNode)
+        .whenTargetNamed(ControlFlowCustomNode.ControlFlowStorageNode);
 
     bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(StringArrayRotateFunctionNode)
-        .whenTargetNamed(CustomNode.StringArrayRotateFunctionNode);
+        .toConstructor(ExpressionWithOperatorControlFlowStorageCallNode)
+        .whenTargetNamed(ControlFlowCustomNode.ExpressionWithOperatorControlFlowStorageCallNode);
 
     bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(StringLiteralControlFlowStorageCallNode)
-        .whenTargetNamed(CustomNode.StringLiteralControlFlowStorageCallNode);
+        .toConstructor(LogicalExpressionFunctionNode)
+        .whenTargetNamed(ControlFlowCustomNode.LogicalExpressionFunctionNode);
 
     bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
         .toConstructor(StringLiteralNode)
-        .whenTargetNamed(CustomNode.StringLiteralNode);
+        .whenTargetNamed(ControlFlowCustomNode.StringLiteralNode);
+
+    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
+        .toConstructor(StringLiteralControlFlowStorageCallNode)
+        .whenTargetNamed(ControlFlowCustomNode.StringLiteralControlFlowStorageCallNode);
 
     // node groups
     bind<ICustomNodeGroup>(ServiceIdentifiers.ICustomNodeGroup)
@@ -136,31 +137,17 @@ export const customNodesModule: interfaces.ContainerModule = new ContainerModule
 
     // customNode factory
     bind<ICustomNode>(ServiceIdentifiers.Factory__ICustomNode)
-        .toFactory<ICustomNode>((context: interfaces.Context) => {
-            const cache: Map <CustomNode, interfaces.Newable<ICustomNode>> = new Map();
-
-            let cachedOptions: IOptions;
-
-            return (customNodeName: CustomNode) => {
-                if (!cachedOptions) {
-                    cachedOptions = context.container.get<IOptions>(ServiceIdentifiers.IOptions);
-                }
-
-                if (cache.has(customNodeName)) {
-                    return new (<interfaces.Newable<ICustomNode>>cache.get(customNodeName));
-                }
-
-                const constructor: interfaces.Newable<ICustomNode> = context.container
-                    .getNamed<interfaces.Newable<ICustomNode>>(
-                        ServiceIdentifiers.Newable__ICustomNode,
-                        customNodeName
-                    );
-
-                cache.set(customNodeName, constructor);
-
-                return new constructor(cachedOptions);
-            };
-        });
+        .toFactory<ICustomNode>(InversifyContainerFacade
+            .getFactory<CustomNode, ICustomNode>(ServiceIdentifiers.ICustomNode));
+
+    // control flow storage customNode constructor factory
+    bind<ICustomNode>(ServiceIdentifiers.Factory__IControlFlowCustomNode)
+        .toFactory<ICustomNode>(InversifyContainerFacade
+            .getConstructorFactory<ControlFlowCustomNode, ICustomNode>(
+                ServiceIdentifiers.Newable__ICustomNode,
+                ServiceIdentifiers.IRandomGenerator,
+                ServiceIdentifiers.IOptions
+            ));
 
     // customNodeGroup factory
     bind<ICustomNodeGroup>(ServiceIdentifiers.Factory__ICustomNodeGroup)

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

@@ -5,6 +5,8 @@ import { TControlFlowStorage } from '../../../types/storages/TControlFlowStorage
 import { TCustomNodeGroupStorage } from '../../../types/storages/TCustomNodeGroupStorage';
 import { TStringArrayStorage } from '../../../types/storages/TStringArrayStorage';
 
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
+
 import { ControlFlowStorage } from '../../../storages/control-flow/ControlFlowStorage';
 import { CustomNodeGroupStorage } from '../../../storages/custom-node-group/CustomNodeGroupStorage';
 import { StringArrayStorage } from '../../../storages/string-array/StringArrayStorage';
@@ -28,8 +30,10 @@ export const storagesModule: interfaces.ContainerModule = new ContainerModule((b
             return () => {
                 const constructor: interfaces.Newable<TControlFlowStorage> = context.container
                     .get<interfaces.Newable<TControlFlowStorage>>(ServiceIdentifiers.Newable__TControlFlowStorage);
+                const randomGenerator: IRandomGenerator = context.container
+                    .get<IRandomGenerator>(ServiceIdentifiers.IRandomGenerator);
 
-                return new constructor();
+                return new constructor(randomGenerator);
             };
         });
 });

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

@@ -0,0 +1,34 @@
+import { ContainerModule, interfaces } from 'inversify';
+import { ServiceIdentifiers } from '../../ServiceIdentifiers';
+
+import { IArrayUtils } from '../../../interfaces/utils/IArrayUtils';
+import { ICryptUtils } from '../../../interfaces/utils/ICryptUtils';
+import { IEscapeSequenceEncoder } from '../../../interfaces/utils/IEscapeSequenceEncoder';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
+
+import { ArrayUtils } from '../../../utils/ArrayUtils';
+import { CryptUtils } from '../../../utils/CryptUtils';
+import { EscapeSequenceEncoder } from '../../../utils/EscapeSequenceEncoder';
+import { RandomGenerator } from '../../../utils/RandomGenerator';
+
+export const utilsModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
+    // array utils
+    bind<IArrayUtils>(ServiceIdentifiers.IArrayUtils)
+        .to(ArrayUtils)
+        .inSingletonScope();
+
+    // random generator
+    bind<IRandomGenerator>(ServiceIdentifiers.IRandomGenerator)
+        .to(RandomGenerator)
+        .inSingletonScope();
+
+    // crypt utils
+    bind<ICryptUtils>(ServiceIdentifiers.ICryptUtils)
+        .to(CryptUtils)
+        .inSingletonScope();
+
+    // escape sequence encoder
+    bind<IEscapeSequenceEncoder>(ServiceIdentifiers.IEscapeSequenceEncoder)
+        .to(EscapeSequenceEncoder)
+        .inSingletonScope();
+});

+ 16 - 0
src/custom-nodes/AbstractCustomNodeGroup.ts

@@ -6,6 +6,7 @@ import { TNodeWithBlockStatement } from '../types/node/TNodeWithBlockStatement';
 import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
 import { ICustomNodeGroup } from '../interfaces/custom-nodes/ICustomNodeGroup';
 import { IOptions } from '../interfaces/options/IOptions';
+import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
 import { IStackTraceData } from '../interfaces/stack-trace-analyzer/IStackTraceData';
 
 import { CustomNode } from '../enums/container/custom-nodes/CustomNode';
@@ -34,11 +35,19 @@ export abstract class AbstractCustomNodeGroup implements ICustomNodeGroup {
     protected readonly options: IOptions;
 
     /**
+     * @type {IRandomGenerator}
+     */
+    protected readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
+        this.randomGenerator = randomGenerator;
         this.options = options;
     }
 
@@ -77,4 +86,11 @@ export abstract class AbstractCustomNodeGroup implements ICustomNodeGroup {
 
         callback(customNode);
     }
+
+    /**
+     * @param stackTraceLength
+     */
+    protected getRandomStackTraceIndex (stackTraceLength: number): number {
+        return this.randomGenerator.getRandomInteger(0, Math.max(0, Math.round(stackTraceLength - 1)));
+    }
 }

+ 11 - 2
src/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.ts

@@ -6,6 +6,7 @@ import * as format from 'string-template';
 import { TStatement } from '../../types/node/TStatement';
 
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
 import { ConsoleOutputDisableExpressionTemplate } from '../../templates/custom-nodes/console-output-nodes/console-output-disable-expression-node/ConsoleOutputDisableExpressionTemplate';
 
@@ -13,7 +14,6 @@ import { initializable } from '../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { NodeUtils } from '../../node/NodeUtils';
-import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
 
 @injectable()
 export class ConsoleOutputDisableExpressionNode extends AbstractCustomNode {
@@ -24,12 +24,21 @@ export class ConsoleOutputDisableExpressionNode extends AbstractCustomNode {
     private callsControllerFunctionName: string;
 
     /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);
+
+        this.randomGenerator = randomGenerator;
     }
 
     /**
@@ -51,7 +60,7 @@ export class ConsoleOutputDisableExpressionNode extends AbstractCustomNode {
      */
     protected getTemplate (): string {
         return format(ConsoleOutputDisableExpressionTemplate(), {
-            consoleLogDisableFunctionName: RandomGeneratorUtils.getRandomVariableName(6),
+            consoleLogDisableFunctionName: this.randomGenerator.getRandomVariableName(6),
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName
         });
     }

+ 6 - 4
src/custom-nodes/console-output-nodes/group/ConsoleOutputCustomNodeGroup.ts

@@ -7,6 +7,7 @@ import { TNodeWithBlockStatement } from '../../../types/node/TNodeWithBlockState
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IObfuscationEventEmitter } from '../../../interfaces/event-emitters/IObfuscationEventEmitter';
 import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IStackTraceData } from '../../../interfaces/stack-trace-analyzer/IStackTraceData';
 
 import { initializable } from '../../../decorators/Initializable';
@@ -16,7 +17,6 @@ import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent
 
 import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
 import { NodeAppender } from '../../../node/NodeAppender';
-import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
 
 @injectable()
 export class ConsoleOutputCustomNodeGroup extends AbstractCustomNodeGroup {
@@ -44,14 +44,16 @@ export class ConsoleOutputCustomNodeGroup extends AbstractCustomNodeGroup {
     /**
      * @param customNodeFactory
      * @param obfuscationEventEmitter
+     * @param randomGenerator
      * @param options
      */
     constructor (
         @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
         @inject(ServiceIdentifiers.IObfuscationEventEmitter) obfuscationEventEmitter: IObfuscationEventEmitter,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
 
         this.customNodeFactory = customNodeFactory;
         this.obfuscationEventEmitter = obfuscationEventEmitter;
@@ -62,7 +64,7 @@ export class ConsoleOutputCustomNodeGroup extends AbstractCustomNodeGroup {
      * @param stackTraceData
      */
     public appendCustomNodes (blockScopeNode: TNodeWithBlockStatement, stackTraceData: IStackTraceData[]): void {
-        const randomStackTraceIndex: number = NodeAppender.getRandomStackTraceIndex(stackTraceData.length);
+        const randomStackTraceIndex: number = this.getRandomStackTraceIndex(stackTraceData.length);
 
         // consoleOutputDisableExpressionNode append
         this.appendCustomNodeIfExist(CustomNode.ConsoleOutputDisableExpressionNode, (customNode: ICustomNode) => {
@@ -95,7 +97,7 @@ export class ConsoleOutputCustomNodeGroup extends AbstractCustomNodeGroup {
             return;
         }
 
-        const callsControllerFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6);
+        const callsControllerFunctionName: string = this.randomGenerator.getRandomVariableName(6);
 
         const consoleOutputDisableExpressionNode: ICustomNode = this.customNodeFactory(CustomNode.ConsoleOutputDisableExpressionNode);
         const nodeCallsControllerFunctionNode: ICustomNode = this.customNodeFactory(CustomNode.NodeCallsControllerFunctionNode);

+ 11 - 2
src/custom-nodes/control-flow-flattening-nodes/BinaryExpressionFunctionNode.ts

@@ -6,13 +6,13 @@ import { BinaryOperator } from 'estree';
 import { TStatement } from '../../types/node/TStatement';
 
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
 import { initializable } from '../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { Nodes } from '../../node/Nodes';
 import { NodeUtils } from '../../node/NodeUtils';
-import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
 
 @injectable()
 export class BinaryExpressionFunctionNode extends AbstractCustomNode {
@@ -23,12 +23,21 @@ export class BinaryExpressionFunctionNode extends AbstractCustomNode {
     private operator: BinaryOperator;
 
     /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);
+
+        this.randomGenerator = randomGenerator;
     }
 
     /**
@@ -43,7 +52,7 @@ export class BinaryExpressionFunctionNode extends AbstractCustomNode {
      */
     protected getNodeStructure (): TStatement[] {
         const structure: TStatement = Nodes.getFunctionDeclarationNode(
-            RandomGeneratorUtils.getRandomString(3),
+            this.randomGenerator.getRandomString(3),
             [
                 Nodes.getIdentifierNode('x'),
                 Nodes.getIdentifierNode('y')

+ 12 - 3
src/custom-nodes/control-flow-flattening-nodes/BlockStatementControlFlowFlatteningNode.ts

@@ -6,13 +6,13 @@ import * as ESTree from 'estree';
 import { TStatement } from '../../types/node/TStatement';
 
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
 import { initializable } from '../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { Nodes } from '../../node/Nodes';
 import { NodeUtils } from '../../node/NodeUtils';
-import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
 
 @injectable()
 export class BlockStatementControlFlowFlatteningNode extends AbstractCustomNode {
@@ -28,6 +28,11 @@ export class BlockStatementControlFlowFlatteningNode extends AbstractCustomNode
     @initializable()
     private originalKeysIndexesInShuffledArray: number[];
 
+    /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
     /**
      * @type {number[]}
      */
@@ -35,12 +40,16 @@ export class BlockStatementControlFlowFlatteningNode extends AbstractCustomNode
     private shuffledKeys: number[];
 
     /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);
+
+        this.randomGenerator = randomGenerator;
     }
 
     /***
@@ -62,8 +71,8 @@ export class BlockStatementControlFlowFlatteningNode extends AbstractCustomNode
      * @returns {TStatement[]}
      */
     protected getNodeStructure (): TStatement[] {
-        const controllerIdentifierName: string = RandomGeneratorUtils.getRandomString(3);
-        const indexIdentifierName: string = RandomGeneratorUtils.getRandomString(3);
+        const controllerIdentifierName: string = this.randomGenerator.getRandomString(3);
+        const indexIdentifierName: string = this.randomGenerator.getRandomString(3);
         const structure: ESTree.BlockStatement = Nodes.getBlockStatementNode([
             Nodes.getVariableDeclarationNode([
                 Nodes.getVariableDeclaratorNode(

+ 11 - 2
src/custom-nodes/control-flow-flattening-nodes/CallExpressionFunctionNode.ts

@@ -6,13 +6,13 @@ import * as ESTree from 'estree';
 import { TStatement } from '../../types/node/TStatement';
 
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
 import { initializable } from '../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { Nodes } from '../../node/Nodes';
 import { NodeUtils } from '../../node/NodeUtils';
-import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
 
 @injectable()
 export class CallExpressionFunctionNode extends AbstractCustomNode {
@@ -23,12 +23,21 @@ export class CallExpressionFunctionNode extends AbstractCustomNode {
     private expressionArguments: (ESTree.Expression | ESTree.SpreadElement)[];
 
     /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);
+
+        this.randomGenerator = randomGenerator;
     }
 
     /**
@@ -51,7 +60,7 @@ export class CallExpressionFunctionNode extends AbstractCustomNode {
         }
 
         const structure: TStatement = Nodes.getFunctionDeclarationNode(
-            RandomGeneratorUtils.getRandomString(3),
+            this.randomGenerator.getRandomString(3),
             [
                 calleeIdentifier,
                 ...params

+ 11 - 2
src/custom-nodes/control-flow-flattening-nodes/LogicalExpressionFunctionNode.ts

@@ -6,12 +6,12 @@ import { LogicalOperator } from 'estree';
 import { TStatement } from '../../types/node/TStatement';
 
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
 import { initializable } from '../../decorators/Initializable';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { Nodes } from '../../node/Nodes';
-import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
@@ -23,12 +23,21 @@ export class LogicalExpressionFunctionNode extends AbstractCustomNode {
     private operator: LogicalOperator;
 
     /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);
+
+        this.randomGenerator = randomGenerator;
     }
 
     /**
@@ -43,7 +52,7 @@ export class LogicalExpressionFunctionNode extends AbstractCustomNode {
      */
     protected getNodeStructure (): TStatement[] {
         const structure: TStatement = Nodes.getFunctionDeclarationNode(
-            RandomGeneratorUtils.getRandomString(3),
+            this.randomGenerator.getRandomString(3),
             [
                 Nodes.getIdentifierNode('x'),
                 Nodes.getIdentifierNode('y')

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

@@ -4,6 +4,7 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import { TStatement } from '../../types/node/TStatement';
 
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
 import { initializable } from '../../decorators/Initializable';
 
@@ -19,12 +20,21 @@ export class StringLiteralNode extends AbstractCustomNode {
     private literalValue: string;
 
     /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);
+
+        this.randomGenerator = randomGenerator;
     }
 
     /**

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

@@ -7,6 +7,7 @@ import { Expression } from 'estree';
 import { TStatement } from '../../../types/node/TStatement';
 
 import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from "../../../interfaces/utils/IRandomGenerator";
 
 import { initializable } from '../../../decorators/Initializable';
 
@@ -41,12 +42,21 @@ export class CallExpressionControlFlowStorageCallNode extends AbstractCustomNode
     private expressionArguments: (ESTree.Expression | ESTree.SpreadElement)[];
 
     /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);
+
+        this.randomGenerator = randomGenerator;
     }
 
     /**

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

@@ -7,6 +7,7 @@ import { TStatement } from '../../../types/node/TStatement';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IStorage } from '../../../interfaces/storages/IStorage';
 
 import { initializable } from '../../../decorators/Initializable';
@@ -24,12 +25,21 @@ export class ControlFlowStorageNode extends AbstractCustomNode {
     private controlFlowStorage: IStorage <ICustomNode>;
 
     /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);
+
+        this.randomGenerator = randomGenerator;
     }
 
     /**

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

@@ -6,6 +6,7 @@ import { Expression } from 'estree';
 import { TStatement } from '../../../types/node/TStatement';
 
 import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 
 import { initializable } from '../../../decorators/Initializable';
 
@@ -33,6 +34,11 @@ export class ExpressionWithOperatorControlFlowStorageCallNode extends AbstractCu
     @initializable()
     private leftValue: Expression;
 
+    /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
     /**
      * @type {ESTree.Expression}
      */
@@ -40,12 +46,16 @@ export class ExpressionWithOperatorControlFlowStorageCallNode extends AbstractCu
     private rightValue: Expression;
 
     /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);
+
+        this.randomGenerator = randomGenerator;
     }
 
     /**

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

@@ -4,6 +4,7 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 import { TStatement } from '../../../types/node/TStatement';
 
 import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 
 import { initializable } from '../../../decorators/Initializable';
 
@@ -26,12 +27,21 @@ export class StringLiteralControlFlowStorageCallNode extends AbstractCustomNode
     private controlFlowStorageName: string;
 
     /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);
+
+        this.randomGenerator = randomGenerator;
     }
 
     /**

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

@@ -7,6 +7,7 @@ import { TNodeWithBlockStatement } from '../../../types/node/TNodeWithBlockState
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IObfuscationEventEmitter } from '../../../interfaces/event-emitters/IObfuscationEventEmitter';
 import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IStackTraceData } from '../../../interfaces/stack-trace-analyzer/IStackTraceData';
 
 import { initializable } from '../../../decorators/Initializable';
@@ -16,7 +17,6 @@ import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent
 
 import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
 import { NodeAppender } from '../../../node/NodeAppender';
-import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
 
 @injectable()
 export class DebugProtectionCustomNodeGroup extends AbstractCustomNodeGroup {
@@ -44,14 +44,16 @@ export class DebugProtectionCustomNodeGroup extends AbstractCustomNodeGroup {
     /**
      * @param customNodeFactory
      * @param obfuscationEventEmitter
+     * @param randomGenerator
      * @param options
      */
     constructor (
         @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
         @inject(ServiceIdentifiers.IObfuscationEventEmitter) obfuscationEventEmitter: IObfuscationEventEmitter,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
 
         this.customNodeFactory = customNodeFactory;
         this.obfuscationEventEmitter = obfuscationEventEmitter;
@@ -75,7 +77,7 @@ export class DebugProtectionCustomNodeGroup extends AbstractCustomNodeGroup {
         // debugProtectionFunctionIntervalNode append
         this.appendCustomNodeIfExist(CustomNode.DebugProtectionFunctionIntervalNode, (customNode: ICustomNode) => {
             const programBodyLength: number = blockScopeNode.body.length;
-            const randomIndex: number = RandomGeneratorUtils.getRandomInteger(0, programBodyLength);
+            const randomIndex: number = this.randomGenerator.getRandomInteger(0, programBodyLength);
 
             NodeAppender.insertNodeAtIndex(blockScopeNode, customNode.getNode(), randomIndex);
         });
@@ -88,7 +90,7 @@ export class DebugProtectionCustomNodeGroup extends AbstractCustomNodeGroup {
             return;
         }
 
-        const debugProtectionFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6);
+        const debugProtectionFunctionName: string = this.randomGenerator.getRandomVariableName(6);
 
         const debugProtectionFunctionNode: ICustomNode = this.customNodeFactory(CustomNode.DebugProtectionFunctionNode);
         const debugProtectionFunctionCallNode: ICustomNode = this.customNodeFactory(CustomNode.DebugProtectionFunctionCallNode);

+ 24 - 4
src/custom-nodes/domain-lock-nodes/DomainLockNode.ts

@@ -5,16 +5,16 @@ import * as format from 'string-template';
 
 import { TStatement } from '../../types/node/TStatement';
 
+import { ICryptUtils } from '../../interfaces/utils/ICryptUtils';
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
 import { initializable } from '../../decorators/Initializable';
 
 import { DomainLockNodeTemplate } from '../../templates/custom-nodes/domain-lock-nodes/domain-lock-node/DomainLockNodeTemplate';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
-import { CryptUtils } from '../../utils/CryptUtils';
 import { NodeUtils } from '../../node/NodeUtils';
-import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
 
 @injectable()
 export class DomainLockNode extends AbstractCustomNode {
@@ -25,12 +25,29 @@ export class DomainLockNode extends AbstractCustomNode {
     protected callsControllerFunctionName: string;
 
     /**
+     * @type {ICryptUtils}
+     */
+    private readonly cryptUtils: ICryptUtils;
+
+    /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param randomGenerator
+     * @param cryptUtils
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.ICryptUtils) cryptUtils: ICryptUtils,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);
+
+        this.randomGenerator = randomGenerator;
+        this.cryptUtils = cryptUtils;
     }
 
     /**
@@ -52,10 +69,13 @@ export class DomainLockNode extends AbstractCustomNode {
      */
     protected getTemplate (): string {
         const domainsString: string = this.options.domainLock.join(';');
-        const [hiddenDomainsString, diff]: string[] = CryptUtils.hideString(domainsString, domainsString.length * 3);
+        const [hiddenDomainsString, diff]: string[] = this.cryptUtils.hideString(
+            domainsString,
+            domainsString.length * 3
+        );
 
         return format(DomainLockNodeTemplate(), {
-            domainLockFunctionName: RandomGeneratorUtils.getRandomVariableName(6),
+            domainLockFunctionName: this.randomGenerator.getRandomVariableName(6),
             diff: diff,
             domains: hiddenDomainsString,
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName

+ 6 - 4
src/custom-nodes/domain-lock-nodes/group/DomainLockCustomNodeGroup.ts

@@ -7,6 +7,7 @@ import { TNodeWithBlockStatement } from '../../../types/node/TNodeWithBlockState
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IObfuscationEventEmitter } from '../../../interfaces/event-emitters/IObfuscationEventEmitter';
 import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IStackTraceData } from '../../../interfaces/stack-trace-analyzer/IStackTraceData';
 
 import { initializable } from '../../../decorators/Initializable';
@@ -16,7 +17,6 @@ import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent
 
 import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
 import { NodeAppender } from '../../../node/NodeAppender';
-import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
 
 @injectable()
 export class DomainLockCustomNodeGroup extends AbstractCustomNodeGroup {
@@ -44,14 +44,16 @@ export class DomainLockCustomNodeGroup extends AbstractCustomNodeGroup {
     /**
      * @param customNodeFactory
      * @param obfuscationEventEmitter
+     * @param randomGenerator
      * @param options
      */
     constructor (
         @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
         @inject(ServiceIdentifiers.IObfuscationEventEmitter) obfuscationEventEmitter: IObfuscationEventEmitter,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
 
         this.customNodeFactory = customNodeFactory;
         this.obfuscationEventEmitter = obfuscationEventEmitter;
@@ -62,7 +64,7 @@ export class DomainLockCustomNodeGroup extends AbstractCustomNodeGroup {
      * @param stackTraceData
      */
     public appendCustomNodes (blockScopeNode: TNodeWithBlockStatement, stackTraceData: IStackTraceData[]): void {
-        const randomStackTraceIndex: number = NodeAppender.getRandomStackTraceIndex(stackTraceData.length);
+        const randomStackTraceIndex: number = this.getRandomStackTraceIndex(stackTraceData.length);
 
         // domainLockNode append
         this.appendCustomNodeIfExist(CustomNode.DomainLockNode, (customNode: ICustomNode) => {
@@ -95,7 +97,7 @@ export class DomainLockCustomNodeGroup extends AbstractCustomNodeGroup {
             return;
         }
 
-        const callsControllerFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6);
+        const callsControllerFunctionName: string = this.randomGenerator.getRandomVariableName(6);
 
         const domainLockNode: ICustomNode = this.customNodeFactory(CustomNode.DomainLockNode);
         const nodeCallsControllerFunctionNode: ICustomNode = this.customNodeFactory(CustomNode.NodeCallsControllerFunctionNode);

+ 22 - 4
src/custom-nodes/self-defending-nodes/SelfDefendingUnicodeNode.ts

@@ -5,7 +5,9 @@ import * as format from 'string-template';
 
 import { TStatement } from '../../types/node/TStatement';
 
+import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
 import { initializable } from '../../decorators/Initializable';
 
@@ -16,23 +18,39 @@ import { SelfDefendingTemplate } from '../../templates/custom-nodes/self-defendi
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { JavaScriptObfuscator } from '../../JavaScriptObfuscator';
 import { NodeUtils } from '../../node/NodeUtils';
-import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
 
 @injectable()
 export class SelfDefendingUnicodeNode extends AbstractCustomNode {
+    /**
+     * @type {IEscapeSequenceEncoder}
+     */
+    private readonly escapeSequenceEncoder: IEscapeSequenceEncoder;
+
     /**
      * @type {string}
      */
     @initializable()
-    protected callsControllerFunctionName: string;
+    private callsControllerFunctionName: string;
 
     /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param randomGenerator
+     * @param escapeSequenceEncoder
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);
+
+        this.randomGenerator = randomGenerator;
+        this.escapeSequenceEncoder = escapeSequenceEncoder;
     }
 
     /**
@@ -54,8 +72,8 @@ export class SelfDefendingUnicodeNode extends AbstractCustomNode {
      */
     protected getTemplate (): string {
         return JavaScriptObfuscator.obfuscate(
-            format(SelfDefendingTemplate(), {
-                selfDefendingFunctionName: RandomGeneratorUtils.getRandomVariableName(6),
+            format(SelfDefendingTemplate(this.escapeSequenceEncoder), {
+                selfDefendingFunctionName: this.randomGenerator.getRandomVariableName(6),
                 singleNodeCallControllerFunctionName: this.callsControllerFunctionName
             }),
             {

+ 6 - 4
src/custom-nodes/self-defending-nodes/group/SelfDefendingCustomNodeGroup.ts

@@ -7,6 +7,7 @@ import { TNodeWithBlockStatement } from '../../../types/node/TNodeWithBlockState
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IObfuscationEventEmitter } from '../../../interfaces/event-emitters/IObfuscationEventEmitter';
 import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IStackTraceData } from '../../../interfaces/stack-trace-analyzer/IStackTraceData';
 
 import { initializable } from '../../../decorators/Initializable';
@@ -16,7 +17,6 @@ import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent
 
 import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
 import { NodeAppender } from '../../../node/NodeAppender';
-import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
 
 @injectable()
 export class SelfDefendingCustomNodeGroup extends AbstractCustomNodeGroup {
@@ -44,14 +44,16 @@ export class SelfDefendingCustomNodeGroup extends AbstractCustomNodeGroup {
     /**
      * @param customNodeFactory
      * @param obfuscationEventEmitter
+     * @param randomGenerator
      * @param options
      */
     constructor (
         @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
         @inject(ServiceIdentifiers.IObfuscationEventEmitter) obfuscationEventEmitter: IObfuscationEventEmitter,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
 
         this.customNodeFactory = customNodeFactory;
         this.obfuscationEventEmitter = obfuscationEventEmitter;
@@ -62,7 +64,7 @@ export class SelfDefendingCustomNodeGroup extends AbstractCustomNodeGroup {
      * @param stackTraceData
      */
     public appendCustomNodes (blockScopeNode: TNodeWithBlockStatement, stackTraceData: IStackTraceData[]): void {
-        const randomStackTraceIndex: number = NodeAppender.getRandomStackTraceIndex(stackTraceData.length);
+        const randomStackTraceIndex: number = this.getRandomStackTraceIndex(stackTraceData.length);
 
         // selfDefendingUnicodeNode append
         this.appendCustomNodeIfExist(CustomNode.SelfDefendingUnicodeNode, (customNode: ICustomNode) => {
@@ -95,7 +97,7 @@ export class SelfDefendingCustomNodeGroup extends AbstractCustomNodeGroup {
             return;
         }
 
-        const callsControllerFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6);
+        const callsControllerFunctionName: string = this.randomGenerator.getRandomVariableName(6);
 
         const selfDefendingUnicodeNode: ICustomNode = this.customNodeFactory(CustomNode.SelfDefendingUnicodeNode);
         const nodeCallsControllerFunctionNode: ICustomNode = this.customNodeFactory(CustomNode.NodeCallsControllerFunctionNode);

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

@@ -5,6 +5,7 @@ import * as format from 'string-template';
 
 import { TStatement } from '../../types/node/TStatement';
 
+import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
 import { IOptions } from '../../interfaces/options/IOptions';
 import { IStorage } from '../../interfaces/storages/IStorage';
 
@@ -27,6 +28,11 @@ import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
 export class StringArrayCallsWrapper extends AbstractCustomNode {
+    /**
+     * @type {IEscapeSequenceEncoder}
+     */
+    private readonly escapeSequenceEncoder: IEscapeSequenceEncoder;
+
     /**
      * @type {IStorage <string>}
      */
@@ -46,12 +52,16 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
     private stringArrayCallsWrapperName: string;
 
     /**
+     * @param escapeSequenceEncoder
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);
+
+        this.escapeSequenceEncoder = escapeSequenceEncoder;
     }
 
     /**
@@ -103,7 +113,7 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
             selfDefendingCode: string = '';
 
         if (this.options.selfDefending) {
-            selfDefendingCode = format(SelfDefendingTemplate(), {
+            selfDefendingCode = format(SelfDefendingTemplate(this.escapeSequenceEncoder), {
                 stringArrayCallsWrapperName: this.stringArrayCallsWrapperName,
                 stringArrayName: this.stringArrayName
             });

+ 22 - 4
src/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.ts

@@ -5,7 +5,9 @@ import * as format from 'string-template';
 
 import { TStatement } from '../../types/node/TStatement';
 
+import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IStorage } from '../../interfaces/storages/IStorage';
 
 import { initializable } from '../../decorators/Initializable';
@@ -18,11 +20,20 @@ import { StringArrayRotateFunctionTemplate } from '../../templates/custom-nodes/
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { JavaScriptObfuscator } from '../../JavaScriptObfuscator';
 import { NodeUtils } from '../../node/NodeUtils';
-import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
 import { Utils } from '../../utils/Utils';
 
 @injectable()
 export class StringArrayRotateFunctionNode extends AbstractCustomNode {
+    /**
+     * @type {IEscapeSequenceEncoder}
+     */
+    private readonly escapeSequenceEncoder: IEscapeSequenceEncoder;
+
+    /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
     /**
      * @type {IStorage <string>}
      */
@@ -42,12 +53,19 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
     private stringArrayRotateValue: number;
 
     /**
+     * @param randomGenerator
+     * @param escapeSequenceEncoder
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);
+
+        this.randomGenerator = randomGenerator;
+        this.escapeSequenceEncoder = escapeSequenceEncoder;
     }
 
     /**
@@ -76,13 +94,13 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
      * @returns {string}
      */
     protected getTemplate (): string {
-        const timesName: string = RandomGeneratorUtils.getRandomVariableName(6);
-        const whileFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6);
+        const timesName: string = this.randomGenerator.getRandomVariableName(6);
+        const whileFunctionName: string = this.randomGenerator.getRandomVariableName(6);
 
         let code: string = '';
 
         if (this.options.selfDefending) {
-            code = format(SelfDefendingTemplate(), {
+            code = format(SelfDefendingTemplate(this.escapeSequenceEncoder), {
                 timesName,
                 whileFunctionName
             });

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

@@ -7,6 +7,7 @@ import { TNodeWithBlockStatement } from '../../../types/node/TNodeWithBlockState
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IObfuscationEventEmitter } from '../../../interfaces/event-emitters/IObfuscationEventEmitter';
 import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IStackTraceData } from '../../../interfaces/stack-trace-analyzer/IStackTraceData';
 import { IStorage } from '../../../interfaces/storages/IStorage';
 
@@ -17,7 +18,6 @@ import { ObfuscationEvent } from '../../../enums/event-emitters/ObfuscationEvent
 
 import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
 import { NodeAppender } from '../../../node/NodeAppender';
-import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
 import { Utils } from '../../../utils/Utils';
 
 @injectable()
@@ -52,16 +52,18 @@ export class StringArrayCustomNodeGroup extends AbstractCustomNodeGroup {
     /**
      * @param customNodeFactory
      * @param obfuscationEventEmitter
+     * @param randomGenerator
      * @param stringArrayStorage
      * @param options
      */
     constructor (
         @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
         @inject(ServiceIdentifiers.IObfuscationEventEmitter) obfuscationEventEmitter: IObfuscationEventEmitter,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: IStorage<string>,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
 
         this.customNodeFactory = customNodeFactory;
         this.obfuscationEventEmitter = obfuscationEventEmitter;
@@ -112,7 +114,7 @@ export class StringArrayCustomNodeGroup extends AbstractCustomNodeGroup {
         let stringArrayRotateValue: number;
 
         if (this.options.rotateStringArray) {
-            stringArrayRotateValue = RandomGeneratorUtils.getRandomInteger(100, 500);
+            stringArrayRotateValue = this.randomGenerator.getRandomInteger(100, 500);
         } else {
             stringArrayRotateValue = 0;
         }

+ 11 - 0
src/enums/container/custom-nodes/ControlFlowCustomNode.ts

@@ -0,0 +1,11 @@
+export enum ControlFlowCustomNode {
+    BinaryExpressionFunctionNode,
+    BlockStatementControlFlowFlatteningNode,
+    CallExpressionControlFlowStorageCallNode,
+    CallExpressionFunctionNode,
+    ControlFlowStorageNode,
+    ExpressionWithOperatorControlFlowStorageCallNode,
+    LogicalExpressionFunctionNode,
+    StringLiteralControlFlowStorageCallNode,
+    StringLiteralNode,
+}

+ 1 - 10
src/enums/container/custom-nodes/CustomNode.ts

@@ -1,21 +1,12 @@
 export enum CustomNode {
-    BinaryExpressionFunctionNode,
-    BlockStatementControlFlowFlatteningNode,
-    CallExpressionControlFlowStorageCallNode,
-    CallExpressionFunctionNode,
-    ControlFlowStorageNode,
     ConsoleOutputDisableExpressionNode,
     DebugProtectionFunctionCallNode,
     DebugProtectionFunctionIntervalNode,
     DebugProtectionFunctionNode,
     DomainLockNode,
-    ExpressionWithOperatorControlFlowStorageCallNode,
-    LogicalExpressionFunctionNode,
     NodeCallsControllerFunctionNode,
     SelfDefendingUnicodeNode,
     StringArrayCallsWrapper,
     StringArrayNode,
-    StringArrayRotateFunctionNode,
-    StringLiteralControlFlowStorageCallNode,
-    StringLiteralNode,
+    StringArrayRotateFunctionNode
 }

+ 9 - 0
src/interfaces/container/IInversifyContainerFacade.d.ts

@@ -1,5 +1,7 @@
 import { interfaces } from 'inversify';
 
+import { TInputOptions } from '../../types/options/TInputOptions';
+
 export interface IInversifyContainerFacade {
     /**
      * @param serviceIdentifier
@@ -11,4 +13,11 @@ export interface IInversifyContainerFacade {
      * @param named
      */
     getNamed <T> (serviceIdentifier: interfaces.ServiceIdentifier<T>, named: string | number | symbol): T;
+
+    /**
+     * @param options
+     */
+    load (options: TInputOptions): void;
+
+    unload (): void;
 }

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

@@ -0,0 +1,20 @@
+export interface IArrayUtils {
+    /**
+     * @param length
+     * @return {number[]}
+     */
+    arrayRange (length: number): number[];
+
+    /**
+     * @param array
+     * @param times
+     * @returns {T[]}
+     */
+    arrayRotate <T> (array: T[], times: number): T[];
+
+    /**
+     * @param array
+     * @return {T[]}
+     */
+    arrayShuffle <T> (array: T[]): T[];
+}

+ 21 - 0
src/interfaces/utils/ICryptUtils.d.ts

@@ -0,0 +1,21 @@
+export interface ICryptUtils {
+    /**
+     * @param string
+     */
+    btoa (string: string): string;
+
+    /**
+     * @param str
+     * @param length
+     * @returns {[string, string]}
+     */
+    hideString (str: string, length: number): [string, string];
+
+    /**
+     * @param key
+     * @param string
+     * @returns {string}
+     */
+    /* tslint:disable */
+    rc4 (string: string, key: string): string;
+}

+ 7 - 0
src/interfaces/utils/IEscapeSequenceEncoder.d.ts

@@ -0,0 +1,7 @@
+export interface IEscapeSequenceEncoder {
+    /**
+     * @param string
+     * @param usingUnicodeEscapeSequence
+     */
+    encode (string: string, usingUnicodeEscapeSequence: boolean): string;
+}

+ 40 - 0
src/interfaces/utils/IRandomGenerator.d.ts

@@ -0,0 +1,40 @@
+import { Chance } from 'chance';
+
+export interface IRandomGenerator {
+    /**
+     * @returns {number}
+     */
+    getMathRandom (): number;
+
+    /**
+     * @param min
+     * @param max
+     * @returns {number}
+     */
+    getRandomFloat (min: number, max: number): number;
+
+    /**
+     * @returns {Chance.Chance}
+     */
+    getRandomGenerator (): Chance.Chance;
+
+    /**
+     * @param min
+     * @param max
+     * @returns {number}
+     */
+    getRandomInteger (min: number, max: number): number;
+
+    /**
+     * @param length
+     * @param pool
+     * @returns {string}
+     */
+    getRandomString (length: number, pool?: string): string;
+
+    /**
+     * @param length
+     * @returns {string}
+     */
+    getRandomVariableName (length: number): string
+}

+ 12 - 3
src/node-transformers/AbstractNodeTransformer.ts

@@ -5,16 +5,15 @@ import * as ESTree from 'estree';
 
 import { INodeTransformer } from '../interfaces/node-transformers/INodeTransformer';
 import { IOptions } from '../interfaces/options/IOptions';
+import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../interfaces/IVisitor';
 
-import { RandomGeneratorUtils } from '../utils/RandomGeneratorUtils';
-
 @injectable()
 export abstract class AbstractNodeTransformer implements INodeTransformer {
     /**
      * @type {number}
      */
-    protected nodeIdentifier: number = RandomGeneratorUtils.getRandomInteger(0, 10000);
+    protected nodeIdentifier: number;
 
     /**
      * @type {IOptions}
@@ -22,12 +21,22 @@ export abstract class AbstractNodeTransformer implements INodeTransformer {
     protected readonly options: IOptions;
 
     /**
+     * @type {IRandomGenerator}
+     */
+    protected readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
+        this.randomGenerator = randomGenerator;
         this.options = options;
+
+        this.nodeIdentifier = this.randomGenerator.getRandomInteger(0, 10000);
     }
 
     /**

+ 26 - 15
src/node-transformers/control-flow-transformers/BlockStatementControlFlowTransformer.ts

@@ -3,37 +3,48 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 import * as ESTree from 'estree';
 
-import { TCustomNodeFactory } from '../../types/container/custom-nodes/TCustomNodeFactory';
+import { TControlFlowCustomNodeFactory } from '../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 
+import { IArrayUtils } from '../../interfaces/utils/IArrayUtils';
 import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/IVisitor';
 
-import { CustomNode } from '../../enums/container/custom-nodes/CustomNode';
+import { ControlFlowCustomNode } from '../../enums/container/custom-nodes/ControlFlowCustomNode';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { Node } from '../../node/Node';
-import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
-import { Utils } from '../../utils/Utils';
 
 @injectable()
 export class BlockStatementControlFlowTransformer extends AbstractNodeTransformer {
     /**
-     * @type {TCustomNodeFactory}
+     * @type {IArrayUtils}
      */
-    private readonly customNodeFactory: TCustomNodeFactory;
+    private readonly arrayUtils: IArrayUtils;
 
     /**
-     * @param customNodeFactory
+     * @type {TControlFlowCustomNodeFactory}
+     */
+    private readonly controlFlowCustomNodeFactory: TControlFlowCustomNodeFactory;
+
+    /**
+     * @param controlFlowCustomNodeFactory
+     * @param arrayUtils
+     * @param randomGenerator
      * @param options
      */
     constructor (
-        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
+        @inject(ServiceIdentifiers.Factory__IControlFlowCustomNode)
+            controlFlowCustomNodeFactory: TControlFlowCustomNodeFactory,
+        @inject(ServiceIdentifiers.IArrayUtils) arrayUtils: IArrayUtils,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
 
-        this.customNodeFactory = customNodeFactory;
+        this.controlFlowCustomNodeFactory = controlFlowCustomNodeFactory;
+        this.arrayUtils = arrayUtils;
     }
 
     /**
@@ -70,7 +81,7 @@ export class BlockStatementControlFlowTransformer extends AbstractNodeTransforme
      */
     public transformNode (blockStatementNode: ESTree.BlockStatement, parentNode: ESTree.Node): ESTree.Node {
         if (
-            RandomGeneratorUtils.getMathRandom() > this.options.controlFlowFlatteningThreshold ||
+            this.randomGenerator.getMathRandom() > this.options.controlFlowFlatteningThreshold ||
             BlockStatementControlFlowTransformer.blockStatementHasProhibitedStatements(blockStatementNode)
         ) {
             return blockStatementNode;
@@ -82,11 +93,11 @@ export class BlockStatementControlFlowTransformer extends AbstractNodeTransforme
             return blockStatementNode;
         }
 
-        const originalKeys: number[] = Utils.arrayRange(blockStatementBody.length);
-        const shuffledKeys: number[] = Utils.arrayShuffle(originalKeys);
+        const originalKeys: number[] = this.arrayUtils.arrayRange(blockStatementBody.length);
+        const shuffledKeys: number[] = this.arrayUtils.arrayShuffle(originalKeys);
         const originalKeysIndexesInShuffledArray: number[] = originalKeys.map((key: number) => shuffledKeys.indexOf(key));
-        const blockStatementControlFlowFlatteningCustomNode: ICustomNode = this.customNodeFactory(
-            CustomNode.BlockStatementControlFlowFlatteningNode
+        const blockStatementControlFlowFlatteningCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
+            ControlFlowCustomNode.BlockStatementControlFlowFlatteningNode
         );
 
         blockStatementControlFlowFlatteningCustomNode.initialize(

+ 45 - 38
src/node-transformers/control-flow-transformers/FunctionControlFlowTransformer.ts

@@ -4,17 +4,18 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import * as estraverse from 'estraverse';
 import * as ESTree from 'estree';
 
+import { TControlFlowCustomNodeFactory } from '../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 import { TControlFlowReplacerFactory } from '../../types/container/node-transformers/TControlFlowReplacerFactory';
 import { TControlFlowStorageFactory } from '../../types/container/node-transformers/TControlFlowStorageFactory';
-import { TCustomNodeFactory } from '../../types/container/custom-nodes/TCustomNodeFactory';
 import { TNodeWithBlockStatement } from '../../types/node/TNodeWithBlockStatement';
 
 import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IStorage } from '../../interfaces/storages/IStorage';
 import { IVisitor } from '../../interfaces/IVisitor';
 
-import { CustomNode } from '../../enums/container/custom-nodes/CustomNode';
+import { ControlFlowCustomNode } from '../../enums/container/custom-nodes/ControlFlowCustomNode';
 import { NodeType } from '../../enums/NodeType';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
@@ -22,7 +23,6 @@ import { Node } from '../../node/Node';
 import { NodeAppender } from '../../node/NodeAppender';
 import { ControlFlowReplacer } from '../../enums/container/node-transformers/ControlFlowReplacer';
 import { NodeUtils } from '../../node/NodeUtils';
-import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
 
 @injectable()
 export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
@@ -72,51 +72,32 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
     private readonly controlFlowStorageFactory: TControlFlowStorageFactory;
 
     /**
-     * @type {TCustomNodeFactory}
+     * @type {TControlFlowCustomNodeFactory}
      */
-    private readonly customNodeFactory: TCustomNodeFactory;
+    private readonly controlFlowCustomNodeFactory: TControlFlowCustomNodeFactory;
 
     /**
      * @param controlFlowStorageFactory
      * @param controlFlowReplacerFactory
-     * @param customNodeFactory
+     * @param controlFlowCustomNodeFactory
+     * @param randomGenerator
      * @param options
      */
     constructor (
-        @inject(ServiceIdentifiers.Factory__TControlFlowStorage) controlFlowStorageFactory: TControlFlowStorageFactory,
-        @inject(ServiceIdentifiers.Factory__IControlFlowReplacer) controlFlowReplacerFactory: TControlFlowReplacerFactory,
-        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
+        @inject(ServiceIdentifiers.Factory__TControlFlowStorage)
+            controlFlowStorageFactory: TControlFlowStorageFactory,
+        @inject(ServiceIdentifiers.Factory__IControlFlowReplacer)
+            controlFlowReplacerFactory: TControlFlowReplacerFactory,
+        @inject(ServiceIdentifiers.Factory__IControlFlowCustomNode)
+            controlFlowCustomNodeFactory: TControlFlowCustomNodeFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
 
         this.controlFlowStorageFactory = controlFlowStorageFactory;
         this.controlFlowReplacerFactory = controlFlowReplacerFactory;
-        this.customNodeFactory = customNodeFactory;
-    }
-
-    /**
-     * @param functionNodeBody
-     * @returns {TNodeWithBlockStatement}
-     */
-    private static getHostNode (functionNodeBody: ESTree.BlockStatement): TNodeWithBlockStatement {
-        const blockScopesOfNode: TNodeWithBlockStatement[] = NodeUtils.getBlockScopesOfNode(functionNodeBody);
-
-        if (blockScopesOfNode.length === 1) {
-            return functionNodeBody;
-        } else {
-            blockScopesOfNode.pop();
-        }
-
-        if (blockScopesOfNode.length > FunctionControlFlowTransformer.hostNodeSearchMinDepth) {
-            blockScopesOfNode.splice(0, FunctionControlFlowTransformer.hostNodeSearchMinDepth);
-        }
-
-        if (blockScopesOfNode.length > FunctionControlFlowTransformer.hostNodeSearchMaxDepth) {
-            blockScopesOfNode.length = FunctionControlFlowTransformer.hostNodeSearchMaxDepth;
-        }
-
-        return RandomGeneratorUtils.getRandomGenerator().pickone(blockScopesOfNode);
+        this.controlFlowCustomNodeFactory = controlFlowCustomNodeFactory;
     }
 
     /**
@@ -148,7 +129,7 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
             return functionNode;
         }
 
-        const hostNode: TNodeWithBlockStatement = FunctionControlFlowTransformer.getHostNode(functionNode.body);
+        const hostNode: TNodeWithBlockStatement = this.getHostNode(functionNode.body);
         const controlFlowStorage: IStorage<ICustomNode> = this.getControlFlowStorage(hostNode);
 
         this.controlFlowData.set(hostNode, controlFlowStorage);
@@ -158,7 +139,9 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
             return functionNode;
         }
 
-        const controlFlowStorageCustomNode: ICustomNode = this.customNodeFactory(CustomNode.ControlFlowStorageNode);
+        const controlFlowStorageCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
+            ControlFlowCustomNode.ControlFlowStorageNode
+        );
 
         controlFlowStorageCustomNode.initialize(controlFlowStorage);
         NodeAppender.prependNode(hostNode, controlFlowStorageCustomNode.getNode());
@@ -187,6 +170,30 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
         return controlFlowStorage;
     }
 
+    /**
+     * @param functionNodeBody
+     * @returns {TNodeWithBlockStatement}
+     */
+    private getHostNode (functionNodeBody: ESTree.BlockStatement): TNodeWithBlockStatement {
+        const blockScopesOfNode: TNodeWithBlockStatement[] = NodeUtils.getBlockScopesOfNode(functionNodeBody);
+
+        if (blockScopesOfNode.length === 1) {
+            return functionNodeBody;
+        } else {
+            blockScopesOfNode.pop();
+        }
+
+        if (blockScopesOfNode.length > FunctionControlFlowTransformer.hostNodeSearchMinDepth) {
+            blockScopesOfNode.splice(0, FunctionControlFlowTransformer.hostNodeSearchMinDepth);
+        }
+
+        if (blockScopesOfNode.length > FunctionControlFlowTransformer.hostNodeSearchMaxDepth) {
+            blockScopesOfNode.length = FunctionControlFlowTransformer.hostNodeSearchMaxDepth;
+        }
+
+        return this.randomGenerator.getRandomGenerator().pickone(blockScopesOfNode);
+    }
+
     /**
      * @param node
      * @return {boolean}
@@ -214,7 +221,7 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
                     return node;
                 }
 
-                if (RandomGeneratorUtils.getMathRandom() > this.options.controlFlowFlatteningThreshold) {
+                if (this.randomGenerator.getMathRandom() > this.options.controlFlowFlatteningThreshold) {
                     return node;
                 }
 

+ 19 - 11
src/node-transformers/control-flow-transformers/control-flow-replacers/AbstractControlFlowReplacer.ts

@@ -3,41 +3,49 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 import * as ESTree from 'estree';
 
-import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
+import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 
 import { IControlFlowReplacer } from '../../../interfaces/node-transformers/control-flow-transformers/IControlFlowReplacer';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IStorage } from '../../../interfaces/storages/IStorage';
 
-import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
-
 @injectable()
 export abstract class AbstractControlFlowReplacer implements IControlFlowReplacer {
     /**
-     * @type {TCustomNodeFactory}
+     * @type {TControlFlowCustomNodeFactory}
      */
-    protected readonly customNodeFactory: TCustomNodeFactory;
+    protected readonly controlFlowCustomNodeFactory: TControlFlowCustomNodeFactory;
 
     /**
      * @type {IOptions}
      */
     protected readonly options: IOptions;
 
+    /**
+     * @type {IRandomGenerator}
+     */
+    protected readonly randomGenerator: IRandomGenerator;
+
     /**
      * @type {Map<string, Map<string, string[]>>}
      */
     protected readonly replacerDataByControlFlowStorageId: Map <string, Map<string, string[]>> = new Map();
 
     /**
-     * @param customNodeFactory
+     * @param controlFlowCustomNodeFactory
+     * @param randomGenerator
      * @param options
      */
     constructor (
-        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
+        @inject(ServiceIdentifiers.Factory__IControlFlowCustomNode)
+            controlFlowCustomNodeFactory: TControlFlowCustomNodeFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        this.customNodeFactory = customNodeFactory;
+        this.controlFlowCustomNodeFactory = controlFlowCustomNodeFactory;
+        this.randomGenerator = randomGenerator;
         this.options = options;
     }
 
@@ -88,15 +96,15 @@ export abstract class AbstractControlFlowReplacer implements IControlFlowReplace
         const storageKeysForCurrentId: string[] | undefined = storageKeysById.get(replacerId);
 
         if (
-            RandomGeneratorUtils.getMathRandom() < usingExistingIdentifierChance &&
+            this.randomGenerator.getMathRandom() < usingExistingIdentifierChance &&
             storageKeysForCurrentId &&
             storageKeysForCurrentId.length
         ) {
-            return RandomGeneratorUtils.getRandomGenerator().pickone(storageKeysForCurrentId);
+            return this.randomGenerator.getRandomGenerator().pickone(storageKeysForCurrentId);
         }
 
         const generateStorageKey: (length: number) => string = (length: number) => {
-            const storageKey: string = RandomGeneratorUtils.getRandomString(length);
+            const storageKey: string = this.randomGenerator.getRandomString(length);
 
             if (controlFlowStorage.getStorage().has(storageKey)) {
                 return generateStorageKey(length);

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

@@ -3,13 +3,14 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 import * as ESTree from 'estree';
 
-import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
+import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IStorage } from '../../../interfaces/storages/IStorage';
 
-import { CustomNode } from '../../../enums/container/custom-nodes/CustomNode';
+import { ControlFlowCustomNode } from '../../../enums/container/custom-nodes/ControlFlowCustomNode';
 
 import { ExpressionWithOperatorControlFlowReplacer } from './ExpressionWithOperatorControlFlowReplacer';
 
@@ -21,14 +22,17 @@ export class BinaryExpressionControlFlowReplacer extends ExpressionWithOperatorC
     private static readonly usingExistingIdentifierChance: number = 0.5;
 
     /**
-     * @param customNodeFactory
+     * @param controlFlowCustomNodeFactory
+     * @param randomGenerator
      * @param options
      */
     constructor (
-        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
+        @inject(ServiceIdentifiers.Factory__IControlFlowCustomNode)
+            controlFlowCustomNodeFactory: TControlFlowCustomNodeFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(customNodeFactory, options);
+        super(controlFlowCustomNodeFactory, randomGenerator, options);
     }
 
     /**
@@ -43,7 +47,9 @@ export class BinaryExpressionControlFlowReplacer extends ExpressionWithOperatorC
         controlFlowStorage: IStorage <ICustomNode>
     ): ESTree.Node {
         const replacerId: string = binaryExpressionNode.operator;
-        const binaryExpressionFunctionCustomNode: ICustomNode = this.customNodeFactory(CustomNode.BinaryExpressionFunctionNode);
+        const binaryExpressionFunctionCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
+            ControlFlowCustomNode.BinaryExpressionFunctionNode
+        );
 
         binaryExpressionFunctionCustomNode.initialize(replacerId);
 

+ 14 - 8
src/node-transformers/control-flow-transformers/control-flow-replacers/CallExpressionControlFlowReplacer.ts

@@ -3,14 +3,15 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 import * as ESTree from 'estree';
 
-import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
+import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 import { TStatement } from '../../../types/node/TStatement';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IStorage } from '../../../interfaces/storages/IStorage';
 
-import { CustomNode } from '../../../enums/container/custom-nodes/CustomNode';
+import { ControlFlowCustomNode } from '../../../enums/container/custom-nodes/ControlFlowCustomNode';
 
 import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
 import { Node } from '../../../node/Node';
@@ -23,14 +24,17 @@ export class CallExpressionControlFlowReplacer extends AbstractControlFlowReplac
     private static readonly usingExistingIdentifierChance: number = 0.5;
 
     /**
-     * @param customNodeFactory
+     * @param controlFlowCustomNodeFactory
+     * @param randomGenerator
      * @param options
      */
     constructor (
-        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
+        @inject(ServiceIdentifiers.Factory__IControlFlowCustomNode)
+            controlFlowCustomNodeFactory: TControlFlowCustomNodeFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(customNodeFactory, options);
+        super(controlFlowCustomNodeFactory, randomGenerator, options);
     }
 
     /**
@@ -51,7 +55,9 @@ export class CallExpressionControlFlowReplacer extends AbstractControlFlowReplac
         }
 
         const replacerId: string = String(callExpressionNode.arguments.length);
-        const callExpressionFunctionCustomNode: ICustomNode = this.customNodeFactory(CustomNode.CallExpressionFunctionNode);
+        const callExpressionFunctionCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
+            ControlFlowCustomNode.CallExpressionFunctionNode
+        );
         const expressionArguments: (ESTree.Expression | ESTree.SpreadElement)[] = callExpressionNode.arguments;
 
         callExpressionFunctionCustomNode.initialize(expressionArguments);
@@ -85,8 +91,8 @@ export class CallExpressionControlFlowReplacer extends AbstractControlFlowReplac
         callee: ESTree.Expression,
         expressionArguments: (ESTree.Expression | ESTree.SpreadElement)[]
     ): ESTree.Node {
-        const controlFlowStorageCallCustomNode: ICustomNode = this.customNodeFactory(
-            CustomNode.CallExpressionControlFlowStorageCallNode
+        const controlFlowStorageCallCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
+            ControlFlowCustomNode.CallExpressionControlFlowStorageCallNode
         );
 
         controlFlowStorageCallCustomNode.initialize(controlFlowStorageId, storageKey, callee, expressionArguments);

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

@@ -3,23 +3,20 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 import * as ESTree from 'estree';
 
-import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
+import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 import { TStatement } from '../../../types/node/TStatement';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
+
+import { ControlFlowCustomNode } from '../../../enums/container/custom-nodes/ControlFlowCustomNode';
 
 import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
-import { CustomNode } from '../../../enums/container/custom-nodes/CustomNode';
 import { Node } from '../../../node/Node';
 
 @injectable()
 export abstract class ExpressionWithOperatorControlFlowReplacer extends AbstractControlFlowReplacer {
-    /**
-     * @type {TCustomNodeFactory}
-     */
-    protected readonly customNodeFactory: TCustomNodeFactory;
-
     /**
      * @type {IOptions}
      */
@@ -31,14 +28,17 @@ export abstract class ExpressionWithOperatorControlFlowReplacer extends Abstract
     protected readonly replacerDataByControlFlowStorageId: Map <string, Map<string, string[]>> = new Map();
 
     /**
-     * @param customNodeFactory
+     * @param controlFlowCustomNodeFactory
+     * @param randomGenerator
      * @param options
      */
     constructor (
-        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
+        @inject(ServiceIdentifiers.Factory__IControlFlowCustomNode)
+            controlFlowCustomNodeFactory: TControlFlowCustomNodeFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(customNodeFactory, options);
+        super(controlFlowCustomNodeFactory, randomGenerator, options);
     }
 
     /**
@@ -54,8 +54,8 @@ export abstract class ExpressionWithOperatorControlFlowReplacer extends Abstract
         leftExpression: ESTree.Expression,
         rightExpression: ESTree.Expression
     ): ESTree.Node {
-        const controlFlowStorageCallCustomNode: ICustomNode = this.customNodeFactory(
-            CustomNode.ExpressionWithOperatorControlFlowStorageCallNode
+        const controlFlowStorageCallCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
+            ControlFlowCustomNode.ExpressionWithOperatorControlFlowStorageCallNode
         );
 
         controlFlowStorageCallCustomNode.initialize(controlFlowStorageId, storageKey, leftExpression, rightExpression);

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

@@ -3,13 +3,14 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 import * as ESTree from 'estree';
 
-import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
+import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IStorage } from '../../../interfaces/storages/IStorage';
 
-import { CustomNode } from '../../../enums/container/custom-nodes/CustomNode';
+import { ControlFlowCustomNode } from '../../../enums/container/custom-nodes/ControlFlowCustomNode';
 
 import { ExpressionWithOperatorControlFlowReplacer } from './ExpressionWithOperatorControlFlowReplacer';
 import { Node } from '../../../node/Node';
@@ -23,14 +24,17 @@ export class LogicalExpressionControlFlowReplacer extends ExpressionWithOperator
     private static readonly usingExistingIdentifierChance: number = 0.5;
 
     /**
-     * @param customNodeFactory
+     * @param controlFlowCustomNodeFactory
+     * @param randomGenerator
      * @param options
      */
     constructor (
-        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
+        @inject(ServiceIdentifiers.Factory__IControlFlowCustomNode)
+            controlFlowCustomNodeFactory: TControlFlowCustomNodeFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(customNodeFactory, options);
+        super(controlFlowCustomNodeFactory, randomGenerator, options);
     }
 
     /**
@@ -49,7 +53,9 @@ export class LogicalExpressionControlFlowReplacer extends ExpressionWithOperator
         }
 
         const replacerId: string = logicalExpressionNode.operator;
-        const logicalExpressionFunctionCustomNode: ICustomNode = this.customNodeFactory(CustomNode.LogicalExpressionFunctionNode);
+        const logicalExpressionFunctionCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
+            ControlFlowCustomNode.LogicalExpressionFunctionNode
+        );
 
         logicalExpressionFunctionCustomNode.initialize(replacerId);
 

+ 14 - 8
src/node-transformers/control-flow-transformers/control-flow-replacers/StringLiteralControlFlowReplacer.ts

@@ -3,14 +3,15 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 
 import * as ESTree from 'estree';
 
-import { TCustomNodeFactory } from '../../../types/container/custom-nodes/TCustomNodeFactory';
+import { TControlFlowCustomNodeFactory } from '../../../types/container/custom-nodes/TControlFlowCustomNodeFactory';
 import { TStatement } from '../../../types/node/TStatement';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
 import { IStorage } from '../../../interfaces/storages/IStorage';
 
-import { CustomNode } from '../../../enums/container/custom-nodes/CustomNode';
+import { ControlFlowCustomNode } from '../../../enums/container/custom-nodes/ControlFlowCustomNode';
 
 import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
 import { Node } from '../../../node/Node';
@@ -23,14 +24,17 @@ export class StringLiteralControlFlowReplacer extends AbstractControlFlowReplace
     private static readonly usingExistingIdentifierChance: number = 1;
 
     /**
-     * @param customNodeFactory
+     * @param controlFlowCustomNodeFactory
+     * @param randomGenerator
      * @param options
      */
     constructor (
-        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
+        @inject(ServiceIdentifiers.Factory__IControlFlowCustomNode)
+            controlFlowCustomNodeFactory: TControlFlowCustomNodeFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(customNodeFactory, options);
+        super(controlFlowCustomNodeFactory, randomGenerator, options);
     }
 
     /**
@@ -53,7 +57,9 @@ export class StringLiteralControlFlowReplacer extends AbstractControlFlowReplace
         }
 
         const replacerId: string = String(literalNode.value);
-        const literalFunctionCustomNode: ICustomNode = this.customNodeFactory(CustomNode.StringLiteralNode);
+        const literalFunctionCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
+            ControlFlowCustomNode.StringLiteralNode
+        );
 
         literalFunctionCustomNode.initialize(literalNode.value);
 
@@ -76,8 +82,8 @@ export class StringLiteralControlFlowReplacer extends AbstractControlFlowReplace
         controlFlowStorageId: string,
         storageKey: string
     ): ESTree.Node {
-        const controlFlowStorageCallCustomNode: ICustomNode = this.customNodeFactory(
-            CustomNode.StringLiteralControlFlowStorageCallNode
+        const controlFlowStorageCallCustomNode: ICustomNode = this.controlFlowCustomNodeFactory(
+            ControlFlowCustomNode.StringLiteralControlFlowStorageCallNode
         );
 
         controlFlowStorageCallCustomNode.initialize(controlFlowStorageId, storageKey);

+ 4 - 1
src/node-transformers/converting-transformers/MemberExpressionTransformer.ts

@@ -4,6 +4,7 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import * as ESTree from 'estree';
 
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/IVisitor';
 
 import { NodeType } from '../../enums/NodeType';
@@ -14,12 +15,14 @@ import { Node } from '../../node/Node';
 @injectable()
 export class MemberExpressionTransformer extends AbstractNodeTransformer {
     /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
     }
 
     /**

+ 4 - 1
src/node-transformers/converting-transformers/MethodDefinitionTransformer.ts

@@ -4,6 +4,7 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import * as ESTree from 'estree';
 
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/IVisitor';
 
 import { NodeType } from '../../enums/NodeType';
@@ -28,12 +29,14 @@ export class MethodDefinitionTransformer extends AbstractNodeTransformer {
     private static readonly ignoredNames: string[] = ['constructor'];
 
     /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
     }
 
     /**

+ 4 - 1
src/node-transformers/converting-transformers/TemplateLiteralTransformer.ts

@@ -4,6 +4,7 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import * as ESTree from 'estree';
 
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/IVisitor';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
@@ -17,12 +18,14 @@ import { Nodes } from '../../node/Nodes';
 @injectable()
 export class TemplateLiteralTransformer extends AbstractNodeTransformer {
     /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
     }
 
     /**

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

@@ -5,13 +5,13 @@ import * as estraverse from 'estraverse';
 import * as ESTree from 'estree';
 
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/IVisitor';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { Node } from '../../node/Node';
 import { Nodes } from '../../node/Nodes';
 import { NodeUtils } from '../../node/NodeUtils';
-import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
 
 @injectable()
 export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
@@ -31,19 +31,45 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
     private readonly collectedBlockStatements: ESTree.BlockStatement[] = [];
 
     /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
+    }
+
+    /**
+     * @return {IVisitor}
+     */
+    public getVisitor (): IVisitor {
+        return {
+            leave: (node: ESTree.Node, parentNode: ESTree.Node) => {
+                if (Node.isProgramNode(node)) {
+                    return this.transformNode(node, parentNode);
+                }
+            }
+        };
+    }
+
+    /**
+     * @param programNode
+     * @param parentNode
+     * @returns {ESTree.Node}
+     */
+    public transformNode (programNode: ESTree.Program, parentNode: ESTree.Node): ESTree.Node {
+        this.transformProgramNode(programNode);
+
+        return programNode;
     }
 
     /**
      * @param blockStatementNode
      * @param collectedBlockStatements
      */
-    private static collectBlockStatementNodes (
+    private collectBlockStatementNodes (
         blockStatementNode: ESTree.BlockStatement,
         collectedBlockStatements: ESTree.BlockStatement[]
     ): void {
@@ -80,7 +106,7 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
                  * in current block statement
                  */
                 if (Node.isIdentifierNode(node) && !Node.isMemberExpressionNode(parentNode)) {
-                    node.name = RandomGeneratorUtils.getRandomVariableName(6);
+                    node.name = this.randomGenerator.getRandomVariableName(6);
                 }
 
                 return node;
@@ -99,16 +125,16 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
      * @param randomBlockStatementNode
      * @return {ESTree.BlockStatement}
      */
-    private static replaceBlockStatementNode (
+    private replaceBlockStatementNode (
         blockStatementNode: ESTree.BlockStatement,
         randomBlockStatementNode: ESTree.BlockStatement
     ): ESTree.BlockStatement {
-        const random1: boolean = RandomGeneratorUtils.getMathRandom() > 0.5;
-        const random2: boolean = RandomGeneratorUtils.getMathRandom() > 0.5;
+        const random1: boolean = this.randomGenerator.getMathRandom() > 0.5;
+        const random2: boolean = this.randomGenerator.getMathRandom() > 0.5;
 
         const operator: ESTree.BinaryOperator = random1 ? '===' : '!==';
-        const leftString: string = RandomGeneratorUtils.getRandomString(3);
-        const rightString: string = random2 ? leftString : RandomGeneratorUtils.getRandomString(3);
+        const leftString: string = this.randomGenerator.getRandomString(3);
+        const rightString: string = random2 ? leftString : this.randomGenerator.getRandomString(3);
 
         let consequent: ESTree.BlockStatement,
             alternate: ESTree.BlockStatement;
@@ -138,30 +164,6 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
         return newBlockStatementNode;
     }
 
-    /**
-     * @return {IVisitor}
-     */
-    public getVisitor (): IVisitor {
-        return {
-            leave: (node: ESTree.Node, parentNode: ESTree.Node) => {
-                if (Node.isProgramNode(node)) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
-    }
-
-    /**
-     * @param programNode
-     * @param parentNode
-     * @returns {ESTree.Node}
-     */
-    public transformNode (programNode: ESTree.Program, parentNode: ESTree.Node): ESTree.Node {
-        this.transformProgramNode(programNode);
-
-        return programNode;
-    }
-
     /**
      * @param programNode
      */
@@ -172,7 +174,7 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
                     return;
                 }
 
-                DeadCodeInjectionTransformer.collectBlockStatementNodes(node, this.collectedBlockStatements);
+                this.collectBlockStatementNodes(node, this.collectedBlockStatements);
             }
         });
 
@@ -188,19 +190,19 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
 
                 if (
                     !Node.isBlockStatementNode(node) ||
-                    RandomGeneratorUtils.getMathRandom() > this.options.deadCodeInjectionThreshold
+                    this.randomGenerator.getMathRandom() > this.options.deadCodeInjectionThreshold
                 ) {
                     return node;
                 }
 
-                const randomIndex: number = RandomGeneratorUtils.getRandomInteger(0, this.collectedBlockStatements.length - 1);
+                const randomIndex: number = this.randomGenerator.getRandomInteger(0, this.collectedBlockStatements.length - 1);
                 const randomBlockStatementNode: ESTree.BlockStatement = this.collectedBlockStatements.splice(randomIndex, 1)[0];
 
                 if (randomBlockStatementNode === node) {
                     return node;
                 }
 
-                return DeadCodeInjectionTransformer.replaceBlockStatementNode(node, randomBlockStatementNode);
+                return this.replaceBlockStatementNode(node, randomBlockStatementNode);
             }
         });
     }

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

@@ -8,6 +8,7 @@ import { TIdentifierObfuscatingReplacerFactory } from '../../types/container/nod
 
 import { IIdentifierObfuscatingReplacer } from '../../interfaces/node-transformers/obfuscating-transformers/IIdentifierObfuscatingReplacer';
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/IVisitor';
 
 import { IdentifierObfuscatingReplacer } from '../../enums/container/node-transformers/IdentifierObfuscatingReplacer';
@@ -32,14 +33,16 @@ export class CatchClauseTransformer extends AbstractNodeTransformer {
 
     /**
      * @param identifierObfuscatingReplacerFactory
+     * @param randomGenerator
      * @param options
      */
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierObfuscatingReplacer)
             identifierObfuscatingReplacerFactory: TIdentifierObfuscatingReplacerFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
 
         this.identifierObfuscatingReplacer = identifierObfuscatingReplacerFactory(
             IdentifierObfuscatingReplacer.BaseIdentifierObfuscatingReplacer

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

@@ -9,6 +9,7 @@ import { TNodeWithBlockStatement } from '../../types/node/TNodeWithBlockStatemen
 
 import { IIdentifierObfuscatingReplacer } from '../../interfaces/node-transformers/obfuscating-transformers/IIdentifierObfuscatingReplacer';
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/IVisitor';
 
 import { IdentifierObfuscatingReplacer } from "../../enums/container/node-transformers/IdentifierObfuscatingReplacer";
@@ -41,14 +42,16 @@ export class FunctionDeclarationTransformer extends AbstractNodeTransformer {
 
     /**
      * @param identifierObfuscatingReplacerFactory
+     * @param randomGenerator
      * @param options
      */
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierObfuscatingReplacer)
             identifierObfuscatingReplacerFactory: TIdentifierObfuscatingReplacerFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
 
         this.identifierObfuscatingReplacer = identifierObfuscatingReplacerFactory(
             IdentifierObfuscatingReplacer.BaseIdentifierObfuscatingReplacer

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

@@ -8,6 +8,7 @@ import { TIdentifierObfuscatingReplacerFactory } from '../../types/container/nod
 
 import { IIdentifierObfuscatingReplacer } from '../../interfaces/node-transformers/obfuscating-transformers/IIdentifierObfuscatingReplacer';
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/IVisitor';
 
 import { IdentifierObfuscatingReplacer } from '../../enums/container/node-transformers/IdentifierObfuscatingReplacer';
@@ -32,14 +33,16 @@ export class FunctionTransformer extends AbstractNodeTransformer {
 
     /**
      * @param identifierObfuscatingReplacerFactory
+     * @param randomGenerator
      * @param options
      */
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierObfuscatingReplacer)
             identifierObfuscatingReplacerFactory: TIdentifierObfuscatingReplacerFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
 
         this.identifierObfuscatingReplacer = identifierObfuscatingReplacerFactory(
             IdentifierObfuscatingReplacer.BaseIdentifierObfuscatingReplacer

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

@@ -8,6 +8,7 @@ import { TIdentifierObfuscatingReplacerFactory } from '../../types/container/nod
 
 import { IIdentifierObfuscatingReplacer } from '../../interfaces/node-transformers/obfuscating-transformers/IIdentifierObfuscatingReplacer';
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/IVisitor';
 
 import { IdentifierObfuscatingReplacer } from '../../enums/container/node-transformers/IdentifierObfuscatingReplacer';
@@ -40,14 +41,16 @@ export class LabeledStatementTransformer extends AbstractNodeTransformer {
 
     /**
      * @param identifierObfuscatingReplacerFactory
+     * @param randomGenerator
      * @param options
      */
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierObfuscatingReplacer)
             identifierObfuscatingReplacerFactory: TIdentifierObfuscatingReplacerFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
 
         this.identifierObfuscatingReplacer = identifierObfuscatingReplacerFactory(
             IdentifierObfuscatingReplacer.BaseIdentifierObfuscatingReplacer

+ 4 - 1
src/node-transformers/obfuscating-transformers/LiteralTransformer.ts

@@ -6,6 +6,7 @@ import * as ESTree from 'estree';
 import { TLiteralObfuscatingReplacerFactory } from '../../types/container/node-transformers/TLiteralObfuscatingReplacerFactory';
 
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/IVisitor';
 
 import { LiteralObfuscatingReplacer } from '../../enums/container/node-transformers/LiteralObfuscatingReplacer';
@@ -22,14 +23,16 @@ export class LiteralTransformer extends AbstractNodeTransformer {
 
     /**
      * @param literalObfuscatingReplacerFactory
+     * @param randomGenerator
      * @param options
      */
     constructor (
         @inject(ServiceIdentifiers.Factory__IObfuscatingReplacer)
             literalObfuscatingReplacerFactory: TLiteralObfuscatingReplacerFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
 
         this.literalObfuscatingReplacerFactory = literalObfuscatingReplacerFactory;
     }

+ 4 - 1
src/node-transformers/obfuscating-transformers/ObjectExpressionTransformer.ts

@@ -4,6 +4,7 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 import * as ESTree from 'estree';
 
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/IVisitor';
 
 import { NodeType } from '../../enums/NodeType';
@@ -21,12 +22,14 @@ import { Node } from '../../node/Node';
 @injectable()
 export class ObjectExpressionTransformer extends AbstractNodeTransformer {
     /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
     }
 
     /**

+ 5 - 2
src/node-transformers/obfuscating-transformers/VariableDeclarationTransformer.ts

@@ -7,8 +7,9 @@ import * as ESTree from 'estree';
 import { TIdentifierObfuscatingReplacerFactory } from '../../types/container/node-transformers/TIdentifierObfuscatingReplacerFactory';
 import { TNodeWithBlockStatement } from '../../types/node/TNodeWithBlockStatement';
 
-import { IOptions } from '../../interfaces/options/IOptions';
 import { IIdentifierObfuscatingReplacer } from '../../interfaces/node-transformers/obfuscating-transformers/IIdentifierObfuscatingReplacer';
+import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/IVisitor';
 
 import { IdentifierObfuscatingReplacer } from "../../enums/container/node-transformers/IdentifierObfuscatingReplacer";
@@ -42,14 +43,16 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
 
     /**
      * @param identifierObfuscatingReplacerFactory
+     * @param randomGenerator
      * @param options
      */
     constructor (
         @inject(ServiceIdentifiers.Factory__IIdentifierObfuscatingReplacer)
             identifierObfuscatingReplacerFactory: TIdentifierObfuscatingReplacerFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super(options);
+        super(randomGenerator, options);
 
         this.identifierObfuscatingReplacer = identifierObfuscatingReplacerFactory(
             IdentifierObfuscatingReplacer.BaseIdentifierObfuscatingReplacer

+ 11 - 2
src/node-transformers/obfuscating-transformers/obfuscating-replacers/identifier-obfuscating-replacers/BaseIdentifierObfuscatingReplacer.ts

@@ -5,10 +5,10 @@ import * as ESTree from 'estree';
 
 import { IIdentifierObfuscatingReplacer } from '../../../../interfaces/node-transformers/obfuscating-transformers/IIdentifierObfuscatingReplacer';
 import { IOptions } from '../../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../../interfaces/utils/IRandomGenerator';
 
 import { AbstractObfuscatingReplacer } from '../AbstractObfuscatingReplacer';
 import { Nodes } from '../../../../node/Nodes';
-import { RandomGeneratorUtils } from '../../../../utils/RandomGeneratorUtils';
 
 @injectable()
 export class BaseIdentifierObfuscatingReplacer extends AbstractObfuscatingReplacer implements IIdentifierObfuscatingReplacer {
@@ -18,12 +18,21 @@ export class BaseIdentifierObfuscatingReplacer extends AbstractObfuscatingReplac
     private readonly namesMap: Map<string, string> = new Map();
 
     /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param randomGenerator
      * @param options
      */
     constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);
+
+        this.randomGenerator = randomGenerator;
     }
 
     /**
@@ -50,7 +59,7 @@ export class BaseIdentifierObfuscatingReplacer extends AbstractObfuscatingReplac
      */
     public storeNames (nodeName: string, nodeIdentifier: number): void {
         if (!this.isReservedName(nodeName)) {
-            this.namesMap.set(`${nodeName}-${String(nodeIdentifier)}`, RandomGeneratorUtils.getRandomVariableName(6));
+            this.namesMap.set(`${nodeName}-${String(nodeIdentifier)}`, this.randomGenerator.getRandomVariableName(6));
         }
     }
 

+ 36 - 14
src/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/StringLiteralObfuscatingReplacer.ts

@@ -3,18 +3,19 @@ import { ServiceIdentifiers } from '../../../../container/ServiceIdentifiers';
 
 import * as ESTree from 'estree';
 
+import { ICryptUtils } from '../../../../interfaces/utils/ICryptUtils';
 import { ICustomNodeGroup } from '../../../../interfaces/custom-nodes/ICustomNodeGroup';
 import { IEncodedValue } from '../../../../interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/IEncodedValue';
+import { IEscapeSequenceEncoder } from '../../../../interfaces/utils/IEscapeSequenceEncoder';
 import { IOptions } from '../../../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../../../interfaces/utils/IRandomGenerator';
 import { IStorage } from '../../../../interfaces/storages/IStorage';
 import { IStringArrayIndexData } from '../../../../interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/literal-obfuscating-replacers/IStringArrayIndexData';
 
 import { StringArrayEncoding } from '../../../../enums/StringArrayEncoding';
 
 import { AbstractObfuscatingReplacer } from '../AbstractObfuscatingReplacer';
-import { CryptUtils } from '../../../../utils/CryptUtils';
 import { Nodes } from '../../../../node/Nodes';
-import { RandomGeneratorUtils } from '../../../../utils/RandomGeneratorUtils';
 import { Utils } from '../../../../utils/Utils';
 
 @injectable()
@@ -34,16 +35,31 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
      */
     private static rc4KeysCount: number = 50;
 
+    /**
+     * @type {ICryptUtils}
+     */
+    private readonly cryptUtils: ICryptUtils;
+
     /**
      * @type {IStorage<ICustomNodeGroup>}
      */
     private readonly customNodeGroupStorage: IStorage<ICustomNodeGroup>;
 
+    /**
+     * @type {IEscapeSequenceEncoder}
+     */
+    private readonly escapeSequenceEncoder: IEscapeSequenceEncoder;
+
     /**
      * @type {Map<string, ESTree.Node>}
      */
     private readonly nodesCache: Map <string, ESTree.Node> = new Map();
 
+    /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
     /**
      * @type {string[]}
      */
@@ -62,21 +78,30 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
     /**
      * @param customNodeGroupStorage
      * @param stringArrayStorage
+     * @param escapeSequenceEncoder
+     * @param randomGenerator
+     * @param cryptUtils
      * @param options
      */
     constructor (
         @inject(ServiceIdentifiers.TCustomNodeGroupStorage) customNodeGroupStorage: IStorage<ICustomNodeGroup>,
         @inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: IStorage<string>,
+        @inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
+        @inject(ServiceIdentifiers.ICryptUtils) cryptUtils: ICryptUtils,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
         super(options);
 
         this.customNodeGroupStorage = customNodeGroupStorage;
         this.stringArrayStorage = stringArrayStorage;
+        this.escapeSequenceEncoder = escapeSequenceEncoder;
+        this.randomGenerator = randomGenerator;
+        this.cryptUtils = cryptUtils;
 
-        this.rc4Keys = RandomGeneratorUtils.getRandomGenerator()
+        this.rc4Keys = this.randomGenerator.getRandomGenerator()
             .n(
-                () => RandomGeneratorUtils.getRandomGenerator().string({
+                () => this.randomGenerator.getRandomGenerator().string({
                     length: StringLiteralObfuscatingReplacer.rc4KeyLength
                 }),
                 StringLiteralObfuscatingReplacer.rc4KeysCount
@@ -137,7 +162,7 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
         return (
             this.options.stringArray &&
             nodeValue.length >= StringLiteralObfuscatingReplacer.minimumLengthForStringArray &&
-            RandomGeneratorUtils.getMathRandom() <= this.options.stringArrayThreshold
+            this.randomGenerator.getMathRandom() <= this.options.stringArrayThreshold
         );
     }
 
@@ -175,13 +200,13 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
 
         switch (this.options.stringArrayEncoding) {
             case StringArrayEncoding.Rc4:
-                key = RandomGeneratorUtils.getRandomGenerator().pickone(this.rc4Keys);
-                encodedValue = CryptUtils.btoa(CryptUtils.rc4(value, key));
+                key = this.randomGenerator.getRandomGenerator().pickone(this.rc4Keys);
+                encodedValue = this.cryptUtils.btoa(this.cryptUtils.rc4(value, key));
 
                 break;
 
             case StringArrayEncoding.Base64:
-                encodedValue = CryptUtils.btoa(value);
+                encodedValue = this.cryptUtils.btoa(value);
 
                 break;
 
@@ -198,10 +223,7 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
      */
     private replaceWithLiteralNode (value: string): ESTree.Node {
         return Nodes.getLiteralNode(
-            Utils.stringToUnicodeEscapeSequence(
-                value,
-                this.options.unicodeEscapeSequence
-            )
+            this.escapeSequenceEncoder.encode(value, this.options.unicodeEscapeSequence)
         );
     }
 
@@ -211,7 +233,7 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
      */
     private replaceWithStringArrayCallNode (value: string): ESTree.Node {
         const { encodedValue, key }: IEncodedValue = this.getEncodedValue(value);
-        const escapedValue: string = Utils.stringToUnicodeEscapeSequence(encodedValue, this.options.unicodeEscapeSequence);
+        const escapedValue: string = this.escapeSequenceEncoder.encode(encodedValue, this.options.unicodeEscapeSequence);
 
         const stringArrayStorageLength: number = this.stringArrayStorage.getLength();
         const rotatedStringArrayStorageId: string = Utils.stringRotate(this.stringArrayStorage.getStorageId(), 1);
@@ -232,7 +254,7 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
 
         if (key) {
             callExpressionArgs.push(StringLiteralObfuscatingReplacer.getRc4KeyLiteralNode(
-                Utils.stringToUnicodeEscapeSequence(key, this.options.unicodeEscapeSequence)
+                this.escapeSequenceEncoder.encode(key, this.options.unicodeEscapeSequence)
             ));
         }
 

+ 0 - 9
src/node/NodeAppender.ts

@@ -5,8 +5,6 @@ import { TStatement } from '../types/node/TStatement';
 
 import { IStackTraceData } from '../interfaces/stack-trace-analyzer/IStackTraceData';
 
-import { RandomGeneratorUtils } from '../utils/RandomGeneratorUtils';
-
 /**
  * This class appends node into a first deepest BlockStatement in order of function calls
  *
@@ -97,13 +95,6 @@ export class NodeAppender {
         }
     }
 
-    /**
-     * @param stackTraceRootLength
-     */
-    public static getRandomStackTraceIndex (stackTraceRootLength: number): number {
-        return RandomGeneratorUtils.getRandomInteger(0, Math.max(0, Math.round(stackTraceRootLength - 1)));
-    }
-
     /**
      * @param blockScopeNode
      * @param nodeBodyStatements

+ 18 - 4
src/storages/ArrayStorage.ts

@@ -1,13 +1,18 @@
-import { injectable } from 'inversify';
+import { injectable, inject } from 'inversify';
+import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
 
+import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
 import { IStorage } from '../interfaces/storages/IStorage';
 
 import { initializable } from '../decorators/Initializable';
 
-import { RandomGeneratorUtils } from '../utils/RandomGeneratorUtils';
-
 @injectable()
 export abstract class ArrayStorage <T> implements IStorage <T> {
+    /**
+     * @type {IRandomGenerator}
+     */
+    protected readonly randomGenerator: IRandomGenerator;
+
     /**
      * @type {T[]}
      */
@@ -25,6 +30,15 @@ export abstract class ArrayStorage <T> implements IStorage <T> {
      */
     private storageLength: number = 0;
 
+    /**
+     * @param randomGenerator
+     */
+    constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator
+    ) {
+        this.randomGenerator = randomGenerator;
+    }
+
     /**
      * @param key
      * @returns {T}
@@ -75,7 +89,7 @@ export abstract class ArrayStorage <T> implements IStorage <T> {
      */
     public initialize (...args: any[]): void {
         this.storage = [];
-        this.storageId = RandomGeneratorUtils.getRandomString(6);
+        this.storageId = this.randomGenerator.getRandomString(6);
     }
 
     /**

+ 18 - 4
src/storages/MapStorage.ts

@@ -1,13 +1,18 @@
-import { injectable } from 'inversify';
+import { injectable, inject } from 'inversify';
+import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
 
+import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
 import { IStorage } from '../interfaces/storages/IStorage';
 
 import { initializable } from '../decorators/Initializable';
 
-import { RandomGeneratorUtils } from '../utils/RandomGeneratorUtils';
-
 @injectable()
 export abstract class MapStorage <T> implements IStorage <T> {
+    /**
+     * @type {IRandomGenerator}
+     */
+    protected readonly randomGenerator: IRandomGenerator;
+
     /**
      * @type {string}
      */
@@ -20,6 +25,15 @@ export abstract class MapStorage <T> implements IStorage <T> {
     @initializable()
     protected storage: Map <string | number, T>;
 
+    /**
+     * @param randomGenerator
+     */
+    constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator
+    ) {
+        this.randomGenerator = randomGenerator;
+    }
+
     /**
      * @param key
      * @returns {T}
@@ -74,7 +88,7 @@ export abstract class MapStorage <T> implements IStorage <T> {
      */
     public initialize (...args: any[]): void {
         this.storage = new Map <string | number, T> ();
-        this.storageId = RandomGeneratorUtils.getRandomString(6);
+        this.storageId = this.randomGenerator.getRandomString(6);
     }
 
     /**

+ 12 - 2
src/storages/control-flow/ControlFlowStorage.ts

@@ -1,10 +1,20 @@
+import { injectable, inject } from 'inversify';
+import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
+
 import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
 import { MapStorage } from '../MapStorage';
 
+@injectable()
 export class ControlFlowStorage extends MapStorage <ICustomNode> {
-    constructor () {
-        super();
+    /**
+     * @param randomGenerator
+     */
+    constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator
+    ) {
+        super(randomGenerator);
 
         this.initialize();
     }

+ 5 - 3
src/storages/custom-node-group/CustomNodeGroupStorage.ts

@@ -5,11 +5,11 @@ import { TCustomNodeGroupFactory } from '../../types/container/custom-nodes/TCus
 
 import { ICustomNodeGroup } from '../../interfaces/custom-nodes/ICustomNodeGroup';
 import { IOptions } from '../../interfaces/options/IOptions';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
 import { CustomNodeGroup } from '../../enums/container/custom-nodes/CustomNodeGroup';
 
 import { MapStorage } from '../MapStorage';
-import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
 
 @injectable()
 export class CustomNodeGroupStorage extends MapStorage <ICustomNodeGroup> {
@@ -36,13 +36,15 @@ export class CustomNodeGroupStorage extends MapStorage <ICustomNodeGroup> {
 
     /**
      * @param customNodeGroupFactory
+     * @param randomGenerator
      * @param options
      */
     constructor (
         @inject(ServiceIdentifiers.Factory__ICustomNodeGroup) customNodeGroupFactory: TCustomNodeGroupFactory,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
         @inject(ServiceIdentifiers.IOptions) options: IOptions
     ) {
-        super();
+        super(randomGenerator);
 
         this.customNodeGroupFactory = customNodeGroupFactory;
         this.options = options;
@@ -52,7 +54,7 @@ export class CustomNodeGroupStorage extends MapStorage <ICustomNodeGroup> {
 
     public initialize (): void {
         this.storage = new Map <string, ICustomNodeGroup> ();
-        this.storageId = RandomGeneratorUtils.getRandomString(6);
+        this.storageId = this.randomGenerator.getRandomString(6);
 
         CustomNodeGroupStorage.customNodeGroupsList.forEach((customNodeGroupName: CustomNodeGroup) => {
             const customNodeGroup: ICustomNodeGroup = this.customNodeGroupFactory(

+ 24 - 7
src/storages/string-array/StringArrayStorage.ts

@@ -1,13 +1,30 @@
-import { injectable } from 'inversify';
+import { injectable, inject } from 'inversify';
+import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
+
+import { IArrayUtils } from '../../interfaces/utils/IArrayUtils';
+import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 
 import { ArrayStorage } from '../ArrayStorage';
-import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
-import { Utils } from '../../utils/Utils';
+import { RandomGenerator } from '../../utils/RandomGenerator';
 
 @injectable()
 export class StringArrayStorage extends ArrayStorage <string> {
-    constructor () {
-        super();
+    /**
+     * @type {IArrayUtils}
+     */
+    private readonly arrayUtils: IArrayUtils;
+
+    /**
+     * @param arrayUtils
+     * @param randomGenerator
+     */
+    constructor (
+        @inject(ServiceIdentifiers.IArrayUtils) arrayUtils: IArrayUtils,
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator
+    ) {
+        super(randomGenerator);
+
+        this.arrayUtils = arrayUtils;
 
         this.initialize();
     }
@@ -18,14 +35,14 @@ export class StringArrayStorage extends ArrayStorage <string> {
     public initialize (...args: any[]): void {
         super.initialize(args);
 
-        this.storageId = RandomGeneratorUtils.getRandomString(4, RandomGeneratorUtils.randomGeneratorPoolHexadecimal);
+        this.storageId = this.randomGenerator.getRandomString(4, RandomGenerator.randomGeneratorPoolHexadecimal);
     }
 
     /**
      * @param rotationValue
      */
     public rotateArray (rotationValue: number): void {
-        this.storage = Utils.arrayRotate(this.storage, rotationValue);
+        this.storage = this.arrayUtils.arrayRotate(this.storage, rotationValue);
     }
 
     /**

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

@@ -1,4 +1,4 @@
-import { Utils } from '../../../../utils/Utils';
+import { IEscapeSequenceEncoder } from '../../../../interfaces/utils/IEscapeSequenceEncoder';
 
 /**
  * SelfDefendingTemplate. Enters code in infinity loop.
@@ -6,7 +6,7 @@ import { Utils } from '../../../../utils/Utils';
  *
  * @returns {string}
  */
-export function SelfDefendingTemplate (): string {
+export function SelfDefendingTemplate (escapeSequenceEncoder: IEscapeSequenceEncoder): string {
     return `
         var {selfDefendingFunctionName} = {singleNodeCallControllerFunctionName}(this, function () {
             var func1 = function(){return 'dev';},
@@ -16,7 +16,7 @@ export function SelfDefendingTemplate (): string {
                 
             var test1 = function () {
                 var regExp = new RegExp('${
-                    Utils.stringToUnicodeEscapeSequence(`\\w+ *\\(\\) *{\\w+ *['|"].+['|"];? *}`, true)
+                    escapeSequenceEncoder.encode(`\\w+ *\\(\\) *{\\w+ *['|"].+['|"];? *}`, true)
                 }');
                 
                 return !regExp.test(func1.toString());
@@ -24,7 +24,7 @@ export function SelfDefendingTemplate (): string {
             
             var test2 = function () {
                 var regExp = new RegExp('${
-                    Utils.stringToUnicodeEscapeSequence(`(\\\\[x|u](\\w){2,4})+`, true)
+                    escapeSequenceEncoder.encode(`(\\\\[x|u](\\w){2,4})+`, true)
                 }');
                 
                 return regExp.test(func2.toString());

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

@@ -1,19 +1,19 @@
-import { Utils } from '../../../../utils/Utils';
+import { IEscapeSequenceEncoder } from '../../../../interfaces/utils/IEscapeSequenceEncoder';
 
 /**
  * @returns {string}
  */
-export function SelfDefendingTemplate (): string {
+export function SelfDefendingTemplate (escapeSequenceEncoder: IEscapeSequenceEncoder): string {
     return `
         var StatesClass = function (rc4Bytes) {
             this.rc4Bytes = rc4Bytes;
             this.states = [1, 0, 0];
             this.newState = function(){return 'newState';};
             this.firstState = '${
-                Utils.stringToUnicodeEscapeSequence(`\\w+ *\\(\\) *{\\w+ *`, true)
+                escapeSequenceEncoder.encode(`\\w+ *\\(\\) *{\\w+ *`, true)
             }';
             this.secondState = '${
-                Utils.stringToUnicodeEscapeSequence(`['|"].+['|"];? *}`, true)
+                escapeSequenceEncoder.encode(`['|"].+['|"];? *}`, true)
             }';
         };
         

+ 3 - 3
src/templates/custom-nodes/string-array-nodes/string-array-rotate-function-node/SelfDefendingTemplate.ts

@@ -1,11 +1,11 @@
-import { Utils } from '../../../../utils/Utils';
+import { IEscapeSequenceEncoder } from '../../../../interfaces/utils/IEscapeSequenceEncoder';
 
 /**
  * SelfDefendingTemplate. Enter code in infinity loop.
  *
  * @returns {string}
  */
-export function SelfDefendingTemplate (): string {
+export function SelfDefendingTemplate (escapeSequenceEncoder: IEscapeSequenceEncoder): string {
     return `
         var selfDefendingFunc = function () {            
             var object = {
@@ -56,7 +56,7 @@ export function SelfDefendingTemplate (): string {
             
             var test1 = function () {
                 var regExp = new RegExp('${
-                    Utils.stringToUnicodeEscapeSequence(`\\w+ *\\(\\) *{\\w+ *['|"].+['|"];? *}`, true)
+                    escapeSequenceEncoder.encode(`\\w+ *\\(\\) *{\\w+ *['|"].+['|"];? *}`, true)
                 }');
                 
                 return regExp.test(object.removeCookie.toString());

+ 6 - 0
src/types/container/custom-nodes/TControlFlowCustomNodeFactory.d.ts

@@ -0,0 +1,6 @@
+import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
+
+import { ControlFlowCustomNode } from '../../../enums/container/custom-nodes/ControlFlowCustomNode';
+
+export type TControlFlowCustomNodeFactory = (controlFlowCustomNodeName: ControlFlowCustomNode) => ICustomNode;
+

+ 78 - 0
src/utils/ArrayUtils.ts

@@ -0,0 +1,78 @@
+import { injectable, inject } from 'inversify';
+import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
+
+import { IArrayUtils } from '../interfaces/utils/IArrayUtils';
+import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
+
+@injectable()
+export class ArrayUtils implements IArrayUtils {
+    /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param randomGenerator
+     */
+    constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator
+    ) {
+        this.randomGenerator = randomGenerator;
+    }
+
+    /**
+     * @param length
+     * @return {number[]}
+     */
+    public arrayRange (length: number): number[] {
+        const range: number[] = [];
+
+        for (let i: number = 0; i < length; i++) {
+            range.push(i);
+        }
+
+        return range;
+    }
+
+    /**
+     * @param array
+     * @param times
+     * @returns {T[]}
+     */
+    public arrayRotate <T> (array: T[], times: number): T[] {
+        if (!array.length) {
+            throw new ReferenceError(`Cannot rotate empty array.`);
+        }
+
+        if (times <= 0) {
+            return array;
+        }
+
+        const newArray: T[] = array;
+
+        let temp: T | undefined;
+
+        while (times--) {
+            temp = newArray.pop()!;
+            newArray.unshift(temp);
+        }
+
+        return newArray;
+    }
+
+    /**
+     * @param array
+     * @return {T[]}
+     */
+    public arrayShuffle <T> (array: T[]): T[] {
+        const shuffledArray: T[] = [...array];
+
+        for (let i: number = shuffledArray.length; i; i--) {
+            const j: number = Math.floor(this.randomGenerator.getMathRandom() * i);
+
+            [shuffledArray[i - 1], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i - 1]];
+        }
+
+        return shuffledArray;
+    }
+}

+ 31 - 10
src/utils/CryptUtils.ts

@@ -1,12 +1,33 @@
-import { RandomGeneratorUtils } from './RandomGeneratorUtils';
+import { injectable, inject } from 'inversify';
+import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
+
+import { ICryptUtils } from '../interfaces/utils/ICryptUtils';
+import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
+
+import { RandomGenerator } from './RandomGenerator';
 import { Utils } from './Utils';
 
-export class CryptUtils {
+@injectable()
+export class CryptUtils implements ICryptUtils {
+    /**
+     * @type {IRandomGenerator}
+     */
+    private readonly randomGenerator: IRandomGenerator;
+
+    /**
+     * @param randomGenerator
+     */
+    constructor (
+        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator
+    ) {
+        this.randomGenerator = randomGenerator;
+    }
+
     /**
      * @param string
      */
     /* tslint:disable */
-    public static btoa (string: string): string {
+    public btoa (string: string): string {
         const chars: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
 
         let output: string = '';
@@ -36,9 +57,9 @@ export class CryptUtils {
     /**
      * @param str
      * @param length
-     * @returns {string[]}
+     * @returns {[string, string]}
      */
-    public static hideString (str: string, length: number): [string, string] {
+    public hideString (str: string, length: number): [string, string] {
         const escapeRegExp: (s: string) => string = (s: string) =>
             s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
 
@@ -48,7 +69,7 @@ export class CryptUtils {
                 result: string = '';
 
             while (i1 < s1.length || i2 < s2.length) {
-                if (RandomGeneratorUtils.getMathRandom() < 0.5 && i2 < s2.length) {
+                if (this.randomGenerator.getMathRandom() < 0.5 && i2 < s2.length) {
                     result += s2.charAt(++i2);
                 } else {
                     result += s1.charAt(++i1);
@@ -58,9 +79,9 @@ export class CryptUtils {
             return result;
         };
 
-        const randomString: string = RandomGeneratorUtils.getRandomGenerator().string({
+        const randomString: string = this.randomGenerator.getRandomGenerator().string({
             length: length,
-            pool: RandomGeneratorUtils.randomGeneratorPool
+            pool: RandomGenerator.randomGeneratorPool
         });
 
         let randomStringDiff: string = randomString.replace(
@@ -69,7 +90,7 @@ export class CryptUtils {
 
         const randomStringDiffArray: string[] = randomStringDiff.split('');
 
-        RandomGeneratorUtils.getRandomGenerator().shuffle(randomStringDiffArray);
+        this.randomGenerator.getRandomGenerator().shuffle(randomStringDiffArray);
         randomStringDiff = randomStringDiffArray.join('');
 
         return [randomMerge(str, randomStringDiff), randomStringDiff];
@@ -84,7 +105,7 @@ export class CryptUtils {
      * @returns {string}
      */
     /* tslint:disable */
-    public static rc4 (string: string, key: string): string {
+    public rc4 (string: string, key: string): string {
         let s: number[] = [],
             j: number = 0,
             x: number,

+ 52 - 0
src/utils/EscapeSequenceEncoder.ts

@@ -0,0 +1,52 @@
+import { injectable } from 'inversify';
+
+import { IEscapeSequenceEncoder } from '../interfaces/utils/IEscapeSequenceEncoder';
+
+@injectable()
+export class EscapeSequenceEncoder implements IEscapeSequenceEncoder {
+    /**
+     * @type {Map<string, string>}
+     */
+    private readonly stringsCache: Map <string, string> = new Map();
+
+    /**
+     * @param string
+     * @param encodeAllSymbols
+     * @returns {string}
+     */
+    public encode (string: string, encodeAllSymbols: boolean): string {
+        const cacheKey: string = `${string}-${String(encodeAllSymbols)}`;
+
+        if (this.stringsCache.has(cacheKey)) {
+            return <string>this.stringsCache.get(cacheKey);
+        }
+
+        const radix: number = 16;
+        const replaceRegExp: RegExp = new RegExp('[\\s\\S]', 'g');
+        const escapeSequenceRegExp: RegExp = new RegExp('[\'\"\\\\\\s]');
+        const regExp: RegExp = new RegExp('[\\x00-\\x7F]');
+
+        let prefix: string,
+            template: string;
+
+        const result: string = string.replace(replaceRegExp, (character: string): string => {
+            if (!encodeAllSymbols && !escapeSequenceRegExp.exec(character)) {
+                return character;
+            }
+
+            if (regExp.exec(character)) {
+                prefix = '\\x';
+                template = '00';
+            } else {
+                prefix = '\\u';
+                template = '0000';
+            }
+
+            return `${prefix}${(template + character.charCodeAt(0).toString(radix)).slice(-template.length)}`;
+        });
+
+        this.stringsCache.set(cacheKey, result);
+
+        return result;
+    }
+}

+ 125 - 0
src/utils/RandomGenerator.ts

@@ -0,0 +1,125 @@
+import { inject, injectable } from 'inversify';
+import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
+
+import { Chance } from 'chance';
+
+import { IOptions } from '../interfaces/options/IOptions';
+import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
+
+import { Utils } from './Utils';
+
+@injectable()
+export class RandomGenerator implements IRandomGenerator {
+    /**
+     * @type {string}
+     */
+    public static readonly randomGeneratorPool: string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+
+    /**
+     * @type {string}
+     */
+    public static readonly randomGeneratorPoolNumbers: string = '0123456789';
+
+    /**
+     * @type {string}
+     */
+    public static readonly randomGeneratorPoolHexadecimal: string = `abcdef${RandomGenerator.randomGeneratorPoolNumbers}`;
+
+    /**
+     * @type {IOptions}
+     */
+    private readonly options: IOptions;
+
+    /**
+     * @type {Set<string>}
+     */
+    private readonly randomVariableNameSet: Set <string> = new Set();
+
+    /**
+     * @type {Chance.Chance | Chance.SeededChance}
+     */
+    private readonly randomGenerator: Chance.Chance | Chance.SeededChance;
+
+    /**
+     * @param options
+     */
+    constructor (
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        this.options = options;
+        this.randomGenerator = options.seed !== 0
+            ? new Chance(options.seed)
+            : new Chance();
+    }
+
+    /**
+     * @returns {number}
+     */
+    public getMathRandom (): number {
+        return this.getRandomInteger(0, 99999) / 100000;
+    }
+
+    /**
+     * @param min
+     * @param max
+     * @returns {number}
+     */
+    public getRandomFloat (min: number, max: number): number {
+        return this.getRandomGenerator().floating({
+            min: min,
+            max: max,
+            fixed: 7
+        });
+    }
+
+    /**
+     * @returns {Chance.Chance}
+     */
+    public getRandomGenerator (): Chance.Chance {
+        return this.randomGenerator;
+    }
+
+    /**
+     * @param min
+     * @param max
+     * @returns {number}
+     */
+    public getRandomInteger (min: number, max: number): number {
+        return this.getRandomGenerator().integer({
+            min: min,
+            max: max
+        });
+    }
+
+    /**
+     * @param length
+     * @param pool
+     * @returns {string}
+     */
+    public getRandomString (length: number, pool: string = RandomGenerator.randomGeneratorPool): string {
+        return this.getRandomGenerator().string({ length, pool });
+    }
+
+    /**
+     * @param length
+     * @returns {string}
+     */
+    public getRandomVariableName (length: number): string {
+        const prefix: string = `_${Utils.hexadecimalPrefix}`;
+        const rangeMinInteger: number = 10000;
+        const rangeMaxInteger: number = 99999999;
+        const randomVariableName: string = `${prefix}${(
+            Utils.decToHex(
+                this.getRandomInteger(rangeMinInteger, rangeMaxInteger)
+            )
+        ).substr(0, length)}`;
+
+        if (this.randomVariableNameSet.has(randomVariableName)) {
+            return this.getRandomVariableName(length);
+        }
+
+        this.randomVariableNameSet.add(randomVariableName);
+
+        return randomVariableName;
+    }
+}

+ 0 - 127
src/utils/RandomGeneratorUtils.ts

@@ -1,127 +0,0 @@
-import { Chance } from 'chance';
-
-import { Utils } from './Utils';
-
-export class RandomGeneratorUtils {
-    /**
-     * @type {string}
-     */
-    public static readonly randomGeneratorPool: string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
-
-    /**
-     * @type {string}
-     */
-    public static readonly randomGeneratorPoolNumbers: string = '0123456789';
-
-    /**
-     * @type {string}
-     */
-    public static readonly randomGeneratorPoolHexadecimal: string = `abcdef${RandomGeneratorUtils.randomGeneratorPoolNumbers}`;
-
-    /**
-     * @type {string}
-     */
-    public static readonly randomGeneratorPoolWithNumbers: string = `${RandomGeneratorUtils.randomGeneratorPool}${RandomGeneratorUtils.randomGeneratorPoolNumbers}`;
-
-    /**
-     * @type {Set<string>}
-     */
-    public static readonly randomVariableNameSet: Set <string> = new Set();
-
-    /**
-     * @type {Chance.Chance | Chance.SeededChance}
-     */
-    private static randomGenerator: Chance.Chance | Chance.SeededChance;
-
-    /**
-     * @param seed
-     */
-    public static initializeRandomGenerator (seed: number): void {
-        if (seed !== 0) {
-            RandomGeneratorUtils.randomGenerator = new Chance(seed);
-        } else {
-            RandomGeneratorUtils.randomGenerator = new Chance();
-        }
-    }
-
-    public static clearRandomGenerator (): void {
-        RandomGeneratorUtils.randomVariableNameSet.clear();
-    }
-
-    /**
-     * @returns {number}
-     */
-    public static getMathRandom (): number {
-        return RandomGeneratorUtils.getRandomInteger(0, 99999) / 100000;
-    }
-
-    /**
-     * @param min
-     * @param max
-     * @returns {number}
-     */
-    public static getRandomFloat (min: number, max: number): number {
-        return RandomGeneratorUtils.getRandomGenerator().floating({
-            min: min,
-            max: max,
-            fixed: 7
-        });
-    }
-
-    /**
-     * @returns {Chance.Chance}
-     */
-    public static getRandomGenerator (): Chance.Chance {
-        const randomGenerator: Chance.Chance = RandomGeneratorUtils.randomGenerator;
-
-        if (!randomGenerator) {
-            RandomGeneratorUtils.initializeRandomGenerator(0);
-        }
-
-        return RandomGeneratorUtils.randomGenerator;
-    }
-
-    /**
-     * @param min
-     * @param max
-     * @returns {number}
-     */
-    public static getRandomInteger (min: number, max: number): number {
-        return RandomGeneratorUtils.getRandomGenerator().integer({
-            min: min,
-            max: max
-        });
-    }
-
-    /**
-     * @param length
-     * @param pool
-     * @returns {string}
-     */
-    public static getRandomString (length: number, pool: string = RandomGeneratorUtils.randomGeneratorPool): string {
-        return RandomGeneratorUtils.getRandomGenerator().string({ length, pool });
-    }
-
-    /**
-     * @param length
-     * @returns {string}
-     */
-    public static getRandomVariableName (length: number): string {
-        const prefix: string = `_${Utils.hexadecimalPrefix}`;
-        const rangeMinInteger: number = 10000;
-        const rangeMaxInteger: number = 99999999;
-        const randomVariableName: string = `${prefix}${(
-            Utils.decToHex(
-                RandomGeneratorUtils.getRandomInteger(rangeMinInteger, rangeMaxInteger)
-            )
-        ).substr(0, length)}`;
-
-        if (RandomGeneratorUtils.randomVariableNameSet.has(randomVariableName)) {
-            return RandomGeneratorUtils.getRandomVariableName(length);
-        }
-
-        RandomGeneratorUtils.randomVariableNameSet.add(randomVariableName);
-
-        return randomVariableName;
-    }
-}

+ 0 - 112
src/utils/Utils.ts

@@ -1,74 +1,11 @@
 import { JSFuck } from '../enums/JSFuck';
 
-import { RandomGeneratorUtils } from './RandomGeneratorUtils';
-
 export class Utils {
     /**
      * @type {string}
      */
     public static readonly hexadecimalPrefix: string = '0x';
 
-    /**
-     * @type {Map<string, string>}
-     */
-    private static readonly stringToUnicodeEscapeSequenceCache: Map <string, string> = new Map();
-
-    /**
-     * @param length
-     * @return {number[]}
-     */
-    public static arrayRange (length: number): number[] {
-        const range: number[] = [];
-
-        for (let i: number = 0; i < length; i++) {
-            range.push(i);
-        }
-
-        return range;
-    }
-
-    /**
-     * @param array
-     * @param times
-     * @returns {T[]}
-     */
-    public static arrayRotate <T> (array: T[], times: number): T[] {
-        if (!array.length) {
-            throw new ReferenceError(`Cannot rotate empty array.`);
-        }
-
-        if (times <= 0) {
-            return array;
-        }
-
-        const newArray: T[] = array;
-
-        let temp: T | undefined;
-
-        while (times--) {
-            temp = newArray.pop()!;
-            newArray.unshift(temp);
-        }
-
-        return newArray;
-    }
-
-    /**
-     * @param array
-     * @return {T[]}
-     */
-    public static arrayShuffle <T> (array: T[]): T[] {
-        const shuffledArray: T[] = [...array];
-
-        for (let i: number = shuffledArray.length; i; i--) {
-            const j: number = Math.floor(RandomGeneratorUtils.getMathRandom() * i);
-
-            [shuffledArray[i - 1], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i - 1]];
-        }
-
-        return shuffledArray;
-    }
-
     /**
      * @param dec
      * @returns {string}
@@ -105,14 +42,6 @@ export class Utils {
         return number % 1 === 0;
     }
 
-    /**
-     * @param obj
-     * @returns {T}
-     */
-    public static strEnumify <T extends {[prop: string]: ''|string}> (obj: T): T {
-        return obj;
-    }
-
     /**
      * @param string
      * @param times
@@ -142,45 +71,4 @@ export class Utils {
             })
             .join(' + ');
     }
-
-    /**
-     * @param string
-     * @param usingUnicodeEscapeSequence
-     * @returns {string}
-     */
-    public static stringToUnicodeEscapeSequence (string: string, usingUnicodeEscapeSequence: boolean): string {
-        const cacheKey: string = `${string}-${String(usingUnicodeEscapeSequence)}`;
-
-        if (Utils.stringToUnicodeEscapeSequenceCache.has(cacheKey)) {
-            return <string>Utils.stringToUnicodeEscapeSequenceCache.get(cacheKey);
-        }
-
-        const radix: number = 16;
-        const replaceRegExp: RegExp = new RegExp('[\\s\\S]', 'g');
-        const escapeSequenceRegExp: RegExp = new RegExp('[\'\"\\\\\\s]');
-        const regExp: RegExp = new RegExp('[\\x00-\\x7F]');
-
-        let prefix: string,
-            template: string;
-
-        const result: string = string.replace(replaceRegExp, (character: string): string => {
-            if (!usingUnicodeEscapeSequence && !escapeSequenceRegExp.exec(character)) {
-                return character;
-            }
-
-            if (regExp.exec(character)) {
-                prefix = '\\x';
-                template = '00';
-            } else {
-                prefix = '\\u';
-                template = '0000';
-            }
-
-            return `${prefix}${(template + character.charCodeAt(0).toString(radix)).slice(-template.length)}`;
-        });
-
-        Utils.stringToUnicodeEscapeSequenceCache.set(cacheKey, result);
-
-        return result;
-    }
 }

+ 7 - 4
test/functional-tests/javascript-obfuscator-internal/JavaScriptObfuscatorInternal.spec.ts

@@ -15,8 +15,7 @@ describe('JavaScriptObfuscatorInternal', () => {
         const code: string = 'var test = 1;';
         const sourceMapUrl: string = 'test.js.map';
 
-        let inversifyContainerFacade: IInversifyContainerFacade,
-            javaScriptObfuscator: IJavaScriptObfuscator;
+        let javaScriptObfuscator: IJavaScriptObfuscator;
 
         describe('variant #1: default behaviour', () => {
             const regExp: RegExp = new RegExp(`sourceMappingURL=${sourceMapUrl}`);
@@ -25,7 +24,9 @@ describe('JavaScriptObfuscatorInternal', () => {
                 sourceMapObject: any;
 
             before(() => {
-                inversifyContainerFacade = new InversifyContainerFacade({
+                const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
+
+                inversifyContainerFacade.load({
                     ...NO_CUSTOM_NODES_PRESET,
                     sourceMap: true,
                     sourceMapFileName: sourceMapUrl
@@ -56,7 +57,9 @@ describe('JavaScriptObfuscatorInternal', () => {
                 sourceMapObject: any;
 
             before(() => {
-                inversifyContainerFacade = new InversifyContainerFacade({
+                const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
+
+                inversifyContainerFacade.load({
                     ...NO_CUSTOM_NODES_PRESET,
                     sourceMap: true,
                     sourceMapBaseUrl: sourceMapBaseUrl,

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

@@ -8,14 +8,8 @@ import { NO_CUSTOM_NODES_PRESET } from '../../../src/options/presets/NoCustomNod
 
 import { readFileAsString } from '../../helpers/readFileAsString';
 
-import { RandomGeneratorUtils } from '../../../src/utils/RandomGeneratorUtils';
-
 describe('JavaScriptObfuscator', () => {
     describe('obfuscate (sourceCode: string, customOptions?: IObfuscatorOptions): IObfuscationResult', () => {
-        beforeEach(() => {
-            RandomGeneratorUtils.initializeRandomGenerator(0);
-        });
-
         describe('correct source code', () => {
             let obfuscatedCode: string,
                 sourceMap: string;
@@ -429,9 +423,5 @@ describe('JavaScriptObfuscator', () => {
                 assert.match(obfuscatedCode, regExp);
             });
         });
-
-        afterEach(() => {
-            RandomGeneratorUtils.initializeRandomGenerator(0);
-        });
     });
 });

+ 10 - 5
test/functional-tests/stack-trace-analyzer/stack-trace-analyzer/StackTraceAnalyzer.spec.ts

@@ -148,13 +148,18 @@ function getObjectFunctionExpressionByName (astTree: ESTree.Node, objectName: st
 
 describe('StackTraceAnalyzer', () => {
     describe('extract (): IStackTraceData[]', () => {
-        const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade({});
-        const stackTraceAnalyzer: IStackTraceAnalyzer = inversifyContainerFacade
-            .get<IStackTraceAnalyzer>(ServiceIdentifiers.IStackTraceAnalyzer);
-
-        let expectedStackTraceData: IStackTraceData[],
+        let stackTraceAnalyzer: IStackTraceAnalyzer,
+            expectedStackTraceData: IStackTraceData[],
             stackTraceData: IStackTraceData[];
 
+        before(() => {
+            const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
+
+            inversifyContainerFacade.load({});
+            stackTraceAnalyzer = inversifyContainerFacade
+                .get<IStackTraceAnalyzer>(ServiceIdentifiers.IStackTraceAnalyzer);
+        });
+
         describe('variant #1: basic-1', () => {
             before(() => {
                 const code: string = readFileAsString(__dirname + '/fixtures/basic-1.js');

+ 18 - 4
test/functional-tests/templates/custom-nodes/domain-lock-nodes/DomainLockNodeTemplate.spec.ts

@@ -2,9 +2,14 @@ import * as format from 'string-template';
 
 import { assert } from 'chai';
 
+import { ServiceIdentifiers } from '../../../../../src/container/ServiceIdentifiers';
+
+import { ICryptUtils } from '../../../../../src/interfaces/utils/ICryptUtils';
+import { IInversifyContainerFacade } from '../../../../../src/interfaces/container/IInversifyContainerFacade';
+
 import { DomainLockNodeTemplate } from '../../../../../src/templates/custom-nodes/domain-lock-nodes/domain-lock-node/DomainLockNodeTemplate';
 
-import { CryptUtils } from '../../../../../src/utils/CryptUtils';
+import { InversifyContainerFacade } from '../../../../../src/container/InversifyContainerFacade';
 
 /**
  * @param templateData
@@ -35,6 +40,15 @@ function getFunctionFromTemplate (templateData: any, callsControllerFunctionName
 describe('DomainLockNodeTemplate (): string', () => {
     const singleNodeCallControllerFunctionName: string = 'callsController';
 
+    let cryptUtils: ICryptUtils;
+
+    before(() => {
+        const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
+
+        inversifyContainerFacade.load({});
+        cryptUtils = inversifyContainerFacade.get<ICryptUtils>(ServiceIdentifiers.ICryptUtils);
+    });
+
     describe('variant #1: current domain matches with `domainsString`', () => {
         const domainsString: string = ['www.example.com'].join(';');
         const currentDomain: string = 'www.example.com';
@@ -45,7 +59,7 @@ describe('DomainLockNodeTemplate (): string', () => {
             const [
                 hiddenDomainsString,
                 diff
-            ] = CryptUtils.hideString(domainsString, domainsString.length * 3);
+            ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
             testFunc = () => getFunctionFromTemplate({
                 domainLockFunctionName: 'domainLockFunction',
@@ -70,7 +84,7 @@ describe('DomainLockNodeTemplate (): string', () => {
             const [
                 hiddenDomainsString,
                 diff
-            ] = CryptUtils.hideString(domainsString, domainsString.length * 3);
+            ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
             testFunc = () => getFunctionFromTemplate({
                 domainLockFunctionName: 'domainLockFunction',
@@ -95,7 +109,7 @@ describe('DomainLockNodeTemplate (): string', () => {
             const [
                 hiddenDomainsString,
                 diff
-            ] = CryptUtils.hideString(domainsString, domainsString.length * 3);
+            ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
 
             testFunc = () => getFunctionFromTemplate({
                 domainLockFunctionName: 'domainLockFunction',

+ 35 - 55
test/functional-tests/templates/custom-nodes/string-array-nodes/StringArrayCallsWrapperNodeTemplate.spec.ts

@@ -2,68 +2,32 @@ import * as format from 'string-template';
 
 import { assert } from 'chai';
 
+import { ServiceIdentifiers } from '../../../../../src/container/ServiceIdentifiers';
+
+import { ICryptUtils } from '../../../../../src/interfaces/utils/ICryptUtils';
+import { IInversifyContainerFacade } from '../../../../../src/interfaces/container/IInversifyContainerFacade';
+
 import { AtobTemplate } from '../../../../../src/templates/custom-nodes/AtobTemplate';
 import { Rc4Template } from '../../../../../src/templates/custom-nodes/Rc4Template';
 import { StringArrayBase64DecodeNodeTemplate } from '../../../../../src/templates/custom-nodes/string-array-nodes/string-array-calls-wrapper/StringArrayBase64DecodeNodeTemplate';
 import { StringArrayCallsWrapperTemplate } from '../../../../../src/templates/custom-nodes/string-array-nodes/string-array-calls-wrapper/StringArrayCallsWrapperTemplate';
 import { StringArrayRc4DecodeNodeTemplate } from '../../../../../src/templates/custom-nodes/string-array-nodes/string-array-calls-wrapper/StringArrayRC4DecodeNodeTemplate';
 
-import { CryptUtils } from '../../../../../src/utils/CryptUtils';
-
-/**
- * @param templateData
- * @param stringArrayName
- * @param stringArrayCallsWrapperName
- * @param index
- * @returns {Function}
- */
-function getFunctionFromTemplateBase64Encoding (
-    templateData: any,
-    stringArrayName: string,
-    stringArrayCallsWrapperName: string,
-    index: string
-) {
-    const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), templateData);
-
-    return Function(`
-        var ${stringArrayName} = ['${CryptUtils.btoa('test1')}'];
-    
-        ${stringArrayCallsWrapperTemplate}
-        
-        return ${stringArrayCallsWrapperName}(${index});
-    `)();
-}
-
-/**
- * @param templateData
- * @param stringArrayName
- * @param stringArrayCallsWrapperName
- * @param index
- * @param key
- * @returns {Function}
- */
-function getFunctionFromTemplateRc4Encoding (
-    templateData: any,
-    stringArrayName: string,
-    stringArrayCallsWrapperName: string,
-    index: string,
-    key: string
-) {
-    const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), templateData);
-
-    return Function(`
-        var ${stringArrayName} = ['${CryptUtils.btoa(CryptUtils.rc4('test1', key))}'];
-    
-        ${stringArrayCallsWrapperTemplate}
-        
-        return ${stringArrayCallsWrapperName}('${index}', '${key}');
-    `)();
-}
+import { InversifyContainerFacade } from '../../../../../src/container/InversifyContainerFacade';
 
 describe('StringArrayCallsWrapperNodeTemplate (): string', () => {
     const stringArrayName: string = 'stringArrayName';
     const stringArrayCallsWrapperName: string = 'stringArrayCallsWrapperName';
 
+    let cryptUtils: ICryptUtils;
+
+    before(() => {
+        const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
+
+        inversifyContainerFacade.load({});
+        cryptUtils = inversifyContainerFacade.get<ICryptUtils>(ServiceIdentifiers.ICryptUtils);
+    });
+
     describe('variant #1: `base64` encoding', () => {
         const atobDecodeNodeTemplate: string = format(StringArrayBase64DecodeNodeTemplate(), {
             atobPolyfill: AtobTemplate(),
@@ -76,11 +40,19 @@ describe('StringArrayCallsWrapperNodeTemplate (): string', () => {
         let decodedValue: string;
 
         before(() => {
-            decodedValue = getFunctionFromTemplateBase64Encoding({
+            const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
                 decodeNodeTemplate: atobDecodeNodeTemplate,
                 stringArrayCallsWrapperName,
                 stringArrayName
-            }, stringArrayName, stringArrayCallsWrapperName, index);
+            });
+
+            decodedValue = Function(`
+                var ${stringArrayName} = ['${cryptUtils.btoa('test1')}'];
+            
+                ${stringArrayCallsWrapperTemplate}
+                
+                return ${stringArrayCallsWrapperName}(${index});
+            `)();
         });
 
         it('should correctly return decoded value', () => {
@@ -102,11 +74,19 @@ describe('StringArrayCallsWrapperNodeTemplate (): string', () => {
         let decodedValue: string;
 
         before(() => {
-            decodedValue = getFunctionFromTemplateRc4Encoding({
+            const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
                 decodeNodeTemplate: rc4DecodeNodeTemplate,
                 stringArrayCallsWrapperName,
                 stringArrayName
-            }, stringArrayName, stringArrayCallsWrapperName, index, key);
+            });
+
+            decodedValue = Function(`
+                var ${stringArrayName} = ['${cryptUtils.btoa(cryptUtils.rc4('test1', key))}'];
+            
+                ${stringArrayCallsWrapperTemplate}
+                
+                return ${stringArrayCallsWrapperName}('${index}', '${key}');
+            `)();
         });
 
         it('should correctly return decoded value', () => {

+ 5 - 3
test/index.spec.ts

@@ -15,9 +15,11 @@ import './unit-tests/source-map-corrector/SourceMapCorrector.spec';
 import './unit-tests/stack-trace-analyzer/stack-trace-analyzer/StackTraceAnalyzer.spec';
 import './unit-tests/storages/ArrayStorage.spec';
 import './unit-tests/storages/MapStorage.spec';
-import './unit-tests/utils/crypt-utils/CryptUtils.spec';
-import './unit-tests/utils/random-generator-utils/RandomGeneratorUtils.spec';
-import './unit-tests/utils/utils/Utils.spec';
+import './unit-tests/utils/ArrayUtils.spec';
+import './unit-tests/utils/CryptUtils.spec';
+import './unit-tests/utils/RandomGeneratorUtils.spec';
+import './unit-tests/utils/EscapeSequenceEncoder.spec';
+import './unit-tests/utils/Utils.spec';
 
 /**
  * Functional tests

+ 11 - 19
test/unit-tests/node/node-appender/NodeAppender.spec.ts

@@ -58,15 +58,20 @@ describe('NodeAppender', () => {
     });
 
     describe('appendNodeToOptimalBlockScope (blockScopeStackTraceData: IStackTraceData[], blockScopeNode: TNodeWithBlockStatement, nodeBodyStatements: TStatement[], index: number = 0): void', () => {
-        const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade({});
-        const stackTraceAnalyzer: IStackTraceAnalyzer = inversifyContainerFacade
-            .get<IStackTraceAnalyzer>(ServiceIdentifiers.IStackTraceAnalyzer);
-
-        let astTree: ESTree.Program,
+        let stackTraceAnalyzer: IStackTraceAnalyzer,
+            astTree: ESTree.Program,
             expectedAstTree: ESTree.Program,
             node: TStatement[],
             stackTraceData: IStackTraceData[];
 
+        before(() => {
+            const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
+
+            inversifyContainerFacade.load({});
+            stackTraceAnalyzer = inversifyContainerFacade
+                .get<IStackTraceAnalyzer>(ServiceIdentifiers.IStackTraceAnalyzer);
+        });
+
         beforeEach(() => {
             node = convertCodeToStructure('/fixtures/simple-input.js');
         });
@@ -145,7 +150,7 @@ describe('NodeAppender', () => {
                         stackTraceData,
                         astTree,
                         node,
-                        NodeAppender.getRandomStackTraceIndex(stackTraceData.length)
+                        stackTraceData.length - 1
                     );
 
                 });
@@ -157,19 +162,6 @@ describe('NodeAppender', () => {
         });
     });
 
-    describe('getRandomStackTraceIndex (stackTraceRootLength: number): number', () => {
-        it('should return random index between 0 and stack trace data root length', () => {
-            let index: number;
-
-            for (let i: number = 0; i < 100; i++) {
-                index = NodeAppender.getRandomStackTraceIndex(100);
-
-                assert.isAtLeast(index, 0);
-                assert.isAtMost(index, 100);
-            }
-        });
-    });
-
     describe('insertNodeAtIndex (blockScopeNode: TNodeWithBlockStatement[], nodeBodyStatements: TStatement[], index: number): void', () => {
         let astTree: ESTree.Program,
             expectedAstTree: ESTree.Program,

+ 4 - 1
test/unit-tests/source-map-corrector/SourceMapCorrector.spec.ts

@@ -26,12 +26,15 @@ function getCorrectedObfuscationResult (
     sourceMapFileName: string,
     sourceMapMode: TSourceMapMode
 ): IObfuscationResult {
-    const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade({
+    const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
+
+    inversifyContainerFacade.load({
         sourceMap: true,
         sourceMapBaseUrl: sourceMapBaseUrl,
         sourceMapFileName: sourceMapFileName,
         sourceMapMode: sourceMapMode
     });
+
     const sourceMapCorrector: ISourceMapCorrector = inversifyContainerFacade
         .get<ISourceMapCorrector>(ServiceIdentifiers.ISourceMapCorrector);
 

+ 10 - 1
test/unit-tests/storages/ArrayStorage.spec.ts

@@ -1,12 +1,21 @@
 import { assert } from 'chai';
 
+import { ServiceIdentifiers } from '../../../src/container/ServiceIdentifiers';
+
+import { IInversifyContainerFacade } from '../../../src/interfaces/container/IInversifyContainerFacade';
+import { IRandomGenerator } from '../../../src/interfaces/utils/IRandomGenerator';
 import { IStorage } from '../../../src/interfaces/storages/IStorage';
 
 import { ArrayStorage } from '../../../src/storages/ArrayStorage';
+import { InversifyContainerFacade } from '../../../src/container/InversifyContainerFacade';
 
 class ConcreteStorage extends ArrayStorage <string> {
     constructor () {
-        super();
+        const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
+
+        inversifyContainerFacade.load({});
+
+        super(inversifyContainerFacade.get<IRandomGenerator>(ServiceIdentifiers.IRandomGenerator));
     }
 }
 

+ 10 - 1
test/unit-tests/storages/MapStorage.spec.ts

@@ -1,12 +1,21 @@
 import { assert } from 'chai';
 
+import { ServiceIdentifiers } from '../../../src/container/ServiceIdentifiers';
+
+import { IInversifyContainerFacade } from '../../../src/interfaces/container/IInversifyContainerFacade';
+import { IRandomGenerator } from '../../../src/interfaces/utils/IRandomGenerator';
 import { IStorage } from '../../../src/interfaces/storages/IStorage';
 
+import { InversifyContainerFacade } from '../../../src/container/InversifyContainerFacade';
 import { MapStorage } from '../../../src/storages/MapStorage';
 
 class ConcreteStorage extends MapStorage <string> {
     constructor () {
-        super();
+        const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
+
+        inversifyContainerFacade.load({});
+
+        super(inversifyContainerFacade.get<IRandomGenerator>(ServiceIdentifiers.IRandomGenerator));
     }
 }
 

+ 117 - 0
test/unit-tests/utils/ArrayUtils.spec.ts

@@ -0,0 +1,117 @@
+import { assert } from 'chai';
+
+import { ServiceIdentifiers } from '../../../src/container/ServiceIdentifiers';
+
+import { IArrayUtils } from '../../../src/interfaces/utils/IArrayUtils';
+import { IInversifyContainerFacade } from '../../../src/interfaces/container/IInversifyContainerFacade';
+
+import { InversifyContainerFacade } from '../../../src/container/InversifyContainerFacade';
+
+describe('Utils', () => {
+    let arrayUtils: IArrayUtils;
+
+    before(() => {
+        const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
+
+        inversifyContainerFacade.load({});
+        arrayUtils = inversifyContainerFacade.get<IArrayUtils>(ServiceIdentifiers.IArrayUtils);
+    });
+
+    describe('arrayRange (length: number): number[]', () => {
+        describe('range length more than 0', () => {
+            const rangeLength: number = 5;
+            const expectedArray: number[] = [0, 1, 2, 3, 4];
+
+            let array: number[];
+
+            before(() => {
+                array = arrayUtils.arrayRange(rangeLength);
+            });
+
+            it('should return array with range of numbers', () => {
+                assert.deepEqual(array, expectedArray);
+            });
+        });
+
+        describe('range length is 0', () => {
+            const rangeLength: number = 0;
+            const expectedArray: number[] = [];
+
+            let array: number[];
+
+            before(() => {
+                array = arrayUtils.arrayRange(rangeLength);
+            });
+
+            it('should return empty array', () => {
+                assert.deepEqual(array, expectedArray);
+            });
+        });
+
+        describe('range length less than 0', () => {
+            const rangeLength: number = -5;
+            const expectedArray: number[] = [];
+
+            let array: number[];
+
+            before(() => {
+                array = arrayUtils.arrayRange(rangeLength);
+            });
+
+            it('should return empty array', () => {
+                assert.deepEqual(array, expectedArray);
+            });
+        });
+    });
+
+    describe('arrayRotate <T> (array: T[], times: number): T[]', () => {
+        let array: number[],
+            rotatedArray: number[];
+
+        beforeEach(() => {
+            array = [1, 2, 3, 4, 5, 6];
+        });
+
+        describe('value is not 0', () => {
+            const rotateValue: number = 2;
+            const expectedArray: number[] = [5, 6, 1, 2, 3, 4];
+
+            beforeEach(() => {
+                rotatedArray = arrayUtils.arrayRotate(array, rotateValue);
+            });
+
+            it('should rotate (shift) array by a given value', () => {
+                assert.deepEqual(rotatedArray, expectedArray);
+            });
+        });
+
+        describe('value equals or less 0', () => {
+            const rotateValue: number = 0;
+            const expectedArray: number[] = [1, 2, 3, 4, 5, 6];
+
+            beforeEach(() => {
+                rotatedArray = arrayUtils.arrayRotate(array, rotateValue);
+            });
+
+            it('shouldn\'t rotate array', () => {
+                assert.deepEqual(rotatedArray, expectedArray);
+            });
+        });
+
+        describe('empty array', () => {
+            const emptyArray: number[] = [];
+            const rotateValue: number = 5;
+            const expectedError: ReferenceErrorConstructor = ReferenceError;
+
+            let testFunc: () => void;
+
+            beforeEach(() => {
+                testFunc = () => arrayUtils.arrayRotate(emptyArray, rotateValue);
+            });
+
+            it('should throw exception if array is empty', () => {
+                assert.throws(testFunc, expectedError);
+            });
+        });
+    });
+});

+ 19 - 5
test/unit-tests/utils/crypt-utils/CryptUtils.spec.ts → test/unit-tests/utils/CryptUtils.spec.ts

@@ -1,15 +1,29 @@
 import { assert } from 'chai';
 
-import { CryptUtils } from '../../../../src/utils/CryptUtils';
+import { ServiceIdentifiers } from '../../../src/container/ServiceIdentifiers';
+
+import { ICryptUtils } from '../../../src/interfaces/utils/ICryptUtils';
+import { IInversifyContainerFacade } from '../../../src/interfaces/container/IInversifyContainerFacade';
+
+import { InversifyContainerFacade } from '../../../src/container/InversifyContainerFacade';
 
 describe('CryptUtils', () => {
+    let cryptUtils: ICryptUtils;
+
+    before(() => {
+        const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
+
+        inversifyContainerFacade.load({});
+        cryptUtils = inversifyContainerFacade.get<ICryptUtils>(ServiceIdentifiers.ICryptUtils);
+    });
+
     describe('btoa (string: string): string', () => {
         const expectedString: string = 'c3RyaW5n';
 
         let string: string;
 
         before(() => {
-            string = CryptUtils.btoa('string');
+            string = cryptUtils.btoa('string');
         });
 
         it('should create a base-64 encoded string from a given string', () => {
@@ -25,7 +39,7 @@ describe('CryptUtils', () => {
             diffString: string;
 
         before(() => {
-            [hiddenString, diffString] = CryptUtils.hideString(originalString, hiddenStringLength);
+            [hiddenString, diffString] = cryptUtils.hideString(originalString, hiddenStringLength);
         });
 
         describe('hidden string length check', () => {
@@ -65,8 +79,8 @@ describe('CryptUtils', () => {
             decodedString: string;
 
         before(() => {
-            encodedString = CryptUtils.rc4(string, key);
-            decodedString = CryptUtils.rc4(encodedString, key);
+            encodedString = cryptUtils.rc4(string, key);
+            decodedString = cryptUtils.rc4(encodedString, key);
         });
 
         it('should encode string using the rc4 algorithm', () => {

+ 52 - 0
test/unit-tests/utils/EscapeSequenceEncoder.spec.ts

@@ -0,0 +1,52 @@
+import { assert } from 'chai';
+
+import { InversifyContainerFacade } from '../../../src/container/InversifyContainerFacade';
+import { ServiceIdentifiers } from '../../../src/container/ServiceIdentifiers';
+
+import { IInversifyContainerFacade } from '../../../src/interfaces/container/IInversifyContainerFacade';
+import { IEscapeSequenceEncoder } from '../../../src/interfaces/utils/IEscapeSequenceEncoder';
+
+
+describe('EscapeSequenceEncoder', () => {
+    describe('encode (string: string, encodeAllSymbols: boolean = false): string', () => {
+        let escapeSequenceEncoder: IEscapeSequenceEncoder;
+
+        before(() => {
+            const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
+
+            inversifyContainerFacade.load({});
+            escapeSequenceEncoder = inversifyContainerFacade
+                .get<IEscapeSequenceEncoder>(ServiceIdentifiers.IEscapeSequenceEncoder);
+        });
+
+        describe('variant #1: default', () => {
+            const string: string = 'string';
+            const expectedString: string = '\\x73\\x74\\x72\\x69\\x6e\\x67';
+
+            let actualString: string;
+
+            before(() => {
+                actualString = escapeSequenceEncoder.encode(string, true);
+            });
+
+            it('should return a string where all characters are encoded', () => {
+                assert.equal(actualString, expectedString);
+            });
+        });
+
+        describe('variant #2: escape `escape sequences`', () => {
+            const string: string = 'abc\'\\r\\n';
+            const expectedString: string = 'abc\\x27\\x5cr\\x5cn';
+
+            let actualString: string;
+
+            before(() => {
+                actualString = escapeSequenceEncoder.encode(string, false);
+            });
+
+            it('should return a string where all `escape sequences` are encoded', () => {
+                assert.equal(actualString, expectedString);
+            });
+        });
+    });
+});

+ 45 - 0
test/unit-tests/utils/RandomGeneratorUtils.spec.ts

@@ -0,0 +1,45 @@
+import { assert } from 'chai';
+
+import { ServiceIdentifiers } from '../../../src/container/ServiceIdentifiers';
+
+import { IInversifyContainerFacade } from '../../../src/interfaces/container/IInversifyContainerFacade';
+import { IRandomGenerator } from '../../../src/interfaces/utils/IRandomGenerator';
+
+import { InversifyContainerFacade } from '../../../src/container/InversifyContainerFacade';
+
+describe('RandomGeneratorUtils', () => {
+    describe('getRandomVariableName (length: number = 6): string', () => {
+        let randomGenerator: IRandomGenerator,
+            randomVariableName: string,
+            regExp: RegExp;
+
+        before(() => {
+            const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
+
+            inversifyContainerFacade.load({});
+            randomGenerator = inversifyContainerFacade.get<IRandomGenerator>(ServiceIdentifiers.IRandomGenerator)
+        });
+
+        describe('variant #1: string with random variable of length `4`', () => {
+            before(() => {
+                randomVariableName = randomGenerator.getRandomVariableName(4);
+                regExp = /^_0x(\w){4}$/;
+            });
+
+            it('should return random variable name', () => {
+                assert.match(randomVariableName, regExp);
+            })
+        });
+
+        describe('variant #2: string with random variable of length `6`', () => {
+            before(() => {
+                randomVariableName = randomGenerator.getRandomVariableName(6);
+                regExp = /^_0x(\w){4,6}$/;
+            });
+
+            it('should return random variable name', () => {
+                assert.match(randomVariableName, regExp);
+            })
+        });
+    });
+});

+ 2 - 132
test/unit-tests/utils/utils/Utils.spec.ts → test/unit-tests/utils/Utils.spec.ts

@@ -1,108 +1,10 @@
 import { assert } from 'chai';
 
-import { Utils } from '../../../../src/utils/Utils';
+import { JSFuck } from '../../../src/enums/JSFuck';
 
-import { JSFuck } from '../../../../src/enums/JSFuck';
+import { Utils } from '../../../src/utils/Utils';
 
 describe('Utils', () => {
-    describe('arrayRange (length: number): number[]', () => {
-        describe('range length more than 0', () => {
-            const rangeLength: number = 5;
-            const expectedArray: number[] = [0, 1, 2, 3, 4];
-
-            let array: number[];
-
-            before(() => {
-                array = Utils.arrayRange(rangeLength);
-            });
-
-            it('should return array with range of numbers', () => {
-                assert.deepEqual(array, expectedArray);
-            });
-        });
-
-        describe('range length is 0', () => {
-            const rangeLength: number = 0;
-            const expectedArray: number[] = [];
-
-            let array: number[];
-
-            before(() => {
-                array = Utils.arrayRange(rangeLength);
-            });
-
-            it('should return empty array', () => {
-                assert.deepEqual(array, expectedArray);
-            });
-        });
-
-        describe('range length less than 0', () => {
-            const rangeLength: number = -5;
-            const expectedArray: number[] = [];
-
-            let array: number[];
-
-            before(() => {
-                array = Utils.arrayRange(rangeLength);
-            });
-
-            it('should return empty array', () => {
-                assert.deepEqual(array, expectedArray);
-            });
-        });
-    });
-
-    describe('arrayRotate <T> (array: T[], times: number): T[]', () => {
-        let array: number[],
-            rotatedArray: number[];
-
-        beforeEach(() => {
-            array = [1, 2, 3, 4, 5, 6];
-        });
-
-        describe('value is not 0', () => {
-            const rotateValue: number = 2;
-            const expectedArray: number[] = [5, 6, 1, 2, 3, 4];
-
-            beforeEach(() => {
-                rotatedArray = Utils.arrayRotate(array, rotateValue);
-            });
-
-            it('should rotate (shift) array by a given value', () => {
-                assert.deepEqual(rotatedArray, expectedArray);
-            });
-        });
-
-        describe('value equals or less 0', () => {
-            const rotateValue: number = 0;
-            const expectedArray: number[] = [1, 2, 3, 4, 5, 6];
-
-            beforeEach(() => {
-                rotatedArray = Utils.arrayRotate(array, rotateValue);
-            });
-
-            it('shouldn\'t rotate array', () => {
-                assert.deepEqual(rotatedArray, expectedArray);
-            });
-        });
-
-        describe('empty array', () => {
-            const emptyArray: number[] = [];
-            const rotateValue: number = 5;
-            const expectedError: ReferenceErrorConstructor = ReferenceError;
-
-            let testFunc: () => void;
-
-            beforeEach(() => {
-                testFunc = () => Utils.arrayRotate(emptyArray, rotateValue);
-            });
-
-            it('should throw exception if array is empty', () => {
-                assert.throws(testFunc, expectedError);
-            });
-        });
-    });
-
     describe('decToHex (dec: number): string', () => {
         describe('variant #1: number `0`', () => {
             const number: number = 0;
@@ -336,36 +238,4 @@ describe('Utils', () => {
             assert.equal(actualString, expectedString);
         });
     });
-
-    describe('stringToUnicodeEscapeSequence (string: string, nonLatinAndNonDigitsOnly: boolean = false): string', () => {
-        describe('variant #1: default', () => {
-            const string: string = 'string';
-            const expectedString: string = '\\x73\\x74\\x72\\x69\\x6e\\x67';
-
-            let actualString: string;
-
-            before(() => {
-                actualString = Utils.stringToUnicodeEscapeSequence(string, true);
-            });
-
-            it('should return a unicode escape sequence based on a given string', () => {
-                assert.equal(actualString, expectedString);
-            });
-        });
-
-        describe('variant #2: escape `escape sequences`', () => {
-            const string: string = 'abc\'\\r\\n';
-            const expectedString: string = 'abc\\x27\\x5cr\\x5cn';
-
-            let actualString: string;
-
-            before(() => {
-                actualString = Utils.stringToUnicodeEscapeSequence(string, false);
-            });
-
-            it('should return a string where all `escape sequences` are escaped', () => {
-                assert.equal(actualString, expectedString);
-            });
-        });
-    });
 });

+ 0 - 32
test/unit-tests/utils/random-generator-utils/RandomGeneratorUtils.spec.ts

@@ -1,32 +0,0 @@
-import { assert } from 'chai';
-
-import { RandomGeneratorUtils } from '../../../../src/utils/RandomGeneratorUtils';
-
-describe('RandomGeneratorUtils', () => {
-    describe('getRandomVariableName (length: number = 6): string', () => {
-        let randomVariableName: string,
-            regExp: RegExp;
-
-        describe('variant #1: string with random variable of length `4`', () => {
-            before(() => {
-                randomVariableName = RandomGeneratorUtils.getRandomVariableName(4);
-                regExp = /^_0x(\w){4}$/;
-            });
-
-            it('should return random variable name', () => {
-                assert.match(randomVariableName, regExp);
-            })
-        });
-
-        describe('variant #2: string with random variable of length `6`', () => {
-            before(() => {
-                randomVariableName = RandomGeneratorUtils.getRandomVariableName(6);
-                regExp = /^_0x(\w){4,6}$/;
-            });
-
-            it('should return random variable name', () => {
-                assert.match(randomVariableName, regExp);
-            })
-        });
-    });
-});

+ 70 - 31
yarn.lock

@@ -2,9 +2,9 @@
 # yarn lockfile v1
 
 
-"@types/[email protected].0":
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.0.0.tgz#4c9adabd2d04265769e6d9e847e86cc404dc7dcd"
+"@types/[email protected].1":
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.0.1.tgz#37fea779617cfec3fd2b19a0247e8bbdd5133bf6"
 
 "@types/[email protected]":
   version "0.7.33"
@@ -45,16 +45,16 @@
   resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.41.tgz#e27cf0817153eb9f2713b2d3f6c68f1e1c3ca608"
 
 "@types/node@*":
-  version "7.0.31"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.31.tgz#80ea4d175599b2a00149c29a10a4eb2dff592e86"
+  version "8.0.1"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.1.tgz#89c271e0c3b9ebb6a3756dd601336970b6228b77"
 
-"@types/[email protected].0":
-  version "8.0.0"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.0.tgz#acaa89247afddc7967e9902fd11761dadea1a555"
+"@types/[email protected].3":
+  version "8.0.3"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.3.tgz#fca61c26f83e5f453166114f57d53a47feb36d45"
 
-"@types/[email protected].1":
-  version "2.3.1"
-  resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-2.3.1.tgz#5e214093e9e2345219ab0f31bf310c9790ad0712"
+"@types/[email protected].2":
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-2.3.2.tgz#1e1e99e67162d78e2db17816892bf93bf5209885"
 
 "@types/[email protected]":
   version "1.0.2"
@@ -378,11 +378,11 @@ babel-helpers@^6.24.1:
     babel-runtime "^6.22.0"
     babel-template "^6.24.1"
 
-babel-loader@7.0.0:
-  version "7.0.0"
-  resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.0.0.tgz#2e43a66bee1fff4470533d0402c8a4532fafbaf7"
+babel-loader@7.1.0:
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.0.tgz#3fbf2581f085774bd9642dca9990e6d6c1491144"
   dependencies:
-    find-cache-dir "^0.1.1"
+    find-cache-dir "^1.0.0"
     loader-utils "^1.0.2"
     mkdirp "^0.5.1"
 
@@ -935,6 +935,12 @@ combined-stream@^1.0.5, combined-stream@~1.0.5:
   dependencies:
     delayed-stream "~1.0.0"
 
[email protected]:
+  version "2.10.0"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.10.0.tgz#e1f5d3245de246d1a5ca04702fa1ad1bd7e405fe"
+  dependencies:
+    graceful-readlink ">= 1.0.0"
+
 [email protected], commander@^2.8.1, commander@^2.9.0:
   version "2.9.0"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
@@ -1437,13 +1443,13 @@ fill-range@^2.1.0:
     repeat-element "^1.1.2"
     repeat-string "^1.5.2"
 
-find-cache-dir@^0.1.1:
-  version "0.1.1"
-  resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9"
+find-cache-dir@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f"
   dependencies:
     commondir "^1.0.1"
-    mkdirp "^0.5.1"
-    pkg-dir "^1.0.0"
+    make-dir "^1.0.0"
+    pkg-dir "^2.0.0"
 
 find-up@^1.0.0:
   version "1.1.2"
@@ -1452,6 +1458,12 @@ find-up@^1.0.0:
     path-exists "^2.0.0"
     pinkie-promise "^2.0.0"
 
+find-up@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
+  dependencies:
+    locate-path "^2.0.0"
+
 for-in@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
@@ -2111,6 +2123,13 @@ loader-utils@^1.0.2, loader-utils@^1.1.0:
     emojis-list "^2.0.0"
     json5 "^0.5.0"
 
+locate-path@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
+  dependencies:
+    p-locate "^2.0.0"
+    path-exists "^3.0.0"
+
 lodash._baseassign@^3.0.0:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
@@ -2187,6 +2206,12 @@ lru-cache@^4.0.1:
     pseudomap "^1.0.1"
     yallist "^2.0.0"
 
+make-dir@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.0.0.tgz#97a011751e91dd87cfadef58832ebb04936de978"
+  dependencies:
+    pify "^2.3.0"
+
 make-error@^1.1.1:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.0.tgz#52ad3a339ccf10ce62b4040b708fe707244b8b96"
@@ -2502,6 +2527,16 @@ output-file-sync@^1.1.0:
     mkdirp "^0.5.1"
     object-assign "^4.1.0"
 
+p-limit@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc"
+
+p-locate@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
+  dependencies:
+    p-limit "^1.1.0"
+
 pako@~0.2.0:
   version "0.2.9"
   resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
@@ -2541,6 +2576,10 @@ path-exists@^2.0.0:
   dependencies:
     pinkie-promise "^2.0.0"
 
+path-exists@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
+
 path-is-absolute@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
@@ -2581,7 +2620,7 @@ performance-now@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
 
-pify@^2.0.0:
+pify@^2.0.0, pify@^2.3.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
 
@@ -2595,11 +2634,11 @@ pinkie@^2.0.0:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
 
-pkg-dir@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4"
+pkg-dir@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
   dependencies:
-    find-up "^1.0.0"
+    find-up "^2.1.0"
 
 [email protected]:
   version "1.2.2"
@@ -2936,9 +2975,9 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
 
[email protected].4:
-  version "2.3.4"
-  resolved "https://registry.yarnpkg.com/sinon/-/sinon-2.3.4.tgz#466ad8d1bae86d6db51aa218b92e997bc3e5db88"
[email protected].5:
+  version "2.3.5"
+  resolved "https://registry.yarnpkg.com/sinon/-/sinon-2.3.5.tgz#9a2fc0ff8d526da716f30953aa2c65d518917f6c"
   dependencies:
     diff "^3.1.0"
     formatio "1.2.0"
@@ -3174,9 +3213,9 @@ trim-right@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
 
-ts-node@3.0.6:
-  version "3.0.6"
-  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-3.0.6.tgz#55127ff790c7eebf6ba68c1e6dde94b09aaa21e0"
+ts-node@3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-3.1.0.tgz#a75ec5aeb48f3058b1b945dba765f1150ba88f8c"
   dependencies:
     arrify "^1.0.0"
     chalk "^1.1.1"

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio