Kaynağa Gözat

Storages refactoring

sanex3339 8 yıl önce
ebeveyn
işleme
86bc2399b1
26 değiştirilmiş dosya ile 471 ekleme ve 345 silme
  1. 231 174
      dist/index.js
  2. 1 0
      package.json
  3. 17 0
      src/Utils.ts
  4. 4 27
      src/custom-nodes/control-flow-storage-nodes/ControlFlowStorageNode.ts
  5. 0 7
      src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionNode.ts
  6. 6 5
      src/custom-nodes/string-array-nodes/StringArrayCallsWrapper.ts
  7. 10 23
      src/custom-nodes/string-array-nodes/StringArrayNode.ts
  8. 4 4
      src/custom-nodes/string-array-nodes/StringArrayRotateFunctionNode.ts
  9. 2 2
      src/interfaces/IControlFlowReplacer.d.ts
  10. 8 0
      src/interfaces/IStorage.d.ts
  11. 0 5
      src/interfaces/custom-nodes/ICustomNodeWithData.d.ts
  12. 3 2
      src/node-groups/StringArrayNodesGroup.ts
  13. 2 1
      src/node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer.ts
  14. 2 2
      src/node-transformers/node-control-flow-transformers/control-flow-replacers/AbstractControlFlowReplacer.ts
  15. 3 3
      src/node-transformers/node-control-flow-transformers/control-flow-replacers/BinaryExpressionControlFlowReplacer.ts
  16. 8 8
      src/node-transformers/node-obfuscators/replacers/StringLiteralReplacer.ts
  17. 45 0
      src/storages/AbstractStorage.ts
  18. 32 14
      src/storages/ControlFlowStorage.ts
  19. 0 53
      src/storages/StringArray.ts
  20. 62 0
      src/storages/StringArrayStorage.ts
  21. 2 4
      src/templates/custom-nodes/debug-protection-nodes/debug-protection-function-node/DebugProtectionFunctionTemplate.ts
  22. 1 0
      src/types/TStorage.d.ts
  23. 0 4
      src/types/custom-nodes/TControlFlowStorageNode.d.ts
  24. 0 3
      src/types/custom-nodes/TStringArrayCallsWrapper.d.ts
  25. 0 4
      src/types/custom-nodes/TStringArrayNode.d.ts
  26. 28 0
      test/unit-tests/Utils.spec.ts

Dosya farkı çok büyük olduğundan ihmal edildi
+ 231 - 174
dist/index.js


+ 1 - 0
package.json

@@ -27,6 +27,7 @@
     "escodegen": "1.8.1",
     "esprima": "3.1.1",
     "estraverse": "4.2.0",
+    "is-equal": "^1.5.3",
     "mkdirp": "0.5.1",
     "source-map-support": "0.4.6",
     "string-template": "^1.0.0"

+ 17 - 0
src/Utils.ts

@@ -2,6 +2,8 @@ import { Chance } from 'chance';
 
 import { JSFuck } from './enums/JSFuck';
 
+const isEqual = require('is-equal');
+
 export class Utils {
     /**
      * @type {Chance.Chance | Chance.SeededChance}
@@ -201,6 +203,21 @@ export class Utils {
         return number % 1 === 0;
     }
 
+    /**
+     * @param map
+     * @param value
+     * @returns {any}
+     */
+    public static mapGetFirstKeyOf(map: Map <any, any>, value: any): any {
+        for (var [key, storageValue] of map) {
+            if (isEqual(value, storageValue)) {
+                return key;
+            }
+        }
+
+        return null;
+    }
+
     /**
      * RC4 symmetric cipher encryption/decryption
      * https://gist.github.com/farhadi/2185197

+ 4 - 27
src/custom-nodes/control-flow-storage-nodes/ControlFlowStorageNode.ts

@@ -4,11 +4,10 @@ import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
 
 import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../interfaces/IOptions';
+import { IStorage } from '../../interfaces/IStorage';
 
 import { AppendState } from '../../enums/AppendState';
 
-import { ControlFlowStorage } from '../../storages/ControlFlowStorage';
-
 import { ControlFlowStorageTemplate } from '../../templates/custom-nodes/control-flow-storage-nodes/ControlFlowStorageTemplate';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
@@ -21,9 +20,9 @@ export class ControlFlowStorageNode extends AbstractCustomNode {
     protected appendState: AppendState = AppendState.AfterObfuscation;
 
     /**
-     * @type {ControlFlowStorage}
+     * @type {IStorage <ICustomNode>}
      */
-    private controlFlowStorage: ControlFlowStorage;
+    private controlFlowStorage: IStorage <ICustomNode>;
 
     /**
      * @type {string}
@@ -36,7 +35,7 @@ export class ControlFlowStorageNode extends AbstractCustomNode {
      * @param options
      */
     constructor (
-        controlFlowStorage: ControlFlowStorage,
+        controlFlowStorage: IStorage <ICustomNode>,
         controlFlowStorageName: string,
         options: IOptions
     ) {
@@ -62,26 +61,4 @@ export class ControlFlowStorageNode extends AbstractCustomNode {
             controlFlowStorageName: this.controlFlowStorageName
         });
     }
-
-    /**
-     * @returns {string}
-     */
-    public getNodeIdentifier (): string {
-        return this.controlFlowStorageName;
-    }
-
-    /**
-     * @returns {StringArray}
-     */
-    public getNodeData (): ControlFlowStorage {
-        return this.controlFlowStorage;
-    }
-
-    /**
-     * @param key
-     * @param value
-     */
-    public updateNodeData (key: string, value: ICustomNode): void {
-        this.controlFlowStorage.addToStorage(key, value);
-    }
 }

+ 0 - 7
src/custom-nodes/debug-protection-nodes/DebugProtectionFunctionNode.ts

@@ -51,11 +51,4 @@ export class DebugProtectionFunctionNode extends AbstractCustomNode {
             debugProtectionFunctionName: this.debugProtectionFunctionName
         });
     }
-
-    /**
-     * @returns {string}
-     */
-    public getNodeIdentifier (): string {
-        return this.debugProtectionFunctionName;
-    }
 }

+ 6 - 5
src/custom-nodes/string-array-nodes/StringArrayCallsWrapper.ts

@@ -3,7 +3,9 @@ import * as format from 'string-template';
 import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
 import { TStatement } from '../../types/TStatement';
 
+import { ICustomNodeWithIdentifier } from '../../interfaces/custom-nodes/ICustomNodeWithIdentifier';
 import { IOptions } from '../../interfaces/IOptions';
+import { IStorage } from '../../interfaces/IStorage';
 
 import { AppendState } from '../../enums/AppendState';
 import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
@@ -20,18 +22,17 @@ import { StringArrayRc4DecodeNodeTemplate } from '../../templates/custom-nodes/s
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { JavaScriptObfuscator } from '../../JavaScriptObfuscator';
 import { NodeAppender } from '../../node/NodeAppender';
-import { StringArray } from '../../storages/StringArray';
 
-export class StringArrayCallsWrapper extends AbstractCustomNode {
+export class StringArrayCallsWrapper extends AbstractCustomNode implements ICustomNodeWithIdentifier {
     /**
      * @type {AppendState}
      */
     protected appendState: AppendState = AppendState.AfterObfuscation;
 
     /**
-     * @type {StringArray}
+     * @type {IStorage <string>}
      */
-    private stringArray: StringArray;
+    private stringArray: IStorage <string>;
 
     /**
      * @type {string}
@@ -52,7 +53,7 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
     constructor (
         stringArrayCallsWrapperName: string,
         stringArrayName: string,
-        stringArray: StringArray,
+        stringArray: IStorage <string>,
         options: IOptions
     ) {
         super(options);

+ 10 - 23
src/custom-nodes/string-array-nodes/StringArrayNode.ts

@@ -3,18 +3,19 @@ import * as format from 'string-template';
 import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
 import { TStatement } from '../../types/TStatement';
 
+import { ICustomNodeWithData } from '../../interfaces/custom-nodes/ICustomNodeWithData';
 import { IOptions } from '../../interfaces/IOptions';
+import { IStorage } from '../../interfaces/IStorage';
 
 import { AppendState } from '../../enums/AppendState';
 
-import { StringArray } from '../../storages/StringArray';
-
 import { StringArrayTemplate } from '../../templates/custom-nodes/string-array-nodes/string-array-node/StringArrayTemplate';
 
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { NodeAppender } from '../../node/NodeAppender';
+import { StringArrayStorage } from '../../storages/StringArrayStorage';
 
-export class StringArrayNode extends AbstractCustomNode {
+export class StringArrayNode extends AbstractCustomNode implements ICustomNodeWithData {
     /**
      * @type {number}
      */
@@ -26,9 +27,9 @@ export class StringArrayNode extends AbstractCustomNode {
     protected appendState: AppendState = AppendState.AfterObfuscation;
 
     /**
-     * @type {StringArray}
+     * @type {IStorage <string>}
      */
-    private stringArray: StringArray;
+    private stringArray: IStorage <string>;
 
     /**
      * @type {string}
@@ -47,7 +48,7 @@ export class StringArrayNode extends AbstractCustomNode {
      * @param options
      */
     constructor (
-        stringArray: StringArray,
+        stringArray: IStorage <string>,
         stringArrayName: string,
         stringArrayRotateValue: number = 0,
         options: IOptions
@@ -81,16 +82,9 @@ export class StringArrayNode extends AbstractCustomNode {
     }
 
     /**
-     * @returns {string}
-     */
-    public getNodeIdentifier (): string {
-        return this.stringArrayName;
-    }
-
-    /**
-     * @returns {StringArray}
+     * @returns {IStorage <string>}
      */
-    public getNodeData (): StringArray {
+    public getNodeData (): IStorage <string> {
         return this.stringArray;
     }
 
@@ -98,15 +92,8 @@ export class StringArrayNode extends AbstractCustomNode {
      * @returns {TStatement[]}
      */
     public getNode (): TStatement[] {
-        this.stringArray.rotateArray(this.stringArrayRotateValue);
+        (<StringArrayStorage>this.stringArray).rotateArray(this.stringArrayRotateValue);
 
         return super.getNode();
     }
-
-    /**
-     * @param data
-     */
-    public updateNodeData (data: string): void {
-        this.stringArray.addToArray(data);
-    }
 }

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

@@ -3,6 +3,7 @@ import * as format from 'string-template';
 import { TNodeWithBlockStatement } from '../../types/TNodeWithBlockStatement';
 
 import { IOptions } from '../../interfaces/IOptions';
+import { IStorage } from '../../interfaces/IStorage';
 
 import { AppendState } from '../../enums/AppendState';
 
@@ -14,7 +15,6 @@ import { StringArrayRotateFunctionTemplate } from '../../templates/custom-nodes/
 import { AbstractCustomNode } from '../AbstractCustomNode';
 import { JavaScriptObfuscator } from '../../JavaScriptObfuscator';
 import { NodeAppender } from '../../node/NodeAppender';
-import { StringArray } from '../../storages/StringArray';
 import { Utils } from '../../Utils';
 
 export class StringArrayRotateFunctionNode extends AbstractCustomNode {
@@ -24,9 +24,9 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
     protected appendState: AppendState = AppendState.AfterObfuscation;
 
     /**
-     * @type {StringArray}
+     * @type {IStorage <string>}
      */
-    private stringArray: StringArray;
+    private stringArray: IStorage <string>;
 
     /**
      * @type {string}
@@ -46,7 +46,7 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
      */
     constructor (
         stringArrayName: string,
-        stringArray: StringArray,
+        stringArray: IStorage <string>,
         stringArrayRotateValue: number,
         options: IOptions
     ) {

+ 2 - 2
src/interfaces/IControlFlowReplacer.d.ts

@@ -1,13 +1,13 @@
 import * as ESTree from 'estree';
 
 import { ICustomNode } from './custom-nodes/ICustomNode';
-import { ControlFlowStorage } from '../storages/ControlFlowStorage';
+import { IStorage } from './IStorage';
 
 export interface IControlFlowReplacer {
     replace (
         node: ESTree.Node,
         parentNode: ESTree.Node,
-        controlFlowStorage: ControlFlowStorage,
+        controlFlowStorage: IStorage <ICustomNode>,
         controlFlowStorageCustomNodeName: string
     ): ICustomNode | undefined;
 }

+ 8 - 0
src/interfaces/IStorage.d.ts

@@ -0,0 +1,8 @@
+export interface IStorage <T> {
+    get (key: string | number): T;
+    getKeyOf (value: T): string | number | null;
+    getLength (): number;
+    getStorage (): Map <string, T> | T[];
+    set (key: string | null, value: T): void;
+    toString (): string;
+}

+ 0 - 5
src/interfaces/custom-nodes/ICustomNodeWithData.d.ts

@@ -5,9 +5,4 @@ export interface ICustomNodeWithData extends ICustomNode {
      * @returns any
      */
     getNodeData (): any;
-
-    /**
-     * @param data
-     */
-    updateNodeData (data: any): void;
 }

+ 3 - 2
src/node-groups/StringArrayNodesGroup.ts

@@ -7,8 +7,9 @@ import { StringArrayNode } from '../custom-nodes/string-array-nodes/StringArrayN
 import { StringArrayRotateFunctionNode } from '../custom-nodes/string-array-nodes/StringArrayRotateFunctionNode';
 
 import { AbstractNodesGroup } from './AbstractNodesGroup';
-import { StringArray } from '../storages/StringArray';
+import { StringArrayStorage } from '../storages/StringArrayStorage';
 import { Utils } from '../Utils';
+import { IStorage } from '../interfaces/IStorage';
 
 export class StringArrayNodesGroup extends AbstractNodesGroup {
     /**
@@ -45,7 +46,7 @@ export class StringArrayNodesGroup extends AbstractNodesGroup {
             this.stringArrayRotateValue = 0;
         }
 
-        const stringArray: StringArray = new StringArray();
+        const stringArray: IStorage <string> = new StringArrayStorage();
         const stringArrayNode: ICustomNode = new StringArrayNode(
             stringArray,
             this.stringArrayName,

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

@@ -17,6 +17,7 @@ import { Node } from '../../node/Node';
 import { NodeAppender } from '../../node/NodeAppender';
 import { Utils } from '../../Utils';
 import { NodeUtils } from '../../node/NodeUtils';
+import { IStorage } from '../../interfaces/IStorage';
 
 export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
     /**
@@ -49,7 +50,7 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
             return;
         }
 
-        const controlFlowStorage: ControlFlowStorage = new ControlFlowStorage();
+        const controlFlowStorage: IStorage <ICustomNode> = new ControlFlowStorage();
         const controlFlowStorageCustomNodeName: string = Utils.getRandomVariableName(6);
 
         console.log(NodeUtils.getNodeBlockScopeDepth(functionNode.body));

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

@@ -3,8 +3,8 @@ import * as ESTree from 'estree';
 import { IControlFlowReplacer } from '../../../interfaces/IControlFlowReplacer';
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
 import { IOptions } from '../../../interfaces/IOptions';
+import { IStorage } from '../../../interfaces/IStorage';
 
-import { ControlFlowStorage } from '../../../storages/ControlFlowStorage';
 import { Utils } from '../../../Utils';
 
 export abstract class AbstractControlFlowReplacer implements IControlFlowReplacer {
@@ -47,7 +47,7 @@ export abstract class AbstractControlFlowReplacer implements IControlFlowReplace
     public abstract replace (
         node: ESTree.Node,
         parentNode: ESTree.Node,
-        controlFlowStorage: ControlFlowStorage,
+        controlFlowStorage: IStorage <ICustomNode>,
         controlFlowStorageCustomNodeName: string
     ): ICustomNode | undefined;
 }

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

@@ -2,10 +2,10 @@ import * as escodegen from 'escodegen';
 import * as ESTree from 'estree';
 
 import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
+import { IStorage } from '../../../interfaces/IStorage';
 
 import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
 import { BinaryExpressionFunctionNode } from '../../../custom-nodes/control-flow-replacers-nodes/binary-expression-control-flow-replacer-nodes/BinaryExpressionFunctionNode';
-import { ControlFlowStorage } from '../../../storages/ControlFlowStorage';
 import { ControlFlowStorageCallNode } from '../../../custom-nodes/control-flow-replacers-nodes/binary-expression-control-flow-replacer-nodes/ControlFlowStorageCallNode';
 
 export class BinaryExpressionControlFlowReplacer extends AbstractControlFlowReplacer {
@@ -29,12 +29,12 @@ export class BinaryExpressionControlFlowReplacer extends AbstractControlFlowRepl
     public replace (
         binaryExpressionNode: ESTree.BinaryExpression,
         parentNode: ESTree.Node,
-        controlFlowStorage: ControlFlowStorage,
+        controlFlowStorage: IStorage <ICustomNode>,
         controlFlowStorageCustomNodeName: string
     ): ICustomNode | undefined {
         const key: string = AbstractControlFlowReplacer.getStorageKey();
 
-        controlFlowStorage.addToStorage(key, new BinaryExpressionFunctionNode(binaryExpressionNode.operator, this.options));
+        controlFlowStorage.set(key, new BinaryExpressionFunctionNode(binaryExpressionNode.operator, this.options));
 
         return new ControlFlowStorageCallNode(
             controlFlowStorageCustomNodeName,

+ 8 - 8
src/node-transformers/node-obfuscators/replacers/StringLiteralReplacer.ts

@@ -1,12 +1,12 @@
-import { TStringArrayCallsWrapper } from '../../../types/custom-nodes/TStringArrayCallsWrapper';
-import { TStringArrayNode } from '../../../types/custom-nodes/TStringArrayNode';
+import { ICustomNodeWithData } from '../../../interfaces/custom-nodes/ICustomNodeWithData';
+import { IStorage } from '../../../interfaces/IStorage';
 
 import { StringArrayEncoding } from '../../../enums/StringArrayEncoding';
 
 import { AbstractReplacer } from './AbstractReplacer';
 import { NumberLiteralReplacer } from './NumberLiteralReplacer';
-import { StringArray } from '../../../storages/StringArray';
 import { Utils } from '../../../Utils';
+import { ICustomNodeWithIdentifier } from '../../../interfaces/custom-nodes/ICustomNodeWithIdentifier';
 
 export class StringLiteralReplacer extends AbstractReplacer {
     /**
@@ -42,7 +42,7 @@ export class StringLiteralReplacer extends AbstractReplacer {
      * @returns {string}
      */
     private replaceStringLiteralWithStringArrayCall (value: string): string {
-        const stringArrayNode: TStringArrayNode = <TStringArrayNode>this.nodes.get('stringArrayNode');
+        const stringArrayNode: ICustomNodeWithData = <ICustomNodeWithData>this.nodes.get('stringArrayNode');
 
         if (!stringArrayNode) {
             throw new ReferenceError('`stringArrayNode` node is not found in Map with custom node.');
@@ -67,8 +67,8 @@ export class StringLiteralReplacer extends AbstractReplacer {
             value = Utils.stringToUnicodeEscapeSequence(value);
         }
 
-        let stringArray: StringArray = stringArrayNode.getNodeData(),
-            indexOfExistingValue: number = stringArray.getIndexOf(value),
+        let stringArray: IStorage <string> = stringArrayNode.getNodeData(),
+            indexOfExistingValue: number = <number>stringArray.getKeyOf(value),
             indexOfValue: number,
             hexadecimalIndex: string;
 
@@ -76,13 +76,13 @@ export class StringLiteralReplacer extends AbstractReplacer {
             indexOfValue = indexOfExistingValue;
         } else {
             indexOfValue = stringArray.getLength();
-            stringArrayNode.updateNodeData(value);
+            stringArray.set(null, value);
         }
 
         hexadecimalIndex = new NumberLiteralReplacer(this.nodes, this.options)
             .replace(indexOfValue);
 
-        const stringArrayCallsWrapper: TStringArrayCallsWrapper = <TStringArrayCallsWrapper>this.nodes.get('stringArrayCallsWrapper');
+        const stringArrayCallsWrapper: ICustomNodeWithIdentifier = <ICustomNodeWithIdentifier>this.nodes.get('stringArrayCallsWrapper');
 
         if (!stringArrayCallsWrapper) {
             throw new ReferenceError('`stringArrayCallsWrapper` node is not found in Map with custom node.');

+ 45 - 0
src/storages/AbstractStorage.ts

@@ -0,0 +1,45 @@
+import { TStorage } from '../types/TStorage';
+
+import { IStorage } from '../interfaces/IStorage';
+
+export abstract class AbstractStorage <T> implements IStorage <T> {
+    /**
+     * @type {TStorage <T>}
+     */
+    protected abstract storage: TStorage <T>;
+
+    /**
+     * @param key
+     * @returns T
+     */
+    public abstract get (key: string | number): T;
+
+    /**
+     * @param value
+     * @returns string | number | null
+     */
+    public abstract getKeyOf (value: T): string | number | null;
+
+    /**
+     * @returns {number}
+     */
+    public abstract getLength (): number;
+
+    /**
+     * @returns {TStorage <T>}
+     */
+    public getStorage (): TStorage <T> {
+        return this.storage;
+    }
+
+    /**
+     * @param key
+     * @param value
+     */
+    public abstract set (key: string | null, value: T): void;
+
+    /**
+     * @returns {string}
+     */
+    public abstract toString (): string;
+}

+ 32 - 14
src/storages/ControlFlowStorage.ts

@@ -1,21 +1,45 @@
 import { ICustomNode } from '../interfaces/custom-nodes/ICustomNode';
 
-export class ControlFlowStorage {
+import { AbstractStorage } from './AbstractStorage';
+import { Utils } from '../Utils';
+
+export class ControlFlowStorage extends AbstractStorage <ICustomNode> {
     /**
      * @type {Map <string, ICustomNode>}
      */
-    private storage: Map <string, ICustomNode> = new Map <string, ICustomNode> ();
+    protected storage: Map <string, ICustomNode> = new Map <string, ICustomNode> ();
 
     /**
      * @param key
+     * @returns {ICustomNode}
+     */
+    public get (key: string): ICustomNode {
+        const value: ICustomNode | undefined = this.storage.get(key);
+
+        if (!value) {
+            throw new Error(`No value found in ControlFlowStorage with key \`${key}\``);
+        }
+
+        return value;
+    }
+
+    /**
      * @param value
+     * @returns {string | number | null}
      */
-    public addToStorage (key: string, value: ICustomNode): void {
-        this.storage.set(key, value);
+    public getKeyOf (value: ICustomNode): string | number | null {
+        return Utils.mapGetFirstKeyOf(this.storage, value);
     }
 
     /**
-     * @returns {Map <string, Function>}
+     * @returns {number}
+     */
+    public getLength (): number {
+        return Array.from(this.storage).length;
+    }
+
+    /**
+     * @returns {Map <string, ICustomNode>}
      */
     public getStorage (): Map <string, ICustomNode> {
         return this.storage;
@@ -23,16 +47,10 @@ export class ControlFlowStorage {
 
     /**
      * @param key
-     * @returns {Function}
+     * @param value
      */
-    public getStorageItem(key: string): ICustomNode {
-        const value: ICustomNode | undefined = this.storage.get(key);
-
-        if (!value) {
-            throw new Error(`No value found in ControlFlowStorage with key \`${key}\``);
-        }
-
-        return value;
+    public set (key: string, value: ICustomNode): void {
+        this.storage.set(key, value);
     }
 
     /**

+ 0 - 53
src/storages/StringArray.ts

@@ -1,53 +0,0 @@
-import { Utils } from '../Utils';
-
-export class StringArray {
-    /**
-     * @type {string[]}
-     */
-    private array: string[] = [];
-
-    /**
-     * @param value
-     */
-    public addToArray (value: string): void {
-        this.array.push(value);
-    }
-
-    /**
-     * @returns {string[]}
-     */
-    public getArray (): string[] {
-        return this.array;
-    }
-
-    /**
-     * @param value
-     * @returns {number}
-     */
-    public getIndexOf(value: string): number {
-        return this.array.indexOf(value);
-    }
-
-    /**
-     * @returns {number}
-     */
-    public getLength (): number {
-        return this.array.length;
-    }
-
-    /**
-     * @param rotationValue
-     */
-    public rotateArray (rotationValue: number): void {
-        this.array = Utils.arrayRotate(this.array, rotationValue);
-    }
-
-    /**
-     * @returns {string}
-     */
-    public toString (): string {
-        return this.array.map((value: string) => {
-            return `'${value}'`;
-        }).toString()
-    }
-}

+ 62 - 0
src/storages/StringArrayStorage.ts

@@ -0,0 +1,62 @@
+import { AbstractStorage } from './AbstractStorage';
+import { Utils } from '../Utils';
+
+export class StringArrayStorage extends AbstractStorage <string> {
+    /**
+     * @type {string[]}
+     */
+    protected storage: string[] = [];
+
+    /**
+     * @param key
+     * @returns {string}
+     */
+    public get (key: number): string {
+        const value: string | undefined = this.storage[key];
+
+        if (!value) {
+            throw new Error(`No value found in StringArray with key \`${key}\``);
+        }
+
+        return value;
+    }
+
+    /**
+     * @param value
+     * @returns {string | number}
+     */
+    public getKeyOf (value: string): string | number {
+        return this.storage.indexOf(value);
+    }
+
+    /**
+     * @returns {number}
+     */
+    public getLength (): number {
+        return this.storage.length;
+    }
+
+    /**
+     * @param rotationValue
+     */
+    public rotateArray (rotationValue: number): void {
+        this.storage = Utils.arrayRotate(this.storage, rotationValue);
+    }
+
+    /**
+     * @param key
+     * @param value
+     */
+    public set (key: string | null, value: string): void {
+        this.storage.push(value);
+    }
+
+    /**
+     * @returns {string}
+     */
+    public toString (): string {
+        return this.storage.map((value: string) => {
+            return `'${value}'`;
+        }).toString()
+    }
+}

+ 2 - 4
src/templates/custom-nodes/debug-protection-nodes/debug-protection-function-node/DebugProtectionFunctionTemplate.ts

@@ -1,5 +1,3 @@
-import { Utils } from '../../../../Utils';
-
 /**
  * @returns {string}
  */
@@ -8,9 +6,9 @@ export function DebugProtectionFunctionTemplate (): string {
         var {debugProtectionFunctionName} = function () {
             function debuggerProtection (counter) {
                 if (('' + counter / counter)['length'] !== 1 || counter % 20 === 0) {
-                    (function () {}.constructor(${Utils.stringToJSFuck('debugger')})());
+                    (function () {}.constructor('debugger')());
                 } else {
-                    (function () {}.constructor(${Utils.stringToJSFuck('debugger')})());
+                    (function () {}.constructor('debugger')());
                 }
                 
                 debuggerProtection(++counter);

+ 1 - 0
src/types/TStorage.d.ts

@@ -0,0 +1 @@
+export type TStorage <T> = Map <string, T> | T[];

+ 0 - 4
src/types/custom-nodes/TControlFlowStorageNode.d.ts

@@ -1,4 +0,0 @@
-import { ICustomNodeWithData } from '../../interfaces/custom-nodes/ICustomNodeWithData';
-import { ICustomNodeWithIdentifier } from '../../interfaces/custom-nodes/ICustomNodeWithIdentifier';
-
-export type TControlFlowStorageNode = ICustomNodeWithData & ICustomNodeWithIdentifier;

+ 0 - 3
src/types/custom-nodes/TStringArrayCallsWrapper.d.ts

@@ -1,3 +0,0 @@
-import { ICustomNodeWithIdentifier } from '../../interfaces/custom-nodes/ICustomNodeWithIdentifier';
-
-export type TStringArrayCallsWrapper = ICustomNodeWithIdentifier;

+ 0 - 4
src/types/custom-nodes/TStringArrayNode.d.ts

@@ -1,4 +0,0 @@
-import { ICustomNodeWithData } from '../../interfaces/custom-nodes/ICustomNodeWithData';
-import { ICustomNodeWithIdentifier } from '../../interfaces/custom-nodes/ICustomNodeWithIdentifier';
-
-export type TStringArrayNode = ICustomNodeWithData & ICustomNodeWithIdentifier;

+ 28 - 0
test/unit-tests/Utils.spec.ts

@@ -75,6 +75,34 @@ describe('Utils', () => {
         });
     });
 
+    describe('mapGetFirstKeyOf(map: Map <any, any>, value: any): any', () => {
+        it('should returns key of map item', () => {
+            const map: Map <any, any> = new Map();
+
+            map.set('number1', 1);
+            map.set('number2', 2);
+            map.set('number3', 2);
+
+            map.set('string1', 'foo');
+            map.set('string2', 'bar');
+
+            map.set('object1', {item: 'value'});
+            map.set('object2', {item: 'value'});
+            map.set({key: 'object'}, [1, 2, 3]);
+
+            assert.deepEqual(Utils.mapGetFirstKeyOf(map, 1), 'number1');
+            assert.deepEqual(Utils.mapGetFirstKeyOf(map, 2), 'number2');
+
+            assert.deepEqual(Utils.mapGetFirstKeyOf(map, 'foo'), 'string1');
+            assert.deepEqual(Utils.mapGetFirstKeyOf(map, 'bar'), 'string2');
+
+            assert.deepEqual(Utils.mapGetFirstKeyOf(map, {item: 'value'}), 'object1');
+            assert.deepEqual(Utils.mapGetFirstKeyOf(map, [1, 2, 3]), {key: 'object'});
+
+            assert.deepEqual(Utils.mapGetFirstKeyOf(map, 3), null);
+        });
+    });
+
     describe('stringToJSFuck (string: string): string', () => {
         let expected: string = `${JSFuck.s} + ${JSFuck.t} + ${JSFuck.r} + ${JSFuck.i} + ${JSFuck.n} + ${JSFuck.g}`;
 

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor