فهرست منبع

callExpression control flow replacer

sanex3339 8 سال پیش
والد
کامیت
610c35b9fd
37فایلهای تغییر یافته به همراه977 افزوده شده و 475 حذف شده
  1. 413 385
      dist/index.js
  2. 13 3
      src/container/modules/custom-nodes/CustomNodesModule.ts
  3. 5 0
      src/container/modules/node-transformers/NodeControlFlowTransformersModule.ts
  4. 1 1
      src/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.ts
  5. 1 1
      src/custom-nodes/console-output-nodes/group/ConsoleOutputCustomNodeGroup.ts
  6. 1 1
      src/custom-nodes/control-flow-replacers-nodes/binary-expression-control-flow-replacer-nodes/BinaryExpressionFunctionNode.ts
  7. 70 0
      src/custom-nodes/control-flow-replacers-nodes/call-expression-control-flow-replacer-nodes/CallExpressionFunctionNode.ts
  8. 1 1
      src/custom-nodes/control-flow-replacers-nodes/logical-expression-control-flow-replacer-nodes/LogicalExpressionFunctionNode.ts
  9. 85 0
      src/custom-nodes/control-flow-storage-nodes/CallExpressionControlFlowStorageCallNode.ts
  10. 1 1
      src/custom-nodes/control-flow-storage-nodes/ExpressionWithOperatorControlFlowStorageCallNode.ts
  11. 1 1
      src/custom-nodes/debug-protection-nodes/group/DebugProtectionCustomNodeGroup.ts
  12. 1 1
      src/custom-nodes/domain-lock-nodes/DomainLockNode.ts
  13. 1 1
      src/custom-nodes/domain-lock-nodes/group/DomainLockCustomNodeGroup.ts
  14. 1 1
      src/custom-nodes/self-defending-nodes/SelfDefendingUnicodeNode.ts
  15. 1 1
      src/custom-nodes/self-defending-nodes/group/SelfDefendingCustomNodeGroup.ts
  16. 2 2
      src/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.ts
  17. 1 0
      src/declarations/ESTree.d.ts
  18. 3 1
      src/enums/container/CustomNodes.ts
  19. 1 0
      src/enums/container/NodeControlFlowReplacers.ts
  20. 1 0
      src/node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer.ts
  21. 1 31
      src/node-transformers/node-control-flow-transformers/control-flow-replacers/AbstractControlFlowReplacer.ts
  22. 2 2
      src/node-transformers/node-control-flow-transformers/control-flow-replacers/BinaryExpressionControlFlowReplacer.ts
  23. 102 0
      src/node-transformers/node-control-flow-transformers/control-flow-replacers/CallExpressionControlFlowReplacer.ts
  24. 71 0
      src/node-transformers/node-control-flow-transformers/control-flow-replacers/ExpressionWithOperatorControlFlowReplacer.ts
  25. 2 2
      src/node-transformers/node-control-flow-transformers/control-flow-replacers/LogicalExpressionControlFlowReplacer.ts
  26. 1 1
      src/node-transformers/node-obfuscators/replacers/IdentifierReplacer.ts
  27. 50 2
      src/node/Nodes.ts
  28. 1 1
      src/storages/string-array/StringArrayStorage.ts
  29. 16 3
      src/utils/RandomGeneratorUtils.ts
  30. 1 30
      test/dev/dev.ts
  31. 7 0
      test/fixtures/node-transformers/node-control-flow-transformers/control-flow-replacers/call-expression-control-flow-replacer/call-expression-control-flow-replacer-1.js
  32. 8 0
      test/fixtures/node-transformers/node-control-flow-transformers/control-flow-replacers/call-expression-control-flow-replacer/call-expression-control-flow-replacer-2.js
  33. 9 0
      test/fixtures/node-transformers/node-control-flow-transformers/control-flow-replacers/call-expression-control-flow-replacer/call-expression-control-flow-replacer-3.js
  34. 3 0
      test/functional-tests/JavaScriptObfuscator.spec.ts
  35. 96 0
      test/functional-tests/node-transformers/node-control-flow-transformers/control-flow-replacers/CallExpressionControlFlowReplacer.spec.ts
  36. 1 0
      test/index.spec.ts
  37. 2 2
      test/unit-tests/utils/RandomGeneratorUtils.spec.ts

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 413 - 385
dist/index.js


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

@@ -15,13 +15,15 @@ import { SelfDefendingCustomNodeGroup } from '../../../custom-nodes/self-defendi
 import { StringArrayCustomNodeGroup } from '../../../custom-nodes/string-array-nodes/group/StringArrayCustomNodeGroup';
 
 import { BinaryExpressionFunctionNode } from '../../../custom-nodes/control-flow-replacers-nodes/binary-expression-control-flow-replacer-nodes/BinaryExpressionFunctionNode';
-import { ControlFlowStorageCallNode } from '../../../custom-nodes/control-flow-storage-nodes/ControlFlowStorageCallNode';
+import { CallExpressionControlFlowStorageCallNode } from '../../../custom-nodes/control-flow-storage-nodes/CallExpressionControlFlowStorageCallNode';
+import { CallExpressionFunctionNode } from '../../../custom-nodes/control-flow-replacers-nodes/call-expression-control-flow-replacer-nodes/CallExpressionFunctionNode';
 import { ControlFlowStorageNode } from '../../../custom-nodes/control-flow-storage-nodes/ControlFlowStorageNode';
 import { ConsoleOutputDisableExpressionNode } from '../../../custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode';
 import { DebugProtectionFunctionCallNode } from '../../../custom-nodes/debug-protection-nodes/DebugProtectionFunctionCallNode';
 import { DebugProtectionFunctionIntervalNode } from '../../../custom-nodes/debug-protection-nodes/DebugProtectionFunctionIntervalNode';
 import { DebugProtectionFunctionNode } from '../../../custom-nodes/debug-protection-nodes/DebugProtectionFunctionNode';
 import { DomainLockNode } from '../../../custom-nodes/domain-lock-nodes/DomainLockNode';
+import { ExpressionWithOperatorControlFlowStorageCallNode } from '../../../custom-nodes/control-flow-storage-nodes/ExpressionWithOperatorControlFlowStorageCallNode';
 import { LogicalExpressionFunctionNode } from '../../../custom-nodes/control-flow-replacers-nodes/logical-expression-control-flow-replacer-nodes/LogicalExpressionFunctionNode';
 import { NodeCallsControllerFunctionNode } from '../../../custom-nodes/node-calls-controller-nodes/NodeCallsControllerFunctionNode';
 import { SelfDefendingUnicodeNode } from '../../../custom-nodes/self-defending-nodes/SelfDefendingUnicodeNode';
@@ -36,8 +38,12 @@ export const customNodesModule: interfaces.ContainerModule = new ContainerModule
         .whenTargetNamed(CustomNodes.BinaryExpressionFunctionNode);
 
     bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
-        .toConstructor(ControlFlowStorageCallNode)
-        .whenTargetNamed(CustomNodes.ControlFlowStorageCallNode);
+        .toConstructor(CallExpressionControlFlowStorageCallNode)
+        .whenTargetNamed(CustomNodes.CallExpressionControlFlowStorageCallNode);
+
+    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
+        .toConstructor(CallExpressionFunctionNode)
+        .whenTargetNamed(CustomNodes.CallExpressionFunctionNode);
 
     bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
         .toConstructor(ControlFlowStorageNode)
@@ -63,6 +69,10 @@ export const customNodesModule: interfaces.ContainerModule = new ContainerModule
         .toConstructor(DomainLockNode)
         .whenTargetNamed(CustomNodes.DomainLockNode);
 
+    bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
+        .toConstructor(ExpressionWithOperatorControlFlowStorageCallNode)
+        .whenTargetNamed(CustomNodes.ExpressionWithOperatorControlFlowStorageCallNode);
+
     bind<interfaces.Newable<ICustomNode>>(ServiceIdentifiers.Newable__ICustomNode)
         .toConstructor(LogicalExpressionFunctionNode)
         .whenTargetNamed(CustomNodes.LogicalExpressionFunctionNode);

+ 5 - 0
src/container/modules/node-transformers/NodeControlFlowTransformersModule.ts

@@ -6,6 +6,7 @@ import { IControlFlowReplacer } from '../../../interfaces/node-transformers/ICon
 import { NodeControlFlowReplacers } from '../../../enums/container/NodeControlFlowReplacers';
 
 import { BinaryExpressionControlFlowReplacer } from '../../../node-transformers/node-control-flow-transformers/control-flow-replacers/BinaryExpressionControlFlowReplacer';
+import { CallExpressionControlFlowReplacer } from '../../../node-transformers/node-control-flow-transformers/control-flow-replacers/CallExpressionControlFlowReplacer';
 import { LogicalExpressionControlFlowReplacer } from '../../../node-transformers/node-control-flow-transformers/control-flow-replacers/LogicalExpressionControlFlowReplacer';
 
 export const nodeControlFlowTransformersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
@@ -13,6 +14,10 @@ export const nodeControlFlowTransformersModule: interfaces.ContainerModule = new
         .to(BinaryExpressionControlFlowReplacer)
         .whenTargetNamed(NodeControlFlowReplacers.BinaryExpressionControlFlowReplacer);
 
+    bind<IControlFlowReplacer>(ServiceIdentifiers.IControlFlowReplacer)
+        .to(CallExpressionControlFlowReplacer)
+        .whenTargetNamed(NodeControlFlowReplacers.CallExpressionControlFlowReplacer);
+
     bind<IControlFlowReplacer>(ServiceIdentifiers.IControlFlowReplacer)
         .to(LogicalExpressionControlFlowReplacer)
         .whenTargetNamed(NodeControlFlowReplacers.LogicalExpressionControlFlowReplacer);

+ 1 - 1
src/custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode.ts

@@ -51,7 +51,7 @@ export class ConsoleOutputDisableExpressionNode extends AbstractCustomNode {
      */
     protected getTemplate (): string {
         return format(ConsoleOutputDisableExpressionTemplate(), {
-            consoleLogDisableFunctionName: RandomGeneratorUtils.getRandomVariableName(),
+            consoleLogDisableFunctionName: RandomGeneratorUtils.getRandomVariableName(6, true, true),
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName
         });
     }

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

@@ -96,7 +96,7 @@ export class ConsoleOutputCustomNodeGroup extends AbstractCustomNodeGroup {
             return;
         }
 
-        const callsControllerFunctionName: string = RandomGeneratorUtils.getRandomVariableName();
+        const callsControllerFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6, true, true);
 
         const consoleOutputDisableExpressionNode: ICustomNode = this.customNodeFactory(CustomNodes.ConsoleOutputDisableExpressionNode);
         const nodeCallsControllerFunctionNode: ICustomNode = this.customNodeFactory(CustomNodes.NodeCallsControllerFunctionNode);

+ 1 - 1
src/custom-nodes/control-flow-replacers-nodes/binary-expression-control-flow-replacer-nodes/BinaryExpressionFunctionNode.ts

@@ -43,7 +43,7 @@ export class BinaryExpressionFunctionNode extends AbstractCustomNode {
     protected getNodeStructure (): TStatement[] {
         return [
             Nodes.getFunctionDeclarationNode(
-                RandomGeneratorUtils.getRandomVariableName(1),
+                RandomGeneratorUtils.getRandomVariableName(1, true, false),
                 [
                     Nodes.getIdentifierNode('x'),
                     Nodes.getIdentifierNode('y')

+ 70 - 0
src/custom-nodes/control-flow-replacers-nodes/call-expression-control-flow-replacer-nodes/CallExpressionFunctionNode.ts

@@ -0,0 +1,70 @@
+import { injectable, inject } from 'inversify';
+import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
+
+import * as ESTree from 'estree';
+
+import { TStatement } from '../../../types/node/TStatement';
+
+import { IOptions } from '../../../interfaces/options/IOptions';
+
+import { initializable } from '../../../decorators/Initializable';
+
+import { AbstractCustomNode } from '../../AbstractCustomNode';
+import { Nodes } from '../../../node/Nodes';
+import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
+
+@injectable()
+export class CallExpressionFunctionNode extends AbstractCustomNode {
+    /**
+     * @type {(ESTree.Expression | ESTree.SpreadElement)[]}
+     */
+    @initializable()
+    private expressionArguments: (ESTree.Expression | ESTree.SpreadElement)[];
+
+    /**
+     * @param options
+     */
+    constructor (
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(options);
+    }
+
+    /**
+     * @param expressionArguments
+     */
+    public initialize (expressionArguments: (ESTree.Expression | ESTree.SpreadElement)[]): void {
+        this.expressionArguments = expressionArguments;
+    }
+
+    /**
+     * @returns {TStatement[]}
+     */
+    protected getNodeStructure (): TStatement[] {
+        const calleeIdentifier: ESTree.Identifier = Nodes.getIdentifierNode('callee');
+        const params: ESTree.Identifier[] = [];
+        const argumentsLength: number = this.expressionArguments.length;
+
+        for (let i: number = 0; i < argumentsLength; i++) {
+            params.push(Nodes.getIdentifierNode(`param${i + 1}`));
+        }
+
+        return [
+            Nodes.getFunctionDeclarationNode(
+                RandomGeneratorUtils.getRandomVariableName(1, true, false),
+                [
+                    calleeIdentifier,
+                    ...params
+                ],
+                Nodes.getBlockStatementNode([
+                    Nodes.getReturnStatementNode(
+                        Nodes.getCallExpressionNode(
+                            calleeIdentifier,
+                            params
+                        )
+                    )
+                ])
+            )
+        ];
+    }
+}

+ 1 - 1
src/custom-nodes/control-flow-replacers-nodes/logical-expression-control-flow-replacer-nodes/LogicalExpressionFunctionNode.ts

@@ -43,7 +43,7 @@ export class LogicalExpressionFunctionNode extends AbstractCustomNode {
     protected getNodeStructure (): TStatement[] {
         return [
             Nodes.getFunctionDeclarationNode(
-                RandomGeneratorUtils.getRandomVariableName(1),
+                RandomGeneratorUtils.getRandomVariableName(1, true, false),
                 [
                     Nodes.getIdentifierNode('x'),
                     Nodes.getIdentifierNode('y')

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

@@ -0,0 +1,85 @@
+import { injectable, inject } from 'inversify';
+import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
+
+import * as ESTree from 'estree';
+import { Expression } from 'estree';
+
+import { TStatement } from '../../types/node/TStatement';
+
+import { IOptions } from '../../interfaces/options/IOptions';
+
+import { initializable } from '../../decorators/Initializable';
+
+import { AbstractCustomNode } from '../AbstractCustomNode';
+import { Nodes } from '../../node/Nodes';
+
+@injectable()
+export class CallExpressionControlFlowStorageCallNode extends AbstractCustomNode {
+    /**
+     * @type {Expression}
+     */
+    @initializable()
+    private callee: Expression;
+
+    /**
+     * @type {string}
+     */
+    @initializable()
+    private controlFlowStorageKey: string;
+
+    /**
+     * @type {string}
+     */
+    @initializable()
+    private controlFlowStorageName: string;
+
+    /**
+     * @type {(ESTree.Expression | ESTree.SpreadElement)[]}
+     */
+    @initializable()
+    private expressionArguments: (ESTree.Expression | ESTree.SpreadElement)[];
+
+    /**
+     * @param options
+     */
+    constructor (
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(options);
+    }
+
+    /**
+     * @param controlFlowStorageName
+     * @param controlFlowStorageKey
+     * @param callee
+     * @param expressionArguments
+     */
+    public initialize (
+        controlFlowStorageName: string,
+        controlFlowStorageKey: string,
+        callee: Expression,
+        expressionArguments: (ESTree.Expression | ESTree.SpreadElement)[]
+    ): void {
+        this.controlFlowStorageName = controlFlowStorageName;
+        this.controlFlowStorageKey = controlFlowStorageKey;
+        this.callee = callee;
+        this.expressionArguments = expressionArguments;
+    }
+
+    protected getNodeStructure (): TStatement[] {
+        return [
+            Nodes.getExpressionStatementNode(
+                Nodes.getCallExpressionNode(
+                    Nodes.getMemberExpressionNode(
+                        Nodes.getIdentifierNode(this.controlFlowStorageName),
+                        Nodes.getIdentifierNode(this.controlFlowStorageKey)
+                    ),
+                    [
+                        this.callee,
+                        ...this.expressionArguments
+                    ]
+                )
+            )
+        ];
+    }
+}

+ 1 - 1
src/custom-nodes/control-flow-storage-nodes/ControlFlowStorageCallNode.ts → src/custom-nodes/control-flow-storage-nodes/ExpressionWithOperatorControlFlowStorageCallNode.ts

@@ -13,7 +13,7 @@ import { AbstractCustomNode } from '../AbstractCustomNode';
 import { Nodes } from '../../node/Nodes';
 
 @injectable()
-export class ControlFlowStorageCallNode extends AbstractCustomNode {
+export class ExpressionWithOperatorControlFlowStorageCallNode extends AbstractCustomNode {
     /**
      * @type {string}
      */

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

@@ -89,7 +89,7 @@ export class DebugProtectionCustomNodeGroup extends AbstractCustomNodeGroup {
             return;
         }
 
-        const debugProtectionFunctionName: string = RandomGeneratorUtils.getRandomVariableName();
+        const debugProtectionFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6, true, true);
 
         const debugProtectionFunctionNode: ICustomNode = this.customNodeFactory(CustomNodes.DebugProtectionFunctionNode);
         const debugProtectionFunctionCallNode: ICustomNode = this.customNodeFactory(CustomNodes.DebugProtectionFunctionCallNode);

+ 1 - 1
src/custom-nodes/domain-lock-nodes/DomainLockNode.ts

@@ -55,7 +55,7 @@ export class DomainLockNode extends AbstractCustomNode {
         const [hiddenDomainsString, diff]: string[] = CryptUtils.hideString(domainsString, domainsString.length * 3);
 
         return format(DomainLockNodeTemplate(), {
-            domainLockFunctionName: RandomGeneratorUtils.getRandomVariableName(),
+            domainLockFunctionName: RandomGeneratorUtils.getRandomVariableName(6, true, true),
             diff: diff,
             domains: hiddenDomainsString,
             singleNodeCallControllerFunctionName: this.callsControllerFunctionName

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

@@ -96,7 +96,7 @@ export class DomainLockCustomNodeGroup extends AbstractCustomNodeGroup {
             return;
         }
 
-        const callsControllerFunctionName: string = RandomGeneratorUtils.getRandomVariableName();
+        const callsControllerFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6, true, true);
 
         const domainLockNode: ICustomNode = this.customNodeFactory(CustomNodes.DomainLockNode);
         const nodeCallsControllerFunctionNode: ICustomNode = this.customNodeFactory(CustomNodes.NodeCallsControllerFunctionNode);

+ 1 - 1
src/custom-nodes/self-defending-nodes/SelfDefendingUnicodeNode.ts

@@ -55,7 +55,7 @@ export class SelfDefendingUnicodeNode extends AbstractCustomNode {
     protected getTemplate (): string {
         return JavaScriptObfuscator.obfuscate(
             format(SelfDefendingTemplate(), {
-                selfDefendingFunctionName: RandomGeneratorUtils.getRandomVariableName(),
+                selfDefendingFunctionName: RandomGeneratorUtils.getRandomVariableName(6, true, true),
                 singleNodeCallControllerFunctionName: this.callsControllerFunctionName
             }),
             {

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

@@ -96,7 +96,7 @@ export class SelfDefendingCustomNodeGroup extends AbstractCustomNodeGroup {
             return;
         }
 
-        const callsControllerFunctionName: string = RandomGeneratorUtils.getRandomVariableName();
+        const callsControllerFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6, true, true);
 
         const selfDefendingUnicodeNode: ICustomNode = this.customNodeFactory(CustomNodes.SelfDefendingUnicodeNode);
         const nodeCallsControllerFunctionNode: ICustomNode = this.customNodeFactory(CustomNodes.NodeCallsControllerFunctionNode);

+ 2 - 2
src/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.ts

@@ -76,8 +76,8 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
      * @returns {string}
      */
     protected getTemplate (): string {
-        const timesName: string = RandomGeneratorUtils.getRandomVariableName();
-        const whileFunctionName: string = RandomGeneratorUtils.getRandomVariableName();
+        const timesName: string = RandomGeneratorUtils.getRandomVariableName(6, true, true);
+        const whileFunctionName: string = RandomGeneratorUtils.getRandomVariableName(6, true, true);
 
         let code: string = '';
 

+ 1 - 0
src/declarations/ESTree.d.ts

@@ -6,6 +6,7 @@ declare module 'estree' {
     interface BaseNode {
         obfuscated?: boolean;
         parentNode?: ESTree.Node;
+        skippedByControlFlow?: boolean;
     }
 
     interface SimpleLiteral extends ESTree.BaseNode, ESTree.BaseExpression {

+ 3 - 1
src/enums/container/CustomNodes.ts

@@ -1,12 +1,14 @@
 export enum CustomNodes {
     BinaryExpressionFunctionNode,
-    ControlFlowStorageCallNode,
+    CallExpressionControlFlowStorageCallNode,
+    CallExpressionFunctionNode,
     ControlFlowStorageNode,
     ConsoleOutputDisableExpressionNode,
     DebugProtectionFunctionCallNode,
     DebugProtectionFunctionIntervalNode,
     DebugProtectionFunctionNode,
     DomainLockNode,
+    ExpressionWithOperatorControlFlowStorageCallNode,
     LogicalExpressionFunctionNode,
     NodeCallsControllerFunctionNode,
     SelfDefendingUnicodeNode,

+ 1 - 0
src/enums/container/NodeControlFlowReplacers.ts

@@ -1,4 +1,5 @@
 export enum NodeControlFlowReplacers {
     BinaryExpressionControlFlowReplacer,
+    CallExpressionControlFlowReplacer,
     LogicalExpressionControlFlowReplacer
 }

+ 1 - 0
src/node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer.ts

@@ -30,6 +30,7 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
      */
     private static readonly controlFlowReplacersMap: Map <string, NodeControlFlowReplacers> = new Map([
         [NodeType.BinaryExpression, NodeControlFlowReplacers.BinaryExpressionControlFlowReplacer],
+        [NodeType.CallExpression, NodeControlFlowReplacers.CallExpressionControlFlowReplacer],
         [NodeType.LogicalExpression, NodeControlFlowReplacers.LogicalExpressionControlFlowReplacer]
     ]);
 

+ 1 - 31
src/node-transformers/node-control-flow-transformers/control-flow-replacers/AbstractControlFlowReplacer.ts

@@ -4,16 +4,12 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
 import * as ESTree from 'estree';
 
 import { TCustomNodeFactory } from '../../../types/container/TCustomNodeFactory';
-import { TStatement } from '../../../types/node/TStatement';
 
 import { IControlFlowReplacer } from '../../../interfaces/node-transformers/IControlFlowReplacer';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/options/IOptions';
 import { IStorage } from '../../../interfaces/storages/IStorage';
 
-import { BinaryExpressionControlFlowReplacer } from './BinaryExpressionControlFlowReplacer';
-import { CustomNodes } from '../../../enums/container/CustomNodes';
-import { Node } from '../../../node/Node';
 import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
 
 @injectable()
@@ -73,32 +69,6 @@ export abstract class AbstractControlFlowReplacer implements IControlFlowReplace
      */
     public abstract replace (node: ESTree.Node, parentNode: ESTree.Node, controlFlowStorage: IStorage <ICustomNode>): ESTree.Node;
 
-    /**
-     * @param controlFlowStorageId
-     * @param storageKey
-     * @param leftExpression
-     * @param rightExpression
-     * @returns {ESTree.Node}
-     */
-    protected getControlFlowStorageCallNode (
-        controlFlowStorageId: string,
-        storageKey: string,
-        leftExpression: ESTree.Expression,
-        rightExpression: ESTree.Expression
-    ): ESTree.Node {
-        const controlFlowStorageCallCustomNode: ICustomNode = this.customNodeFactory(CustomNodes.ControlFlowStorageCallNode);
-
-        controlFlowStorageCallCustomNode.initialize(controlFlowStorageId, storageKey, leftExpression, rightExpression);
-
-        const statementNode: TStatement = controlFlowStorageCallCustomNode.getNode()[0];
-
-        if (!statementNode || !Node.isExpressionStatementNode(statementNode)) {
-            throw new Error(`\`controlFlowStorageCallNode.getNode()[0]\` should returns array with \`ExpressionStatement\` node`);
-        }
-
-        return statementNode.expression;
-    }
-
     /**
      * @param customNode
      * @param controlFlowStorage
@@ -113,7 +83,7 @@ export abstract class AbstractControlFlowReplacer implements IControlFlowReplace
         usingExistingIdentifierChance: number
     ): string {
         const controlFlowStorageId: string = controlFlowStorage.getStorageId();
-        const storageKeysById: Map<string, string[]> = BinaryExpressionControlFlowReplacer
+        const storageKeysById: Map<string, string[]> = AbstractControlFlowReplacer
             .getStorageKeysByIdForCurrentStorage(this.replacerDataByControlFlowStorageId, controlFlowStorageId);
         const storageKeysForCurrentId: string[] | undefined = storageKeysById.get(replacerId);
 

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

@@ -11,10 +11,10 @@ import { IStorage } from '../../../interfaces/storages/IStorage';
 
 import { CustomNodes } from '../../../enums/container/CustomNodes';
 
-import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
+import { ExpressionWithOperatorControlFlowReplacer } from './ExpressionWithOperatorControlFlowReplacer';
 
 @injectable()
-export class BinaryExpressionControlFlowReplacer extends AbstractControlFlowReplacer {
+export class BinaryExpressionControlFlowReplacer extends ExpressionWithOperatorControlFlowReplacer {
     /**
      * @type {number}
      */

+ 102 - 0
src/node-transformers/node-control-flow-transformers/control-flow-replacers/CallExpressionControlFlowReplacer.ts

@@ -0,0 +1,102 @@
+import { injectable, inject } from 'inversify';
+import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
+
+import * as ESTree from 'estree';
+
+import { TCustomNodeFactory } from '../../../types/container/TCustomNodeFactory';
+import { TStatement } from '../../../types/node/TStatement';
+
+import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
+import { IOptions } from '../../../interfaces/options/IOptions';
+import { IStorage } from '../../../interfaces/storages/IStorage';
+
+import { CustomNodes } from '../../../enums/container/CustomNodes';
+
+import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
+import { Node } from '../../../node/Node';
+
+@injectable()
+export class CallExpressionControlFlowReplacer extends AbstractControlFlowReplacer {
+    /**
+     * @type {number}
+     */
+    private static readonly usingExistingIdentifierChance: number = 0.5;
+
+    /**
+     * @param customNodeFactory
+     * @param options
+     */
+    constructor (
+        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(customNodeFactory, options);
+    }
+
+    /**
+     * @param callExpressionNode
+     * @param parentNode
+     * @param controlFlowStorage
+     * @returns {ESTree.Node}
+     */
+    public replace (
+        callExpressionNode: ESTree.CallExpression,
+        parentNode: ESTree.Node,
+        controlFlowStorage: IStorage <ICustomNode>
+    ): ESTree.Node {
+        const callee: ESTree.Expression = <ESTree.Expression>callExpressionNode.callee;
+
+        if (!Node.isIdentifierNode(callee)) {
+            return callExpressionNode;
+        }
+
+        const replacerId: string = String(callExpressionNode.arguments.length);
+        const callExpressionFunctionCustomNode: ICustomNode = this.customNodeFactory(CustomNodes.CallExpressionFunctionNode);
+        const expressionArguments: (ESTree.Expression | ESTree.SpreadElement)[] = callExpressionNode.arguments;
+
+        callExpressionFunctionCustomNode.initialize(expressionArguments);
+
+        const storageKey: string = this.insertCustomNodeToControlFlowStorage(
+            callExpressionFunctionCustomNode,
+            controlFlowStorage,
+            replacerId,
+            CallExpressionControlFlowReplacer.usingExistingIdentifierChance
+        );
+
+        return this.getControlFlowStorageCallNode(
+            controlFlowStorage.getStorageId(),
+            storageKey,
+            callee,
+            expressionArguments
+        );
+    }
+
+    /**
+     * @param controlFlowStorageId
+     * @param storageKey
+     * @param callee
+     * @param expressionArguments
+     * @param arguments
+     * @returns {ESTree.Node}
+     */
+    protected getControlFlowStorageCallNode (
+        controlFlowStorageId: string,
+        storageKey: string,
+        callee: ESTree.Expression,
+        expressionArguments: (ESTree.Expression | ESTree.SpreadElement)[]
+    ): ESTree.Node {
+        const controlFlowStorageCallCustomNode: ICustomNode = this.customNodeFactory(
+            CustomNodes.CallExpressionControlFlowStorageCallNode
+        );
+
+        controlFlowStorageCallCustomNode.initialize(controlFlowStorageId, storageKey, callee, expressionArguments);
+
+        const statementNode: TStatement = controlFlowStorageCallCustomNode.getNode()[0];
+
+        if (!statementNode || !Node.isExpressionStatementNode(statementNode)) {
+            throw new Error(`\`controlFlowStorageCallCustomNode.getNode()[0]\` should returns array with \`ExpressionStatement\` node`);
+        }
+
+        return statementNode.expression;
+    }
+}

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

@@ -0,0 +1,71 @@
+import { injectable, inject } from 'inversify';
+import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
+
+import * as ESTree from 'estree';
+
+import { TCustomNodeFactory } from '../../../types/container/TCustomNodeFactory';
+import { TStatement } from '../../../types/node/TStatement';
+
+import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
+import { IOptions } from '../../../interfaces/options/IOptions';
+
+import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
+import { CustomNodes } from '../../../enums/container/CustomNodes';
+import { Node } from '../../../node/Node';
+
+@injectable()
+export abstract class ExpressionWithOperatorControlFlowReplacer extends AbstractControlFlowReplacer {
+    /**
+     * @type {TCustomNodeFactory}
+     */
+    protected readonly customNodeFactory: TCustomNodeFactory;
+
+    /**
+     * @type {IOptions}
+     */
+    protected readonly options: IOptions;
+
+    /**
+     * @type {Map<string, Map<string, string[]>>}
+     */
+    protected readonly replacerDataByControlFlowStorageId: Map <string, Map<string, string[]>> = new Map();
+
+    /**
+     * @param customNodeFactory
+     * @param options
+     */
+    constructor (
+        @inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
+        @inject(ServiceIdentifiers.IOptions) options: IOptions
+    ) {
+        super(customNodeFactory, options);
+    }
+
+    /**
+     * @param controlFlowStorageId
+     * @param storageKey
+     * @param leftExpression
+     * @param rightExpression
+     * @returns {ESTree.Node}
+     */
+    protected getControlFlowStorageCallNode (
+        controlFlowStorageId: string,
+        storageKey: string,
+        leftExpression: ESTree.Expression,
+        rightExpression: ESTree.Expression
+    ): ESTree.Node {
+        const controlFlowStorageCallCustomNode: ICustomNode = this.customNodeFactory(
+            CustomNodes.ExpressionWithOperatorControlFlowStorageCallNode
+        );
+
+        controlFlowStorageCallCustomNode.initialize(controlFlowStorageId, storageKey, leftExpression, rightExpression);
+
+        const statementNode: TStatement = controlFlowStorageCallCustomNode.getNode()[0];
+
+        if (!statementNode || !Node.isExpressionStatementNode(statementNode)) {
+            throw new Error(`\`controlFlowStorageCallCustomNode.getNode()[0]\` should returns array with \`ExpressionStatement\` node`);
+        }
+
+        return statementNode.expression;
+    }
+}

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

@@ -11,12 +11,12 @@ import { IStorage } from '../../../interfaces/storages/IStorage';
 
 import { CustomNodes } from '../../../enums/container/CustomNodes';
 
-import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
+import { ExpressionWithOperatorControlFlowReplacer } from './ExpressionWithOperatorControlFlowReplacer';
 import { Node } from '../../../node/Node';
 import { NodeUtils } from '../../../node/NodeUtils';
 
 @injectable()
-export class LogicalExpressionControlFlowReplacer extends AbstractControlFlowReplacer {
+export class LogicalExpressionControlFlowReplacer extends ExpressionWithOperatorControlFlowReplacer {
     /**
      * @type {number}
      */

+ 1 - 1
src/node-transformers/node-obfuscators/replacers/IdentifierReplacer.ts

@@ -47,7 +47,7 @@ export class IdentifierReplacer extends AbstractReplacer implements IObfuscatorR
      */
     public storeNames (nodeName: string, nodeIdentifier: number): void {
         if (!this.isReservedName(nodeName)) {
-            this.namesMap.set(`${nodeName}-${String(nodeIdentifier)}`, RandomGeneratorUtils.getRandomVariableName());
+            this.namesMap.set(`${nodeName}-${String(nodeIdentifier)}`, RandomGeneratorUtils.getRandomVariableName(6, true, true));
         }
     }
 

+ 50 - 2
src/node/Nodes.ts

@@ -51,6 +51,23 @@ export class Nodes {
         };
     }
 
+    /**
+     * @param label
+     * @return {ESTree.BreakStatement}
+     */
+    public static getBreakStatement (label?: ESTree.Identifier): ESTree.BreakStatement {
+        const breakStatementNode: ESTree.BreakStatement = {
+            type: NodeType.BreakStatement,
+            obfuscated: false
+        };
+
+        if (label) {
+            breakStatementNode.label = label;
+        }
+
+        return breakStatementNode;
+    }
+
     /**
      * @param body
      * @returns {ESTree.CatchClause}
@@ -71,7 +88,7 @@ export class Nodes {
      */
     public static getCallExpressionNode (
         callee: ESTree.Expression,
-        args: ESTree.Expression[] | ESTree.SpreadElement[] = []
+        args: (ESTree.Expression | ESTree.SpreadElement)[] = []
     ): ESTree.CallExpression {
         return {
             type: NodeType.CallExpression,
@@ -202,7 +219,7 @@ export class Nodes {
      * @return {ESTree.MemberExpression}
      */
     public static getMemberExpressionNode (
-        object: ESTree.Identifier,
+        object: ESTree.Expression | ESTree.Super,
         property: ESTree.Identifier|ESTree.Literal,
         computed: boolean = false
     ): ESTree.MemberExpression {
@@ -279,6 +296,37 @@ export class Nodes {
         };
     }
 
+    /**
+     * @param discriminant
+     * @param cases
+     * @returns {ESTree.SwitchStatement}
+     */
+    public static getSwitchStatementNode (
+        discriminant: ESTree.Expression,
+        cases: ESTree.SwitchCase[]
+    ): ESTree.SwitchStatement {
+        return {
+            type: NodeType.SwitchStatement,
+            discriminant,
+            cases,
+            obfuscated: false
+        };
+    }
+
+    /**
+     * @param test
+     * @param consequent
+     * @returns {ESTree.SwitchCase}
+     */
+    public static getSwitchCaseNode (test: ESTree.Expression, consequent: ESTree.Statement[]): ESTree.SwitchCase {
+        return {
+            type: NodeType.SwitchCase,
+            test,
+            consequent,
+            obfuscated: false
+        };
+    }
+
     /**
      * @param declarations
      * @param kind

+ 1 - 1
src/storages/string-array/StringArrayStorage.ts

@@ -18,7 +18,7 @@ export class StringArrayStorage extends ArrayStorage <string> {
     public initialize (...args: any[]): void {
         super.initialize(args);
 
-        this.storageId = RandomGeneratorUtils.getRandomVariableName(4, false);
+        this.storageId = RandomGeneratorUtils.getRandomVariableName(4, false, false);
     }
 
     /**

+ 16 - 3
src/utils/RandomGeneratorUtils.ts

@@ -13,6 +13,11 @@ export class RandomGeneratorUtils {
      */
     public static readonly randomGeneratorPoolWithNumbers: string = `${RandomGeneratorUtils.randomGeneratorPool}0123456789`;
 
+    /**
+     * @type {Set<string>}
+     */
+    public static randomVariableNameSet: Set <string> = new Set();
+
     /**
      * @type {Chance.Chance | Chance.SeededChance}
      */
@@ -68,18 +73,26 @@ export class RandomGeneratorUtils {
     /**
      * @param length
      * @param withPrefix
+     * @param unique
      * @returns {string}
      */
-    public static getRandomVariableName (length: number = 6, withPrefix: boolean = true): string {
+    public static getRandomVariableName (length: number, withPrefix: boolean, unique: boolean): string {
         const prefix: string = withPrefix ? `_${Utils.hexadecimalPrefix}` : '';
         const rangeMinInteger: number = 10000;
         const rangeMaxInteger: number = 99999999;
-
-        return `${prefix}${(
+        const randomVariableName: string = `${prefix}${(
             Utils.decToHex(
                 RandomGeneratorUtils.getRandomInteger(rangeMinInteger, rangeMaxInteger)
             )
         ).substr(0, length)}`;
+
+        if (unique && RandomGeneratorUtils.randomVariableNameSet.has(randomVariableName)) {
+            return RandomGeneratorUtils.getRandomVariableName(length, withPrefix, unique);
+        }
+
+        RandomGeneratorUtils.randomVariableNameSet.add(randomVariableName);
+
+        return randomVariableName;
     }
 
     /**

+ 1 - 30
test/dev/dev.ts

@@ -49,41 +49,12 @@ if (!(<any>global)._babelPolyfill) {
                     
                     return abc.item = 15, test1();
                 };
-                
-                var regexptest = /version\\/(\\d+)/i;
-                console.log(regexptest);
-                
-                test2(22);
-                console.log(105.4);
-                console.log(true, false);
-                
-                var sA = 'shorthand1';
-                var sB = 'shorthand2';
-                
-                console.log({sA, sB});
-                
-                try {
-                } catch (error) {
-                    console.log(error);
-                }
-                
-                function foo () {
-                    return function () {
-                        var sum1 = 10 + 20;
-                        var sum2 = 20 + 30;
-                        var sum3 = 30 + 50;
-                        var sub = sum3 - sum2;
-                        
-                        return sum1 + sub;
-                    }
-                }
-                
-                console.log(foo()());
             })();
         `,
         {
             compact: false,
             controlFlowFlattening: true,
+            controlFlowFlatteningThreshold: 1,
             disableConsoleOutput: false
         }
     ).getObfuscatedCode();

+ 7 - 0
test/fixtures/node-transformers/node-control-flow-transformers/control-flow-replacers/call-expression-control-flow-replacer/call-expression-control-flow-replacer-1.js

@@ -0,0 +1,7 @@
+(function () {
+    function sum (a, b) {
+        return a + b;
+    }
+
+    var variable = sum(1, 2);
+})();

+ 8 - 0
test/fixtures/node-transformers/node-control-flow-transformers/control-flow-replacers/call-expression-control-flow-replacer/call-expression-control-flow-replacer-2.js

@@ -0,0 +1,8 @@
+(function () {
+    function sum (a, b) {
+        return a + b;
+    }
+
+    var variable1 = sum(1, 2);
+    var variable2 = sum(2, 3);
+})();

+ 9 - 0
test/fixtures/node-transformers/node-control-flow-transformers/control-flow-replacers/call-expression-control-flow-replacer/call-expression-control-flow-replacer-3.js

@@ -0,0 +1,9 @@
+(function () {
+    var object = {
+        sum: function (a, b) {
+            return a + b;
+        }
+    };
+
+    var variable = object.sum(1, 2);
+})();

+ 3 - 0
test/functional-tests/JavaScriptObfuscator.spec.ts

@@ -152,9 +152,12 @@ describe('JavaScriptObfuscator', () => {
             const obfuscationResult1: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code, { seed: seed }
             );
+            RandomGeneratorUtils.randomVariableNameSet.clear();
+
             const obfuscationResult2: IObfuscationResult = JavaScriptObfuscator.obfuscate(
                 code, { seed: seed }
             );
+            RandomGeneratorUtils.randomVariableNameSet.clear();
 
             assert.equal(obfuscationResult1.getObfuscatedCode(), obfuscationResult2.getObfuscatedCode());
         });

+ 96 - 0
test/functional-tests/node-transformers/node-control-flow-transformers/control-flow-replacers/CallExpressionControlFlowReplacer.spec.ts

@@ -0,0 +1,96 @@
+import { assert } from 'chai';
+
+import { IObfuscationResult } from '../../../../../src/interfaces/IObfuscationResult';
+
+import { NO_CUSTOM_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
+
+import { readFileAsString } from '../../../../helpers/readFileAsString';
+
+import { JavaScriptObfuscator } from '../../../../../src/JavaScriptObfuscator';
+
+describe('CallExpressionControlFlowReplacer', () => {
+    describe('replace (callExpressionNode: ESTree.CallExpression,parentNode: ESTree.Node,controlFlowStorage: IStorage <ICustomNode>)', () => {
+        describe('variant #1 - single call expression', () => {
+            const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                readFileAsString(
+                    './test/fixtures/node-transformers/node-control-flow-transformers/control-flow-replacers/call-expression-control-flow-replacer/call-expression-control-flow-replacer-1.js'
+                ),
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
+                    controlFlowFlattening: true,
+                    controlFlowFlatteningThreshold: 1
+                }
+            );
+            const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+            const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-z0-9]){4,6} *= *_0x([a-z0-9]){4,6}\['(\\x[a-f0-9]*){3}'\]\(_0x([a-z0-9]){4,6}, *0x1, *0x2\);/;
+
+            it('should replace call expression node by call to control flow storage node', () => {
+                assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
+            });
+        });
+
+        describe('variant #2 - multiple call expressions with threshold = 1', () => {
+            it('should replace call expression node by call to control flow storage node', function () {
+                this.timeout(4000);
+
+                const samplesCount: number = 200;
+                const expectedValue: number = 0.5;
+                const delta: number = 0.1;
+
+                let equalsValue: number = 0;
+
+                for (let i = 0; i < samplesCount; i++) {
+                    const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                        readFileAsString(
+                            './test/fixtures/node-transformers/node-control-flow-transformers/control-flow-replacers/call-expression-control-flow-replacer/call-expression-control-flow-replacer-2.js'
+                        ),
+                        {
+                            ...NO_CUSTOM_NODES_PRESET,
+                            controlFlowFlattening: true,
+                            controlFlowFlatteningThreshold: 1
+                        }
+                    );
+                    const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+                    const controlFlowStorageCallRegExp1: RegExp = /var *_0x([a-z0-9]){4,6} *= *(_0x([a-z0-9]){4,6}\['(\\x[a-f0-9]*){3}'\])\(_0x([a-z0-9]){4,6}, *0x1, *0x2\);/;
+                    const controlFlowStorageCallRegExp2: RegExp = /var *_0x([a-z0-9]){4,6} *= *(_0x([a-z0-9]){4,6}\['(\\x[a-f0-9]*){3}'\])\(_0x([a-z0-9]){4,6}, *0x2, *0x3\);/;
+
+                    const firstMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp1);
+                    const secondMatchArray: RegExpMatchArray | null = obfuscatedCode.match(controlFlowStorageCallRegExp2);
+
+                    const firstMatch: string | undefined = firstMatchArray ? firstMatchArray[2] : undefined;
+                    const secondMatch: string | undefined = secondMatchArray ? secondMatchArray[2] : undefined;
+
+                    assert.match(obfuscatedCode, controlFlowStorageCallRegExp1);
+                    assert.match(obfuscatedCode, controlFlowStorageCallRegExp2);
+                    assert.isOk(firstMatch);
+                    assert.isOk(secondMatch);
+
+                    if (firstMatch === secondMatch) {
+                        equalsValue++;
+                    }
+                }
+
+                assert.closeTo(equalsValue / samplesCount, expectedValue, delta);
+            });
+        });
+
+        describe('variant #3 - callee - member expression', () => {
+            const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
+                readFileAsString(
+                    './test/fixtures/node-transformers/node-control-flow-transformers/control-flow-replacers/call-expression-control-flow-replacer/call-expression-control-flow-replacer-3.js'
+                ),
+                {
+                    ...NO_CUSTOM_NODES_PRESET,
+                    controlFlowFlattening: true,
+                    controlFlowFlatteningThreshold: 1
+                }
+            );
+            const obfuscatedCode: string = obfuscationResult.getObfuscatedCode();
+            const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-z0-9]){4,6} *= *_0x([a-z0-9]){4,6}\['\\x73\\x75\\x6d'\]\(0x1, *0x2\);/;
+
+            it('shouldn\'t replace call expression node by call to control flow storage node if call expression callee is member expression node', () => {
+                assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
+            });
+        });
+    });
+});

+ 1 - 0
test/index.spec.ts

@@ -32,6 +32,7 @@ import './functional-tests/custom-nodes/string-array-nodes/StringArrayRotateFunc
 import './functional-tests/custom-nodes/string-array-nodes/StringArrayNode.spec';
 import './functional-tests/node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer.spec';
 import './functional-tests/node-transformers/node-control-flow-transformers/control-flow-replacers/BinaryExpressionControlFlowReplacer.spec';
+import './functional-tests/node-transformers/node-control-flow-transformers/control-flow-replacers/CallExpressionControlFlowReplacer.spec';
 import './functional-tests/node-transformers/node-control-flow-transformers/control-flow-replacers/LogicalExpressionControlFlowReplacer.spec';
 import './functional-tests/node-transformers/node-obfuscators/CatchClauseObfuscator.spec';
 import './functional-tests/node-transformers/node-obfuscators/FunctionDeclarationObfuscator.spec';

+ 2 - 2
test/unit-tests/utils/RandomGeneratorUtils.spec.ts

@@ -5,8 +5,8 @@ import { RandomGeneratorUtils } from '../../../src/utils/RandomGeneratorUtils';
 describe('RandomGeneratorUtils', () => {
     describe('getRandomVariableName (length: number = 6): string', () => {
         it('should return a string of given length with random variable name', () => {
-            assert.match(RandomGeneratorUtils.getRandomVariableName(4), /^_0x(\w){4}$/);
-            assert.match(RandomGeneratorUtils.getRandomVariableName(6), /^_0x(\w){4,6}$/);
+            assert.match(RandomGeneratorUtils.getRandomVariableName(4, true, false), /^_0x(\w){4}$/);
+            assert.match(RandomGeneratorUtils.getRandomVariableName(6, true, true), /^_0x(\w){4,6}$/);
         });
     });
 });

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است