瀏覽代碼

StackTraceAnalyzer refactoring

sanex3339 8 年之前
父節點
當前提交
87b44bf852

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


+ 0 - 148
src/StackTraceAnalyzer.ts

@@ -1,148 +0,0 @@
-import * as estraverse from 'estraverse';
-import * as ESTree from 'estree';
-
-import { TNodeWithBlockStatement } from './types/TNodeWithBlockStatement';
-
-import { IStackTraceData } from './interfaces/IStackTraceData';
-import { IStackTraceAnalyzer } from './interfaces/IAnalyzer';
-
-import { Nodes } from './Nodes';
-import { NodeUtils } from './NodeUtils';
-
-/**
- * This class generates a data with code stack trace functions calls
- *
- * For example:
- *
- * function Foo () {
- *     var baz = function () {
- *
- *     }
- *
- *     baz();
- * }
- *
- * foo();
- *
- * Will generate a structure like:
- *
- * [
- *      {
- *          callee: FOO_FUNCTION_NODE
- *          name: 'Foo',
- *          trace: [
- *              {
- *                  callee: BAZ_FUNCTION_NODE,
- *                  name: 'baz,
- *                  trace: []
- *              }
- *          ]
- *      }
- * ]
- */
-export class StackTraceAnalyzer implements IStackTraceAnalyzer {
-    /**
-     * @type {ESTree.Node[]}
-     */
-    private blockScopeBody: ESTree.Node[];
-
-    /**
-     * @type {IStackTraceData[]}
-     */
-    private stackTraceData: IStackTraceData[] = [];
-
-    /**
-     * @param blockScopeBody
-     */
-    constructor (blockScopeBody: ESTree.Node[]) {
-        this.blockScopeBody = blockScopeBody;
-    }
-
-    /**
-     * @returns {T}
-     */
-    public analyze (): IStackTraceData[] {
-        if (this.blockScopeBody.length === 1) {
-            estraverse.traverse(this.blockScopeBody[0], {
-                enter: (node: ESTree.Node): any => {
-                    if (Nodes.isBlockStatementNode(node)) {
-                        this.analyzeRecursive(node.body, this.stackTraceData);
-
-                        return estraverse.VisitorOption.Skip;
-                    }
-                }
-            });
-        } else {
-            this.analyzeRecursive(this.blockScopeBody, this.stackTraceData);
-        }
-
-        return this.stackTraceData;
-    }
-
-    /**
-     * @param blockScopeBody
-     * @param stackTraceData
-     */
-    private analyzeRecursive (blockScopeBody: ESTree.Node[], stackTraceData: IStackTraceData[]): void {
-        for (let rootNode of blockScopeBody) {
-            estraverse.traverse(rootNode, {
-                enter: (node: ESTree.Node): any => {
-                    let calleeNode: TNodeWithBlockStatement|null = null,
-                        name: string = '';
-
-                    if (Nodes.isCallExpressionNode(node) && rootNode.parentNode === NodeUtils.getBlockScopeOfNode(node)) {
-                        if (Nodes.isIdentifierNode(node.callee)) {
-                            calleeNode = this.getCalleeBlockStatement(
-                                NodeUtils.getBlockScopeOfNode(blockScopeBody[0]),
-                                node.callee.name
-                            );
-
-                            name = node.callee.name;
-                        }
-                    }
-
-                    if (!calleeNode) {
-                        return;
-                    }
-
-                    const data: IStackTraceData = {
-                        callee: calleeNode,
-                        name: name,
-                        stackTrace: []
-                    };
-
-                    stackTraceData.push(data);
-
-                    this.analyzeRecursive(calleeNode.body, data.stackTrace);
-                }
-            });
-        }
-    }
-
-    private getCalleeBlockStatement (node: ESTree.Node, name: string): TNodeWithBlockStatement|null {
-        let calleeBlockStatement: TNodeWithBlockStatement|null = null;
-
-        estraverse.traverse(node, {
-            enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
-                if (Nodes.isFunctionDeclarationNode(node) && node.id.name === name) {
-                    calleeBlockStatement = node.body;
-
-                    return estraverse.VisitorOption.Break;
-                }
-
-                if (
-                    Nodes.isFunctionExpressionNode(node) &&
-                    Nodes.isVariableDeclaratorNode(parentNode) &&
-                    Nodes.isIdentifierNode(parentNode.id) &&
-                    parentNode.id.name === name
-                ) {
-                    calleeBlockStatement = node.body;
-
-                    return estraverse.VisitorOption.Break;
-                }
-            }
-        });
-
-        return calleeBlockStatement;
-    }
-}

+ 12 - 15
src/custom-nodes/CustomNodeAppender.ts

@@ -1,11 +1,9 @@
 import * as ESTree from 'estree';
 
-import { TNodeWithBlockStatement } from '../types/TNodeWithBlockStatement';
-
-import { IStackTraceData } from '../interfaces/IStackTraceData';
+import { IStackTraceData } from '../interfaces/stack-trace-analyzer/IStackTraceData';
 
 import { NodeUtils } from '../NodeUtils';
-import { StackTraceAnalyzer } from '../StackTraceAnalyzer';
+import { StackTraceAnalyzer } from '../stack-trace-analyzer/StackTraceAnalyzer';
 import { Utils } from '../Utils';
 
 /**
@@ -34,16 +32,15 @@ export class CustomNodeAppender {
     public static appendNode (blockScopeBody: ESTree.Node[], node: ESTree.Node, index: number = 0): void {
         const blockScopeTraceData: IStackTraceData[] = new StackTraceAnalyzer(blockScopeBody).analyze();
 
-        if (!blockScopeTraceData.length) {
-            NodeUtils.prependNode(blockScopeBody, node);
+        let targetBlockScopeBody: ESTree.Node[];
 
-            return;
+        if (!blockScopeTraceData.length) {
+            targetBlockScopeBody = blockScopeBody;
+        } else {
+            targetBlockScopeBody = CustomNodeAppender.getOptimalBlockScopeBody(blockScopeTraceData, index);
         }
 
-        NodeUtils.prependNode(
-            CustomNodeAppender.getOptimalBlockScope(blockScopeTraceData, index).body,
-            node
-        );
+        NodeUtils.prependNode(targetBlockScopeBody, node);
     }
 
     /**
@@ -64,15 +61,15 @@ export class CustomNodeAppender {
     /**
      * @param blockScopeTraceData
      * @param index
-     * @returns {TNodeWithBlockStatement}
+     * @returns {ESTree.Node[]}
      */
-    private static getOptimalBlockScope (blockScopeTraceData: IStackTraceData[], index: number): TNodeWithBlockStatement {
+    private static getOptimalBlockScopeBody (blockScopeTraceData: IStackTraceData[], index: number): ESTree.Node[] {
         const firstCall: IStackTraceData = blockScopeTraceData[index];
 
         if (firstCall.stackTrace.length) {
-            return CustomNodeAppender.getOptimalBlockScope(firstCall.stackTrace, 0);
+            return CustomNodeAppender.getOptimalBlockScopeBody(firstCall.stackTrace, 0);
         } else {
-            return firstCall.callee;
+            return firstCall.callee.body;
         }
     }
 }

+ 0 - 7
src/interfaces/IStackTraceData.d.ts

@@ -1,7 +0,0 @@
-import { TNodeWithBlockStatement } from '../types/TNodeWithBlockStatement';
-
-export interface IStackTraceData {
-    callee: TNodeWithBlockStatement;
-    name: string;
-    stackTrace: IStackTraceData[];
-}

+ 6 - 0
src/interfaces/stack-trace-analyzer/ICalleeData.d.ts

@@ -0,0 +1,6 @@
+import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
+
+export interface ICalleeData {
+    callee: TNodeWithBlockStatement;
+    name: string;
+}

+ 5 - 0
src/interfaces/stack-trace-analyzer/ICalleeDataExtractor.d.ts

@@ -0,0 +1,5 @@
+import { ICalleeData } from './ICalleeData';
+
+export interface ICalleeDataExtractor {
+    extract (): ICalleeData|null;
+}

+ 0 - 0
src/interfaces/IAnalyzer.d.ts → src/interfaces/stack-trace-analyzer/IStackTraceAnalyzer.d.ts


+ 5 - 0
src/interfaces/stack-trace-analyzer/IStackTraceData.d.ts

@@ -0,0 +1,5 @@
+import { ICalleeData } from './ICalleeData';
+
+export interface IStackTraceData extends ICalleeData {
+    stackTrace: IStackTraceData[];
+}

+ 110 - 0
src/stack-trace-analyzer/StackTraceAnalyzer.ts

@@ -0,0 +1,110 @@
+import * as estraverse from 'estraverse';
+import * as ESTree from 'estree';
+
+import { TCalleeDataExtractor } from '../types/TCalleeDataExtractor';
+
+import { ICalleeData } from '../interfaces/stack-trace-analyzer/ICalleeData';
+import { IStackTraceAnalyzer } from '../interfaces/stack-trace-analyzer/IStackTraceAnalyzer';
+import { IStackTraceData } from '../interfaces/stack-trace-analyzer/IStackTraceData';
+
+import { NodeType } from '../enums/NodeType';
+
+import { FunctionDeclarationCalleeDataExtractor } from './callee-data-extractors/FunctionDeclarationCalleeDataExtractor';
+import { FunctionExpressionCalleeDataExtractor } from './callee-data-extractors/FunctionExpressionCalleeDataExtractor';
+import { Nodes } from '../Nodes';
+import { NodeUtils } from '../NodeUtils';
+
+/**
+ * This class generates a data with code stack trace functions calls
+ *
+ * For example:
+ *
+ * function Foo () {
+ *     var baz = function () {
+ *
+ *     }
+ *
+ *     baz();
+ * }
+ *
+ * foo();
+ *
+ * Will generate a structure like:
+ *
+ * [
+ *      {
+ *          callee: FOO_FUNCTION_NODE
+ *          name: 'Foo',
+ *          trace: [
+ *              {
+ *                  callee: BAZ_FUNCTION_NODE,
+ *                  name: 'baz,
+ *                  trace: []
+ *              }
+ *          ]
+ *      }
+ * ]
+ */
+export class StackTraceAnalyzer implements IStackTraceAnalyzer {
+    /**
+     * @type {ESTree.Node[]}
+     */
+    private blockScopeBody: ESTree.Node[];
+
+    /**
+     * @type {Map<string, TCalleeDataExtractor>}
+     */
+    private calleeDataExtractors: Map <string, TCalleeDataExtractor> = new Map <string, TCalleeDataExtractor> ([
+        [NodeType.FunctionDeclaration, FunctionDeclarationCalleeDataExtractor],
+        [NodeType.FunctionExpression, FunctionExpressionCalleeDataExtractor]
+    ]);
+
+    /**
+     * @param blockScopeBody
+     */
+    constructor (blockScopeBody: ESTree.Node[]) {
+        this.blockScopeBody = blockScopeBody;
+    }
+
+    /**
+     * @returns {IStackTraceData[]}
+     */
+    public analyze (): IStackTraceData[] {
+        return this.analyzeRecursive(this.blockScopeBody);
+    }
+
+    /**
+     * @param blockScopeBody
+     * @returns {IStackTraceData[]}
+     */
+    private analyzeRecursive (blockScopeBody: ESTree.Node[]): IStackTraceData[] {
+        const stackTraceData: IStackTraceData[] = [];
+
+        for (let rootNode of blockScopeBody) {
+            estraverse.traverse(rootNode, {
+                enter: (node: ESTree.Node): any => {
+                    if (!Nodes.isCallExpressionNode(node) || rootNode.parentNode !== NodeUtils.getBlockScopeOfNode(node)) {
+                        return;
+                    }
+
+                    this.calleeDataExtractors.forEach((calleeDataExtractor: TCalleeDataExtractor) => {
+                        const calleeData: ICalleeData|null = new calleeDataExtractor(
+                            blockScopeBody,
+                            node.callee
+                        ).extract();
+
+                        if (!calleeData) {
+                            return;
+                        }
+
+                        stackTraceData.push(Object.assign({}, calleeData, {
+                            stackTrace: this.analyzeRecursive(calleeData.callee.body)
+                        }));
+                    });
+                }
+            });
+        }
+
+        return stackTraceData;
+    }
+}

+ 75 - 0
src/stack-trace-analyzer/callee-data-extractors/FunctionDeclarationCalleeDataExtractor.ts

@@ -0,0 +1,75 @@
+import * as estraverse from 'estraverse';
+import * as ESTree from 'estree';
+
+import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
+
+import { ICalleeData } from '../../interfaces/stack-trace-analyzer/ICalleeData';
+import { ICalleeDataExtractor } from '../../interfaces/stack-trace-analyzer/ICalleeDataExtractor';
+
+import { Nodes } from '../../Nodes';
+import { NodeUtils } from '../../NodeUtils';
+
+export class FunctionDeclarationCalleeDataExtractor implements ICalleeDataExtractor {
+    /**
+     * @type {ESTree.Node[]}
+     */
+    private blockScopeBody: ESTree.Node[];
+
+    /**
+     * @type {ESTree.Identifier}
+     */
+    private callee: ESTree.Identifier;
+
+    /**
+     * @param blockScopeBody
+     * @param callee
+     */
+    constructor (blockScopeBody: ESTree.Node[], callee: ESTree.Identifier) {
+        this.blockScopeBody = blockScopeBody;
+        this.callee = callee;
+    }
+
+    /**
+     * @returns {ICalleeData|null}
+     */
+    public extract (): ICalleeData|null {
+        let calleeBlockStatement: TNodeWithBlockStatement|null = null;
+
+        if (Nodes.isIdentifierNode(this.callee)) {
+            calleeBlockStatement = this.getCalleeBlockStatement(
+                NodeUtils.getBlockScopeOfNode(this.blockScopeBody[0]),
+                this.callee.name
+            );
+        }
+
+        if (!calleeBlockStatement) {
+            return null;
+        }
+
+        return {
+            callee: calleeBlockStatement,
+            name: this.callee.name
+        };
+    }
+
+    /**
+     * @param node
+     * @param name
+     * @returns {TNodeWithBlockStatement|null}
+     */
+    private getCalleeBlockStatement (node: ESTree.Node, name: string): TNodeWithBlockStatement|null {
+        let calleeBlockStatement: TNodeWithBlockStatement|null = null;
+
+        estraverse.traverse(node, {
+            enter: (node: ESTree.Node): any => {
+                if (Nodes.isFunctionDeclarationNode(node) && node.id.name === name) {
+                    calleeBlockStatement = node.body;
+
+                    return estraverse.VisitorOption.Break;
+                }
+            }
+        });
+
+        return calleeBlockStatement;
+    }
+}

+ 80 - 0
src/stack-trace-analyzer/callee-data-extractors/FunctionExpressionCalleeDataExtractor.ts

@@ -0,0 +1,80 @@
+import * as estraverse from 'estraverse';
+import * as ESTree from 'estree';
+
+import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
+
+import { ICalleeData } from '../../interfaces/stack-trace-analyzer/ICalleeData';
+import { ICalleeDataExtractor } from '../../interfaces/stack-trace-analyzer/ICalleeDataExtractor';
+
+import { Nodes } from '../../Nodes';
+import { NodeUtils } from '../../NodeUtils';
+
+export class FunctionExpressionCalleeDataExtractor implements ICalleeDataExtractor {
+    /**
+     * @type {ESTree.Node[]}
+     */
+    private blockScopeBody: ESTree.Node[];
+
+    /**
+     * @type {ESTree.Identifier}
+     */
+    private callee: ESTree.Identifier;
+
+    /**
+     * @param blockScopeBody
+     * @param callee
+     */
+    constructor (blockScopeBody: ESTree.Node[], callee: ESTree.Identifier) {
+        this.blockScopeBody = blockScopeBody;
+        this.callee = callee;
+    }
+
+    /**
+     * @returns {ICalleeData|null}
+     */
+    public extract (): ICalleeData|null {
+        let calleeBlockStatement: TNodeWithBlockStatement|null = null;
+
+        if (Nodes.isIdentifierNode(this.callee)) {
+            calleeBlockStatement = this.getCalleeBlockStatement(
+                NodeUtils.getBlockScopeOfNode(this.blockScopeBody[0]),
+                this.callee.name
+            );
+        }
+
+        if (!calleeBlockStatement) {
+            return null;
+        }
+
+        return {
+            callee: calleeBlockStatement,
+            name: this.callee.name
+        };
+    }
+
+    /**
+     * @param node
+     * @param name
+     * @returns {TNodeWithBlockStatement|null}
+     */
+    private getCalleeBlockStatement (node: ESTree.Node, name: string): TNodeWithBlockStatement|null {
+        let calleeBlockStatement: TNodeWithBlockStatement|null = null;
+
+        estraverse.traverse(node, {
+            enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
+                if (
+                    Nodes.isFunctionExpressionNode(node) &&
+                    Nodes.isVariableDeclaratorNode(parentNode) &&
+                    Nodes.isIdentifierNode(parentNode.id) &&
+                    parentNode.id.name === name
+                ) {
+                    calleeBlockStatement = node.body;
+
+                    return estraverse.VisitorOption.Break;
+                }
+            }
+        });
+
+        return calleeBlockStatement;
+    }
+}

+ 5 - 0
src/types/TCalleeDataExtractor.d.ts

@@ -0,0 +1,5 @@
+import * as ESTree from 'estree';
+
+import { ICalleeDataExtractor } from '../interfaces/stack-trace-analyzer/ICalleeDataExtractor';
+
+export type TCalleeDataExtractor = (new (blockScopeBody: ESTree.Node[], callee: any) => ICalleeDataExtractor);

+ 1 - 1
src/types/TNodeObfuscator.d.ts

@@ -2,4 +2,4 @@ import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
 import { INodeObfuscator } from '../interfaces/INodeObfuscator';
 import { IOptions } from '../interfaces/IOptions';
 
-export type TNodeObfuscator =  (new (nodes: Map <string, ICustomNode>, options: IOptions) => INodeObfuscator);
+export type TNodeObfuscator = (new (nodes: Map <string, ICustomNode>, options: IOptions) => INodeObfuscator);

+ 7 - 7
test/unit-tests/StackTraceAnalyzer-spec.ts → test/functional-tests/stack-trace-analyzer/StackTraceAnalyzer-spec.ts

@@ -2,15 +2,15 @@ import * as chai from 'chai';
 import * as estraverse from 'estraverse';
 import * as ESTree from 'estree';
 
-import { TNodeWithBlockStatement } from '../../src/types/TNodeWithBlockStatement';
+import { TNodeWithBlockStatement } from '../../../src/types/TNodeWithBlockStatement';
 
-import { IStackTraceData } from '../../src/interfaces/IStackTraceData';
+import { IStackTraceData } from '../../../src/interfaces/stack-trace-analyzer/IStackTraceData';
 
-import { readFileAsString } from '../helpers/readFileAsString';
+import { readFileAsString } from '../../helpers/readFileAsString';
 
-import { Nodes } from '../../src/Nodes';
-import { NodeUtils } from '../../src/NodeUtils';
-import { StackTraceAnalyzer } from '../../src/StackTraceAnalyzer';
+import { Nodes } from '../../../src/Nodes';
+import { NodeUtils } from '../../../src/NodeUtils';
+import { StackTraceAnalyzer } from '../../../src/stack-trace-analyzer/StackTraceAnalyzer';
 
 const assert: any = chai.assert;
 
@@ -67,7 +67,7 @@ function getFunctionExpressionByName (astTree: ESTree.Node, name: string): ESTre
 }
 
 describe('StackTraceAnalyzer', () => {
-    describe('analyze (): IStackTraceData[]', () => {
+    describe('extract (): IStackTraceData[]', () => {
         let astTree: TNodeWithBlockStatement,
             stackTraceData: IStackTraceData[],
             expectedStackTraceData: IStackTraceData[];

+ 1 - 1
test/index.spec.ts

@@ -14,7 +14,6 @@ import './unit-tests/SourceMapCorrector.spec';
 import './unit-tests/Utils.spec';
 import './unit-tests/cli/CLIUtils.spec';
 import './unit-tests/custom-nodes/CustomNodeAppender-spec';
-import './unit-tests/StackTraceAnalyzer-spec';
 import './unit-tests/node-obfuscators/CatchClauseObfuscator.spec';
 import './unit-tests/node-obfuscators/FunctionDeclarationObfuscator.spec';
 import './unit-tests/node-obfuscators/FunctionObfuscator.spec';
@@ -37,5 +36,6 @@ import './functional-tests/node-obfuscators/MemberExpressionObfuscator.spec';
 import './functional-tests/node-obfuscators/MethodDefinitionObfuscator.spec';
 import './functional-tests/node-obfuscators/ObjectExpressionObfuscator.spec';
 import './functional-tests/node-obfuscators/VariableDeclarationObfuscator.spec';
+import './functional-tests/stack-trace-analyzer/StackTraceAnalyzer-spec';
 import './functional-tests/templates/custom-nodes/domain-lock-nodes/DomainLockNodeTemplate.spec';
 import './functional-tests/templates/custom-nodes/unicode-array-nodes/UnicodeArrayDecodeNodeTemplate.spec';

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