浏览代码

Now transformers knows about its transformation stage

sanex3339 7 年之前
父节点
当前提交
2950613d44
共有 43 个文件被更改,包括 476 次插入349 次删除
  1. 0 0
      dist/index.js
  2. 32 56
      src/JavaScriptObfuscator.ts
  3. 1 10
      src/container/modules/node-transformers/FinalizingTransformersModule.ts
  4. 3 3
      src/container/modules/node-transformers/PreparingTransformersModule.ts
  5. 0 1
      src/declarations/ESTree.d.ts
  6. 2 7
      src/enums/logger/LoggingMessage.ts
  7. 1 2
      src/enums/node-transformers/NodeTransformer.ts
  8. 8 0
      src/enums/node-transformers/TransformationStage.ts
  9. 5 2
      src/interfaces/node-transformers/INodeTransformer.d.ts
  10. 7 1
      src/interfaces/node-transformers/ITransformersRunner.d.ts
  11. 5 2
      src/node-transformers/AbstractNodeTransformer.ts
  12. 10 3
      src/node-transformers/TransformersRunner.ts
  13. 17 9
      src/node-transformers/control-flow-transformers/BlockStatementControlFlowTransformer.ts
  14. 23 15
      src/node-transformers/control-flow-transformers/FunctionControlFlowTransformer.ts
  15. 17 9
      src/node-transformers/converting-transformers/MemberExpressionTransformer.ts
  16. 17 9
      src/node-transformers/converting-transformers/MethodDefinitionTransformer.ts
  17. 23 14
      src/node-transformers/converting-transformers/ObjectExpressionKeysTransformer.ts
  18. 18 9
      src/node-transformers/converting-transformers/TemplateLiteralTransformer.ts
  19. 26 17
      src/node-transformers/dead-code-injection-transformers/DeadCodeInjectionTransformer.ts
  20. 0 58
      src/node-transformers/finalizing-transformers/AstToEvalCallExpressionTransformer.ts
  21. 17 9
      src/node-transformers/obfuscating-transformers/CatchClauseTransformer.ts
  22. 17 9
      src/node-transformers/obfuscating-transformers/ClassDeclarationTransformer.ts
  23. 17 9
      src/node-transformers/obfuscating-transformers/FunctionDeclarationTransformer.ts
  24. 23 15
      src/node-transformers/obfuscating-transformers/FunctionTransformer.ts
  25. 17 9
      src/node-transformers/obfuscating-transformers/LabeledStatementTransformer.ts
  26. 17 9
      src/node-transformers/obfuscating-transformers/LiteralTransformer.ts
  27. 17 9
      src/node-transformers/obfuscating-transformers/ObjectExpressionTransformer.ts
  28. 17 9
      src/node-transformers/obfuscating-transformers/VariableDeclarationTransformer.ts
  29. 18 9
      src/node-transformers/preparing-transformers/CommentsTransformer.ts
  30. 68 19
      src/node-transformers/preparing-transformers/EvaCallExpressionTransformer.ts
  31. 15 7
      src/node-transformers/preparing-transformers/ObfuscatingGuardsTransformer.ts
  32. 16 7
      src/node-transformers/preparing-transformers/ParentificationTransformer.ts
  33. 1 1
      test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/EvalCallExpressionTransformer.spec.ts
  34. 0 0
      test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/call-expression-identifier-reference.js
  35. 0 0
      test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/control-flow-flattening-integration.js
  36. 0 0
      test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/eval-expression-as-argument.js
  37. 0 0
      test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/eval-expression-template-literal.js
  38. 0 0
      test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/identifier-reference.js
  39. 0 0
      test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/multiple-statements-eval.js
  40. 0 0
      test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/nested-eval-expressions.js
  41. 0 0
      test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/string-array-calls-wrapper-call.js
  42. 0 0
      test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/wrong-eval-string.js
  43. 1 1
      test/index.spec.ts

文件差异内容过多而无法显示
+ 0 - 0
dist/index.js


+ 32 - 56
src/JavaScriptObfuscator.ts

@@ -23,6 +23,7 @@ import { ITransformersRunner } from './interfaces/node-transformers/ITransformer
 import { LoggingMessage } from './enums/logger/LoggingMessage';
 import { NodeTransformer } from './enums/node-transformers/NodeTransformer';
 import { ObfuscationEvent } from './enums/event-emitters/ObfuscationEvent';
+import { TransformationStage } from './enums/node-transformers/TransformationStage';
 
 import { NodeGuards } from './node/NodeGuards';
 
@@ -40,59 +41,28 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
     /**
      * @type {NodeTransformer[]}
      */
-    private static readonly controlFlowTransformersList: NodeTransformer[] = [
+    private static readonly transformersList: NodeTransformer[] = [
         NodeTransformer.BlockStatementControlFlowTransformer,
-        NodeTransformer.FunctionControlFlowTransformer
-    ];
-
-    /**
-     * @type {NodeTransformer[]}
-     */
-    private static readonly convertingTransformersList: NodeTransformer[] = [
-        NodeTransformer.MemberExpressionTransformer,
-        NodeTransformer.MethodDefinitionTransformer,
-        NodeTransformer.ObjectExpressionKeysTransformer,
-        NodeTransformer.TemplateLiteralTransformer
-    ];
-
-    /**
-     * @type {NodeTransformer[]}
-     */
-    private static readonly deadCodeInjectionTransformersList: NodeTransformer[] = [
-        NodeTransformer.DeadCodeInjectionTransformer
-    ];
-
-    /**
-     * @type {NodeTransformer[]}
-     */
-    private static readonly finalizingTransformersList: NodeTransformer[] = [
-        NodeTransformer.AstToEvalCallExpressionTransformer
-    ];
-
-    /**
-     * @type {NodeTransformer[]}
-     */
-    private static readonly obfuscatingTransformersList: NodeTransformer[] = [
-        NodeTransformer.CatchClauseTransformer,
         NodeTransformer.ClassDeclarationTransformer,
+        NodeTransformer.CommentsTransformer,
+        NodeTransformer.DeadCodeInjectionTransformer,
+        NodeTransformer.EvalCallExpressionTransformer,
+        NodeTransformer.FunctionControlFlowTransformer,
+        NodeTransformer.CatchClauseTransformer,
         NodeTransformer.FunctionDeclarationTransformer,
         NodeTransformer.FunctionTransformer,
         NodeTransformer.LabeledStatementTransformer,
         NodeTransformer.LiteralTransformer,
+        NodeTransformer.MemberExpressionTransformer,
+        NodeTransformer.MethodDefinitionTransformer,
+        NodeTransformer.ObfuscatingGuardsTransformer,
+        NodeTransformer.ObjectExpressionKeysTransformer,
         NodeTransformer.ObjectExpressionTransformer,
+        NodeTransformer.ParentificationTransformer,
+        NodeTransformer.TemplateLiteralTransformer,
         NodeTransformer.VariableDeclarationTransformer
     ];
 
-    /**
-     * @type {NodeTransformer[]}
-     */
-    private static readonly preparingTransformersList: NodeTransformer[] = [
-        NodeTransformer.CommentsTransformer,
-        NodeTransformer.EvalCallExpressionToAstTransformer,
-        NodeTransformer.ObfuscatingGuardsTransformer,
-        NodeTransformer.ParentificationTransformer
-    ];
-
     /**
      * @type {IStorage<ICustomNodeGroup>}
      */
@@ -215,14 +185,15 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
         }
 
         // first pass: AST-tree preparation
-        this.logger.info(LoggingMessage.StagePreparingASTTree);
+        this.logger.info(LoggingMessage.TransformationStage, TransformationStage.Preparing);
         astTree = this.transformersRunner.transform(
             astTree,
-            JavaScriptObfuscator.preparingTransformersList
+            JavaScriptObfuscator.transformersList,
+            TransformationStage.Preparing
         );
 
         // second pass: AST-tree analyzing
-        this.logger.info(LoggingMessage.StageAnalyzingASTTree);
+        this.logger.info(LoggingMessage.AnalyzingASTTreeStage);
         const stackTraceData: IStackTraceData[] = this.stackTraceAnalyzer.analyze(astTree);
 
         // initialize custom node groups and configure custom nodes
@@ -241,43 +212,48 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
 
         // third pass: dead code injection transformer
         if (this.options.deadCodeInjection) {
-            this.logger.info(LoggingMessage.StageDeadCodeInjection);
+            this.logger.info(LoggingMessage.TransformationStage, TransformationStage.DeadCodeInjection);
 
             astTree = this.transformersRunner.transform(
                 astTree,
-                JavaScriptObfuscator.deadCodeInjectionTransformersList
+                JavaScriptObfuscator.transformersList,
+                TransformationStage.DeadCodeInjection
             );
         }
 
         // fourth pass: control flow flattening transformers
         if (this.options.controlFlowFlattening) {
-            this.logger.info(LoggingMessage.StageControlFlowFlattening);
+            this.logger.info(LoggingMessage.TransformationStage, TransformationStage.ControlFlowFlattening);
 
             astTree = this.transformersRunner.transform(
                 astTree,
-                JavaScriptObfuscator.controlFlowTransformersList
+                JavaScriptObfuscator.transformersList,
+                TransformationStage.ControlFlowFlattening
             );
         }
 
         // fifth pass: converting transformers
-        this.logger.info(LoggingMessage.StagePreObfuscation);
+        this.logger.info(LoggingMessage.TransformationStage, TransformationStage.Converting);
         astTree = this.transformersRunner.transform(
             astTree,
-            JavaScriptObfuscator.convertingTransformersList
+            JavaScriptObfuscator.transformersList,
+            TransformationStage.Converting
         );
 
         // sixth pass: obfuscating transformers
-        this.logger.info(LoggingMessage.StageObfuscation);
+        this.logger.info(LoggingMessage.TransformationStage, TransformationStage.Obfuscating);
         astTree = this.transformersRunner.transform(
             astTree,
-            JavaScriptObfuscator.obfuscatingTransformersList
+            JavaScriptObfuscator.transformersList,
+            TransformationStage.Obfuscating
         );
 
         // seventh pass: finalizing transformers
-        this.logger.info(LoggingMessage.StagePostObfuscation);
+        this.logger.info(LoggingMessage.TransformationStage, TransformationStage.Finalizing);
         astTree = this.transformersRunner.transform(
             astTree,
-            JavaScriptObfuscator.finalizingTransformersList
+            JavaScriptObfuscator.transformersList,
+            TransformationStage.Finalizing
         );
 
         this.obfuscationEventEmitter.emit(ObfuscationEvent.AfterObfuscation, astTree, stackTraceData);

+ 1 - 10
src/container/modules/node-transformers/FinalizingTransformersModule.ts

@@ -1,15 +1,6 @@
 import { ContainerModule, interfaces } from 'inversify';
-import { ServiceIdentifiers } from '../../ServiceIdentifiers';
-
-import { INodeTransformer } from '../../../interfaces/node-transformers/INodeTransformer';
-
-import { NodeTransformer } from '../../../enums/node-transformers/NodeTransformer';
-
-import { AstToEvalCallExpressionTransformer } from '../../../node-transformers/finalizing-transformers/AstToEvalCallExpressionTransformer';
 
 export const finalizingTransformersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
     // finalizing transformers
-    bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
-        .to(AstToEvalCallExpressionTransformer)
-        .whenTargetNamed(NodeTransformer.AstToEvalCallExpressionTransformer);
+
 });

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

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

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

@@ -5,7 +5,6 @@ import * as ESTree from 'estree';
 declare module 'estree' {
     interface BaseNode {
         ignoredNode?: boolean;
-        isEvalRoot?: boolean;
         obfuscatedNode?: boolean;
         parentNode?: ESTree.Node;
     }

+ 2 - 7
src/enums/logger/LoggingMessage.ts

@@ -1,14 +1,9 @@
 export enum LoggingMessage {
+    AnalyzingASTTreeStage = 'Stage: analyzing AST-tree...',
     EmptySourceCode = 'Empty source code. Obfuscation canceled...',
     ObfuscationCompleted = 'Obfuscation completed. Total time: %s sec.',
     ObfuscationStarted = 'Obfuscation started...',
     RandomGeneratorSeed = 'Random generator seed: %s...',
-    StagePreparingASTTree = 'Stage: preparing AST-tree...',
-    StageAnalyzingASTTree = 'Stage: analyzing AST-tree...',
-    StageControlFlowFlattening = 'Stage: control flow flattening...',
-    StageDeadCodeInjection = 'Stage: dead code injection...',
-    StagePostObfuscation = 'Stage: post-obfuscation...',
-    StagePreObfuscation = 'Stage: pre-obfuscation...',
-    StageObfuscation = 'Stage: obfuscation...',
+    TransformationStage = 'Transformation stage: %s...',
     Version = 'Version: %s'
 }

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

@@ -1,10 +1,9 @@
 export enum NodeTransformer {
-    AstToEvalCallExpressionTransformer = 'AstToEvalCallExpressionTransformer',
     BlockStatementControlFlowTransformer = 'BlockStatementControlFlowTransformer',
     ClassDeclarationTransformer = 'ClassDeclarationTransformer',
     CommentsTransformer = 'CommentsTransformer',
     DeadCodeInjectionTransformer = 'DeadCodeInjectionTransformer',
-    EvalCallExpressionToAstTransformer = 'EvalCallExpressionToAstTransformer',
+    EvalCallExpressionTransformer = 'EvalCallExpressionTransformer',
     FunctionControlFlowTransformer = 'FunctionControlFlowTransformer',
     CatchClauseTransformer = 'CatchClauseTransformer',
     FunctionDeclarationTransformer = 'FunctionDeclarationTransformer',

+ 8 - 0
src/enums/node-transformers/TransformationStage.ts

@@ -0,0 +1,8 @@
+export enum TransformationStage {
+    Preparing = 'Preparing',
+    DeadCodeInjection = 'DeadCodeInjection',
+    ControlFlowFlattening = 'ControlFlowFlattening',
+    Converting = 'Converting',
+    Obfuscating = 'Obfuscating',
+    Finalizing = 'Finalizing'
+}

+ 5 - 2
src/interfaces/node-transformers/INodeTransformer.d.ts

@@ -3,11 +3,14 @@ import * as ESTree from 'estree';
 
 import { IVisitor } from './IVisitor';
 
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
+
 export interface INodeTransformer {
     /**
-     * @returns {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    getVisitor (): IVisitor;
+    getVisitor (transformationStage: TransformationStage): IVisitor | null;
 
     /**
      * @param {Node} node

+ 7 - 1
src/interfaces/node-transformers/ITransformersRunner.d.ts

@@ -1,12 +1,18 @@
 import * as ESTree from 'estree';
 
 import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 export interface ITransformersRunner {
     /**
      * @param {T} astTree
      * @param {NodeTransformer[]} nodeTransformers
+     * @param {TransformationStage} transformationStage
      * @returns {T}
      */
-    transform <T extends ESTree.Node = ESTree.Program> (astTree: T, nodeTransformers: NodeTransformer[]): T;
+    transform <T extends ESTree.Node = ESTree.Program> (
+        astTree: T,
+        nodeTransformers: NodeTransformer[],
+        transformationStage: TransformationStage
+    ): T;
 }

+ 5 - 2
src/node-transformers/AbstractNodeTransformer.ts

@@ -12,6 +12,8 @@ import { IVisitor } from '../interfaces/node-transformers/IVisitor';
 
 import { initializable } from '../decorators/Initializable';
 
+import { TransformationStage } from '../enums/node-transformers/TransformationStage';
+
 @injectable()
 export abstract class AbstractNodeTransformer implements INodeTransformer, IInitializable {
     /**
@@ -48,9 +50,10 @@ export abstract class AbstractNodeTransformer implements INodeTransformer, IInit
     }
 
     /**
-     * @returns {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public abstract getVisitor (): IVisitor;
+    public abstract getVisitor (transformationStage: TransformationStage): IVisitor | null;
 
     /**
      * @param {Node} node

+ 10 - 3
src/node-transformers/TransformersRunner.ts

@@ -13,6 +13,7 @@ import { ITransformersRunner } from '../interfaces/node-transformers/ITransforme
 import { IVisitor } from '../interfaces/node-transformers/IVisitor';
 
 import { NodeTransformer } from '../enums/node-transformers/NodeTransformer';
+import { TransformationStage } from '../enums/node-transformers/TransformationStage';
 import { VisitorDirection } from '../enums/node-transformers/VisitorDirection';
 
 import { NodeGuards } from '../node/NodeGuards';
@@ -36,11 +37,13 @@ export class TransformersRunner implements ITransformersRunner {
     /**
      * @param {T} astTree
      * @param {NodeTransformer[]} nodeTransformers
+     * @param {TransformationStage} transformationStage
      * @returns {T}
      */
     public transform <T extends ESTree.Node = ESTree.Program> (
         astTree: T,
-        nodeTransformers: NodeTransformer[]
+        nodeTransformers: NodeTransformer[],
+        transformationStage: TransformationStage
     ): T {
         if (!nodeTransformers.length) {
             return astTree;
@@ -50,10 +53,14 @@ export class TransformersRunner implements ITransformersRunner {
         const leaveVisitors: IVisitor[] = [];
         const nodeTransformersLength: number = nodeTransformers.length;
 
-        let visitor: IVisitor;
+        let visitor: IVisitor | null;
 
         for (let i: number = 0; i < nodeTransformersLength; i++) {
-            visitor = this.nodeTransformerFactory(nodeTransformers[i]).getVisitor();
+            visitor = this.nodeTransformerFactory(nodeTransformers[i]).getVisitor(transformationStage);
+
+            if (!visitor) {
+                continue;
+            }
 
             if (visitor.enter) {
                 enterVisitors.push(visitor);

+ 17 - 9
src/node-transformers/control-flow-transformers/BlockStatementControlFlowTransformer.ts

@@ -14,6 +14,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
 import { ControlFlowCustomNode } from '../../enums/custom-nodes/ControlFlowCustomNode';
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
@@ -97,16 +98,23 @@ export class BlockStatementControlFlowTransformer extends AbstractNodeTransforme
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            leave: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (parentNode && NodeGuards.isBlockStatementNode(node)) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.ControlFlowFlattening:
+                return {
+                    leave: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (parentNode && NodeGuards.isBlockStatementNode(node)) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 23 - 15
src/node-transformers/control-flow-transformers/FunctionControlFlowTransformer.ts

@@ -18,6 +18,7 @@ import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 import { ControlFlowCustomNode } from '../../enums/custom-nodes/ControlFlowCustomNode';
 import { ControlFlowReplacer } from '../../enums/node-transformers/obfuscating-transformers/obfuscating-replacers/ControlFlowReplacer';
 import { NodeType } from '../../enums/node/NodeType';
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
@@ -101,22 +102,29 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            leave: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (
-                    parentNode && (
-                        NodeGuards.isFunctionDeclarationNode(node) ||
-                        NodeGuards.isFunctionExpressionNode(node) ||
-                        NodeGuards.isArrowFunctionExpressionNode(node)
-                    )
-                ) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.ControlFlowFlattening:
+                return {
+                    leave: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (
+                            parentNode && (
+                                NodeGuards.isFunctionDeclarationNode(node) ||
+                                NodeGuards.isFunctionExpressionNode(node) ||
+                                NodeGuards.isArrowFunctionExpressionNode(node)
+                            )
+                        ) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 17 - 9
src/node-transformers/converting-transformers/MemberExpressionTransformer.ts

@@ -8,6 +8,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
 import { NodeType } from '../../enums/node/NodeType';
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
@@ -26,16 +27,23 @@ export class MemberExpressionTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (parentNode && NodeGuards.isMemberExpressionNode(node)) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Converting:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (parentNode && NodeGuards.isMemberExpressionNode(node)) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 17 - 9
src/node-transformers/converting-transformers/MethodDefinitionTransformer.ts

@@ -8,6 +8,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
 import { NodeType } from '../../enums/node/NodeType';
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
@@ -40,16 +41,23 @@ export class MethodDefinitionTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (parentNode && NodeGuards.isMethodDefinitionNode(node)) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Converting:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (parentNode && NodeGuards.isMethodDefinitionNode(node)) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 23 - 14
src/node-transformers/converting-transformers/ObjectExpressionKeysTransformer.ts

@@ -9,6 +9,8 @@ import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
+
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeAppender } from '../../node/NodeAppender';
 import { NodeGuards } from '../../node/NodeGuards';
@@ -62,21 +64,28 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (
-                    this.options.transformObjectKeys
-                    && parentNode
-                    && NodeGuards.isObjectExpressionNode(node)
-                    && NodeGuards.isVariableDeclaratorNode(parentNode)
-                ) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Converting:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (
+                            this.options.transformObjectKeys
+                            && parentNode
+                            && NodeGuards.isObjectExpressionNode(node)
+                            && NodeGuards.isVariableDeclaratorNode(parentNode)
+                        ) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 18 - 9
src/node-transformers/converting-transformers/TemplateLiteralTransformer.ts

@@ -7,6 +7,8 @@ import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
+
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
 import { Nodes } from '../../node/Nodes';
@@ -37,16 +39,23 @@ export class TemplateLiteralTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (parentNode && NodeGuards.isTemplateLiteralNode(node)) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Converting:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (parentNode && NodeGuards.isTemplateLiteralNode(node)) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 26 - 17
src/node-transformers/dead-code-injection-transformers/DeadCodeInjectionTransformer.ts

@@ -16,6 +16,7 @@ import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 import { DeadCodeInjectionCustomNode } from '../../enums/custom-nodes/DeadCodeInjectionCustomNode';
 import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';
 import { NodeType } from '../../enums/node/NodeType';
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
@@ -96,23 +97,30 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (parentNode && NodeGuards.isProgramNode(node)) {
-                    this.analyzeNode(node, parentNode);
-
-                    return node;
-                }
-            },
-            leave: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (parentNode && NodeGuards.isBlockStatementNode(node)) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.DeadCodeInjection:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (parentNode && NodeGuards.isProgramNode(node)) {
+                            this.analyzeNode(node, parentNode);
+
+                            return node;
+                        }
+                    },
+                    leave: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (parentNode && NodeGuards.isBlockStatementNode(node)) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**
@@ -218,7 +226,8 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
         NodeUtils.parentizeNode(clonedBlockStatementNode, parentNode);
         clonedBlockStatementNode = this.transformersRunner.transform(
             clonedBlockStatementNode,
-            DeadCodeInjectionTransformer.transformersToRenameBlockScopeIdentifiers
+            DeadCodeInjectionTransformer.transformersToRenameBlockScopeIdentifiers,
+            TransformationStage.Obfuscating
         );
 
         collectedBlockStatements.push(clonedBlockStatementNode);

+ 0 - 58
src/node-transformers/finalizing-transformers/AstToEvalCallExpressionTransformer.ts

@@ -1,58 +0,0 @@
-import { inject, injectable, } from 'inversify';
-import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
-
-import * as ESTree from 'estree';
-import jsStringEscape = require('js-string-escape');
-
-import { IOptions } from '../../interfaces/options/IOptions';
-import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
-import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
-
-import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
-import { NodeGuards } from '../../node/NodeGuards';
-import { Nodes } from '../../node/Nodes';
-import { NodeUtils } from '../../node/NodeUtils';
-
-@injectable()
-export class AstToEvalCallExpressionTransformer extends AbstractNodeTransformer {
-    /**
-     * @param {IRandomGenerator} randomGenerator
-     * @param {IOptions} options
-     */
-    constructor (
-        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
-        @inject(ServiceIdentifiers.IOptions) options: IOptions
-    ) {
-        super(randomGenerator, options);
-    }
-
-    /**
-     * @return {IVisitor}
-     */
-    public getVisitor (): IVisitor {
-        return {
-            leave: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (parentNode && node.isEvalRoot && NodeGuards.isFunctionExpressionNode(node)) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
-    }
-
-    /**
-     * @param {FunctionExpression} evalRootAstHostNode
-     * @param {Node} parentNode
-     * @returns {Node}
-     */
-    public transformNode (evalRootAstHostNode: ESTree.FunctionExpression, parentNode: ESTree.Node): ESTree.Node {
-        const targetAst: ESTree.Statement[] = evalRootAstHostNode.body.body;
-        const obfuscatedCode: string = NodeUtils.convertStructureToCode(targetAst);
-
-        return Nodes.getCallExpressionNode(
-            Nodes.getIdentifierNode('eval'),
-            [
-                Nodes.getLiteralNode(jsStringEscape(obfuscatedCode))
-            ]
-        );
-    }
-}

+ 17 - 9
src/node-transformers/obfuscating-transformers/CatchClauseTransformer.ts

@@ -12,6 +12,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
 import { IdentifierObfuscatingReplacer } from '../../enums/node-transformers/obfuscating-transformers/obfuscating-replacers/IdentifierObfuscatingReplacer';
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
@@ -50,16 +51,23 @@ export class CatchClauseTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (parentNode && NodeGuards.isCatchClauseNode(node)) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Obfuscating:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (parentNode && NodeGuards.isCatchClauseNode(node)) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 17 - 9
src/node-transformers/obfuscating-transformers/ClassDeclarationTransformer.ts

@@ -14,6 +14,7 @@ import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
 import { IdentifierObfuscatingReplacer } from "../../enums/node-transformers/obfuscating-transformers/obfuscating-replacers/IdentifierObfuscatingReplacer";
 import { NodeType } from '../../enums/node/NodeType';
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
@@ -59,16 +60,23 @@ export class ClassDeclarationTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (parentNode && NodeGuards.isClassDeclarationNode(node)) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Obfuscating:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (parentNode && NodeGuards.isClassDeclarationNode(node)) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 17 - 9
src/node-transformers/obfuscating-transformers/FunctionDeclarationTransformer.ts

@@ -16,6 +16,7 @@ import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
 import { IdentifierObfuscatingReplacer } from "../../enums/node-transformers/obfuscating-transformers/obfuscating-replacers/IdentifierObfuscatingReplacer";
 import { NodeType } from '../../enums/node/NodeType';
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
@@ -61,16 +62,23 @@ export class FunctionDeclarationTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (parentNode && NodeGuards.isFunctionDeclarationNode(node)) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Obfuscating:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (parentNode && NodeGuards.isFunctionDeclarationNode(node)) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 23 - 15
src/node-transformers/obfuscating-transformers/FunctionTransformer.ts

@@ -12,6 +12,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
 import { IdentifierObfuscatingReplacer } from '../../enums/node-transformers/obfuscating-transformers/obfuscating-replacers/IdentifierObfuscatingReplacer';
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
@@ -50,22 +51,29 @@ export class FunctionTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (
-                    parentNode && (
-                        NodeGuards.isFunctionDeclarationNode(node) ||
-                        NodeGuards.isFunctionExpressionNode(node) ||
-                        NodeGuards.isArrowFunctionExpressionNode(node)
-                    )
-                ) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Obfuscating:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (
+                            parentNode && (
+                                NodeGuards.isFunctionDeclarationNode(node) ||
+                                NodeGuards.isFunctionExpressionNode(node) ||
+                                NodeGuards.isArrowFunctionExpressionNode(node)
+                            )
+                        ) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 17 - 9
src/node-transformers/obfuscating-transformers/LabeledStatementTransformer.ts

@@ -12,6 +12,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
 import { IdentifierObfuscatingReplacer } from '../../enums/node-transformers/obfuscating-transformers/obfuscating-replacers/IdentifierObfuscatingReplacer';
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
@@ -58,16 +59,23 @@ export class LabeledStatementTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (parentNode && NodeGuards.isLabeledStatementNode(node)) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Obfuscating:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (parentNode && NodeGuards.isLabeledStatementNode(node)) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 17 - 9
src/node-transformers/obfuscating-transformers/LiteralTransformer.ts

@@ -10,6 +10,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
 import { LiteralObfuscatingReplacer } from '../../enums/node-transformers/obfuscating-transformers/obfuscating-replacers/LiteralObfuscatingReplacer';
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
@@ -38,16 +39,23 @@ export class LiteralTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (parentNode && NodeGuards.isLiteralNode(node) && !node.obfuscatedNode) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Obfuscating:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (parentNode && NodeGuards.isLiteralNode(node) && !node.obfuscatedNode) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 17 - 9
src/node-transformers/obfuscating-transformers/ObjectExpressionTransformer.ts

@@ -8,6 +8,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
 import { NodeType } from '../../enums/node/NodeType';
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
@@ -45,16 +46,23 @@ export class ObjectExpressionTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (parentNode && NodeGuards.isObjectExpressionNode(node)) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Obfuscating:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (parentNode && NodeGuards.isObjectExpressionNode(node)) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 17 - 9
src/node-transformers/obfuscating-transformers/VariableDeclarationTransformer.ts

@@ -16,6 +16,7 @@ import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
 import { IdentifierObfuscatingReplacer } from "../../enums/node-transformers/obfuscating-transformers/obfuscating-replacers/IdentifierObfuscatingReplacer";
 import { NodeType } from '../../enums/node/NodeType';
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
@@ -62,16 +63,23 @@ export class VariableDeclarationTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (parentNode && NodeGuards.isVariableDeclarationNode(node)) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Obfuscating:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (parentNode && NodeGuards.isVariableDeclarationNode(node)) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 18 - 9
src/node-transformers/preparing-transformers/CommentsTransformer.ts

@@ -7,6 +7,8 @@ import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
+
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
 
@@ -29,16 +31,23 @@ export class CommentsTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            leave: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (parentNode && NodeGuards.isNodeWithComments(node)) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Preparing:
+                return {
+                    leave: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (parentNode && NodeGuards.isNodeWithComments(node)) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 68 - 19
src/node-transformers/preparing-transformers/EvaCallExpressionToAstTransformer.ts → src/node-transformers/preparing-transformers/EvaCallExpressionTransformer.ts

@@ -2,6 +2,7 @@ import { inject, injectable, } from 'inversify';
 import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
 
 import * as ESTree from 'estree';
+import jsStringEscape = require('js-string-escape');
 
 import { TStatement } from '../../types/node/TStatement';
 
@@ -9,13 +10,20 @@ import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
+
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeGuards } from '../../node/NodeGuards';
 import { Nodes } from '../../node/Nodes';
 import { NodeUtils } from '../../node/NodeUtils';
 
 @injectable()
-export class EvalCallExpressionToAstTransformer extends AbstractNodeTransformer {
+export class EvalCallExpressionTransformer extends AbstractNodeTransformer {
+    /**
+     * @type {WeakSet <FunctionExpression>}
+     */
+    private readonly evalRootAstHostNodeStorage: WeakSet <ESTree.FunctionExpression> = new WeakSet();
+
     /**
      * @param {IRandomGenerator} randomGenerator
      * @param {IOptions} options
@@ -33,12 +41,12 @@ export class EvalCallExpressionToAstTransformer extends AbstractNodeTransformer
      */
     private static extractEvalStringFromCallExpressionArgument (node: ESTree.Expression | ESTree.SpreadElement): string | null {
         if (NodeGuards.isLiteralNode(node)) {
-            return EvalCallExpressionToAstTransformer
+            return EvalCallExpressionTransformer
                 .extractEvalStringFromLiteralNode(node);
         }
 
         if (NodeGuards.isTemplateLiteralNode(node)) {
-            return EvalCallExpressionToAstTransformer
+            return EvalCallExpressionTransformer
                 .extractEvalStringFromTemplateLiteralNode(node);
         }
 
@@ -69,21 +77,37 @@ export class EvalCallExpressionToAstTransformer extends AbstractNodeTransformer
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                if (
-                    parentNode
-                    && NodeGuards.isCallExpressionNode(node)
-                    && NodeGuards.isIdentifierNode(node.callee)
-                    && node.callee.name === 'eval'
-                ) {
-                    return this.transformNode(node, parentNode);
-                }
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Preparing:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (
+                            parentNode
+                            && NodeGuards.isCallExpressionNode(node)
+                            && NodeGuards.isIdentifierNode(node.callee)
+                            && node.callee.name === 'eval'
+                        ) {
+                            return this.transformNode(node, parentNode);
+                        }
+                    }
+                };
+
+            case TransformationStage.Finalizing:
+                return {
+                    leave: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        if (parentNode && this.isEvalRootAstHostNode(node)) {
+                            return this.restoreEvalExpressionNode(node, parentNode);
+                        }
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**
@@ -98,7 +122,7 @@ export class EvalCallExpressionToAstTransformer extends AbstractNodeTransformer
             return callExpressionNode;
         }
 
-        const evalString: string | null = EvalCallExpressionToAstTransformer
+        const evalString: string | null = EvalCallExpressionTransformer
             .extractEvalStringFromCallExpressionArgument(callExpressionFirstArgument);
 
         if (!evalString) {
@@ -117,8 +141,33 @@ export class EvalCallExpressionToAstTransformer extends AbstractNodeTransformer
         const evalRootAstHostNode: ESTree.FunctionExpression = Nodes
             .getFunctionExpressionNode([], Nodes.getBlockStatementNode(<any>ast));
 
-        evalRootAstHostNode.isEvalRoot = true;
+        this.evalRootAstHostNodeStorage.add(evalRootAstHostNode);
 
         return evalRootAstHostNode;
     }
+
+    /**
+     * @param {Node} node
+     * @returns {boolean}
+     */
+    private isEvalRootAstHostNode (node: ESTree.Node): node is ESTree.FunctionExpression {
+        return NodeGuards.isFunctionExpressionNode(node) && this.evalRootAstHostNodeStorage.has(node);
+    }
+
+    /**
+     * @param {FunctionExpression} evalRootAstHostNode
+     * @param {Node} parentNode
+     * @returns {Node}
+     */
+    private restoreEvalExpressionNode (evalRootAstHostNode: ESTree.FunctionExpression, parentNode: ESTree.Node): ESTree.Node {
+        const targetAst: ESTree.Statement[] = evalRootAstHostNode.body.body;
+        const obfuscatedCode: string = NodeUtils.convertStructureToCode(targetAst);
+
+        return Nodes.getCallExpressionNode(
+            Nodes.getIdentifierNode('eval'),
+            [
+                Nodes.getLiteralNode(jsStringEscape(obfuscatedCode))
+            ]
+        );
+    }
 }

+ 15 - 7
src/node-transformers/preparing-transformers/ObfuscatingGuardsTransformer.ts

@@ -11,6 +11,7 @@ import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
 import { ObfuscatingGuard } from '../../enums/node-transformers/preparing-transformers/obfuscating-guards/ObfuscatingGuard';
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
 
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 
@@ -48,14 +49,21 @@ export class ObfuscatingGuardsTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                return this.transformNode(node, parentNode);
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Preparing:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        return this.transformNode(node, parentNode);
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 16 - 7
src/node-transformers/preparing-transformers/ParentificationTransformer.ts

@@ -7,6 +7,8 @@ import { IOptions } from '../../interfaces/options/IOptions';
 import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
 import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
 
+import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
+
 import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
 import { NodeUtils } from '../../node/NodeUtils';
 
@@ -27,14 +29,21 @@ export class ParentificationTransformer extends AbstractNodeTransformer {
     }
 
     /**
-     * @return {IVisitor}
+     * @param {TransformationStage} transformationStage
+     * @returns {IVisitor | null}
      */
-    public getVisitor (): IVisitor {
-        return {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
-                return this.transformNode(node, parentNode);
-            }
-        };
+    public getVisitor (transformationStage: TransformationStage): IVisitor | null {
+        switch (transformationStage) {
+            case TransformationStage.Preparing:
+                return {
+                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
+                        return this.transformNode(node, parentNode);
+                    }
+                };
+
+            default:
+                return null;
+        }
     }
 
     /**

+ 1 - 1
test/functional-tests/node-transformers/finalizing-transformers/ast-to-eval-call-expression-transformer/AstToEvalCallExpressionTransformer.spec.ts → test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/EvalCallExpressionTransformer.spec.ts

@@ -9,7 +9,7 @@ import { readFileAsString } from '../../../../helpers/readFileAsString';
 import { JavaScriptObfuscator } from '../../../../../src/JavaScriptObfuscatorFacade';
 import { getRegExpMatch } from '../../../../helpers/getRegExpMatch';
 
-describe('AstToEvalCallExpressionTransformer', () => {
+describe('EvalCallExpressionTransformer', () => {
     describe('variant #1: identifier reference', () => {
         const functionIdentifierRegExp: RegExp = /function *_0x(?:[a-f0-9]){4,6} *\((_0x(?:[a-f0-9]){4,6})\)/;
         const evalExpressionRegExp: RegExp = /eval *\('(_0x(?:[a-f0-9]){4,6});'\);/;

+ 0 - 0
test/functional-tests/node-transformers/finalizing-transformers/ast-to-eval-call-expression-transformer/fixtures/call-expression-identifier-reference.js → test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/call-expression-identifier-reference.js


+ 0 - 0
test/functional-tests/node-transformers/finalizing-transformers/ast-to-eval-call-expression-transformer/fixtures/control-flow-flattening-integration.js → test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/control-flow-flattening-integration.js


+ 0 - 0
test/functional-tests/node-transformers/finalizing-transformers/ast-to-eval-call-expression-transformer/fixtures/eval-expression-as-argument.js → test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/eval-expression-as-argument.js


+ 0 - 0
test/functional-tests/node-transformers/finalizing-transformers/ast-to-eval-call-expression-transformer/fixtures/eval-expression-template-literal.js → test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/eval-expression-template-literal.js


+ 0 - 0
test/functional-tests/node-transformers/finalizing-transformers/ast-to-eval-call-expression-transformer/fixtures/identifier-reference.js → test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/identifier-reference.js


+ 0 - 0
test/functional-tests/node-transformers/finalizing-transformers/ast-to-eval-call-expression-transformer/fixtures/multiple-statements-eval.js → test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/multiple-statements-eval.js


+ 0 - 0
test/functional-tests/node-transformers/finalizing-transformers/ast-to-eval-call-expression-transformer/fixtures/nested-eval-expressions.js → test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/nested-eval-expressions.js


+ 0 - 0
test/functional-tests/node-transformers/finalizing-transformers/ast-to-eval-call-expression-transformer/fixtures/string-array-calls-wrapper-call.js → test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/string-array-calls-wrapper-call.js


+ 0 - 0
test/functional-tests/node-transformers/finalizing-transformers/ast-to-eval-call-expression-transformer/fixtures/wrong-eval-string.js → test/functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/fixtures/wrong-eval-string.js


+ 1 - 1
test/index.spec.ts

@@ -56,7 +56,6 @@ import './functional-tests/node-transformers/converting-transformers/method-defi
 import './functional-tests/node-transformers/converting-transformers/object-expression-keys-transformer/ObjectExpressionKeysTransformer.spec';
 import './functional-tests/node-transformers/converting-transformers/template-literal-transformer/TemplateLiteralTransformer.spec';
 import './functional-tests/node-transformers/dead-code-injection-transformers/DeadCodeInjectionTransformer.spec';
-import './functional-tests/node-transformers/finalizing-transformers/ast-to-eval-call-expression-transformer/AstToEvalCallExpressionTransformer.spec';
 import './functional-tests/node-transformers/obfuscating-transformers/catch-clause-transformer/CatchClauseTransformer.spec';
 import './functional-tests/node-transformers/obfuscating-transformers/class-declaration-transformer/ClassDeclarationTransformer.spec';
 import './functional-tests/node-transformers/obfuscating-transformers/function-declaration-transformer/FunctionDeclarationTransformer.spec';
@@ -65,6 +64,7 @@ import './functional-tests/node-transformers/obfuscating-transformers/labeled-st
 import './functional-tests/node-transformers/obfuscating-transformers/literal-transformer/LiteralTransformer.spec';
 import './functional-tests/node-transformers/obfuscating-transformers/object-expression-transformer/ObjectExpressionTransformer.spec';
 import './functional-tests/node-transformers/obfuscating-transformers/variable-declaration-transformer/VariableDeclarationTransformer.spec';
+import './functional-tests/node-transformers/preparing-transformers/eval-call-expression-transformer/EvalCallExpressionTransformer.spec';
 import './functional-tests/node-transformers/preparing-transformers/comments-transformer/CommentsTransformer.spec';
 import './functional-tests/node-transformers/preparing-transformers/obfuscating-guards/black-list-obfuscating-guard/BlackListObfuscatingGuard.spec';
 import './functional-tests/node-transformers/preparing-transformers/obfuscating-guards/conditional-comment-obfuscating-guard/ConditionalCommentObfuscatingGuard.spec';

部分文件因为文件数量过多而无法显示