Kaynağa Gözat

add js files back

sanex3339 9 yıl önce
ebeveyn
işleme
f2aa8a3911

+ 0 - 1
.gitignore

@@ -1,5 +1,4 @@
 .idea
 node_modules
 npm-debug.log
-**/**.js
 **/**.js.map

+ 20 - 0
index.js

@@ -0,0 +1,20 @@
+"use strict";
+const Obfuscator_1 = require('./src/Obfuscator');
+let escodegen = require('escodegen'), esprima = require('esprima');
+class JavaScriptObfuscator {
+    static obfuscate(sourceCode, options) {
+        let astTree = esprima.parse(sourceCode), obfuscator = new Obfuscator_1.Obfuscator(options);
+        obfuscator.obfuscateNode(astTree);
+        return JavaScriptObfuscator.generateCode(astTree);
+    }
+    static generateCode(astTree) {
+        return escodegen.generate(astTree, JavaScriptObfuscator.escodegenParams);
+    }
+}
+JavaScriptObfuscator.escodegenParams = {
+    format: {},
+    verbatim: 'x-verbatim-property'
+};
+exports.JavaScriptObfuscator = JavaScriptObfuscator;
+module.exports = JavaScriptObfuscator;
+//# sourceMappingURL=index.js.map

+ 89 - 0
src/Obfuscator.js

@@ -0,0 +1,89 @@
+"use strict";
+const AppendState_1 = require('./enums/AppendState');
+const FunctionDeclarationObfuscator_1 = require('./node-obfuscators/FunctionDeclarationObfuscator');
+const FunctionObfuscator_1 = require('./node-obfuscators/FunctionObfuscator');
+const LiteralObfuscator_1 = require('./node-obfuscators/LiteralObfuscator');
+const MemberExpressionObfuscator_1 = require('./node-obfuscators/MemberExpressionObfuscator');
+const MethodDefinitionObfuscator_1 = require('./node-obfuscators/MethodDefinitionObfuscator');
+const ObjectExpressionObfuscator_1 = require('./node-obfuscators/ObjectExpressionObfuscator');
+const UnicodeArrayNode_1 = require('./nodes/UnicodeArrayNode');
+const UnicodeArrayNodesGroup_1 = require('./node-groups/UnicodeArrayNodesGroup');
+const Utils_1 = require('./Utils');
+const VariableDeclarationObfuscator_1 = require('./node-obfuscators/VariableDeclarationObfuscator');
+let estraverse = require('estraverse');
+class Obfuscator {
+    constructor(options) {
+        this.nodes = new Map();
+        this.nodeObfuscators = new Map([
+            ['ClassDeclaration', [FunctionDeclarationObfuscator_1.FunctionDeclarationObfuscator]],
+            ['FunctionDeclaration', [
+                    FunctionDeclarationObfuscator_1.FunctionDeclarationObfuscator,
+                    FunctionObfuscator_1.FunctionObfuscator
+                ]],
+            ['ArrowFunctionExpression', [FunctionObfuscator_1.FunctionObfuscator]],
+            ['FunctionExpression', [FunctionObfuscator_1.FunctionObfuscator]],
+            ['MethodDefinition', [MethodDefinitionObfuscator_1.MethodDefinitionObfuscator]],
+            ['VariableDeclaration', [VariableDeclarationObfuscator_1.VariableDeclarationObfuscator]],
+            ['ObjectExpression', [ObjectExpressionObfuscator_1.ObjectExpressionObfuscator]],
+            ['MemberExpression', [MemberExpressionObfuscator_1.MemberExpressionObfuscator]],
+            ['Literal', [LiteralObfuscator_1.LiteralObfuscator]]
+        ]);
+        this.options = {
+            rotateUnicodeArray: true
+        };
+        Object.assign(this.options, options);
+    }
+    obfuscateNode(node) {
+        if (this.options['rotateUnicodeArray']) {
+            this.setNodesGroup('unicodeArrayNodesGroup', new UnicodeArrayNodesGroup_1.UnicodeArrayNodesGroup(node));
+        }
+        else {
+            this.setNode('unicodeArrayNode', new UnicodeArrayNode_1.UnicodeArrayNode(node, Utils_1.Utils.getRandomVariableName(UnicodeArrayNode_1.UnicodeArrayNode.UNICODE_ARRAY_RANDOM_LENGTH)));
+        }
+        this.beforeObfuscation(node);
+        estraverse.replace(node, {
+            leave: (node, parent) => this.nodeController(node, parent)
+        });
+        this.afterObfuscation(node);
+    }
+    setNode(nodeName, node) {
+        this.nodes.set(nodeName, node);
+    }
+    setNodesGroup(groupName, nodesGroup) {
+        let nodes = nodesGroup.getNodes();
+        nodes.forEach((node, key) => {
+            this.nodes.set(key, node);
+        });
+    }
+    afterObfuscation(node) {
+        this.nodes.forEach((node) => {
+            if (node.getAppendState() === AppendState_1.AppendState.AfterObfuscation) {
+                node.appendNode();
+            }
+        });
+    }
+    beforeObfuscation(node) {
+        this.nodes.forEach((node) => {
+            if (node.getAppendState() === AppendState_1.AppendState.BeforeObfuscation) {
+                node.appendNode();
+            }
+        });
+    }
+    ;
+    nodeController(node, parent) {
+        switch (node.type) {
+            default:
+                this.initializeNodeObfuscators(node, parent);
+        }
+    }
+    initializeNodeObfuscators(node, parent) {
+        if (!this.nodeObfuscators.has(node.type)) {
+            return;
+        }
+        this.nodeObfuscators.get(node.type).forEach((obfuscator) => {
+            new obfuscator(this.nodes).obfuscateNode(node, parent);
+        });
+    }
+}
+exports.Obfuscator = Obfuscator;
+//# sourceMappingURL=Obfuscator.js.map

+ 37 - 0
src/Utils.js

@@ -0,0 +1,37 @@
+"use strict";
+class Utils {
+    static arrayRotate(array, times, reverse = false) {
+        if (times < 0) {
+            return;
+        }
+        let newArray = array, temp;
+        while (times--) {
+            if (!reverse) {
+                temp = newArray.pop();
+                newArray.unshift(temp);
+            }
+            else {
+                temp = newArray.shift();
+                newArray.push(temp);
+            }
+        }
+        return newArray;
+    }
+    static decToHex(dec) {
+        return (dec + Math.pow(16, 6)).toString(16).substr(-6);
+    }
+    static getRandomInteger(min, max) {
+        return Math.floor(Math.random() * (max - min + 1)) + min;
+    }
+    static getRandomVariableName(length = 6) {
+        const prefix = '_0x';
+        return `${prefix}${(Utils.decToHex(Utils.getRandomInteger(10000, 9999999))).substr(0, length)}`;
+    }
+    static stringToUnicode(string) {
+        return `'${string.replace(/[\s\S]/g, (escape) => {
+            return `\\u${('0000' + escape.charCodeAt(0).toString(16)).slice(-4)}`;
+        })}'`;
+    }
+}
+exports.Utils = Utils;
+//# sourceMappingURL=Utils.js.map

+ 7 - 0
src/enums/AppendState.js

@@ -0,0 +1,7 @@
+"use strict";
+(function (AppendState) {
+    AppendState[AppendState["BeforeObfuscation"] = 0] = "BeforeObfuscation";
+    AppendState[AppendState["AfterObfuscation"] = 1] = "AfterObfuscation";
+})(exports.AppendState || (exports.AppendState = {}));
+var AppendState = exports.AppendState;
+//# sourceMappingURL=AppendState.js.map

+ 2 - 0
src/interfaces/INode.js

@@ -0,0 +1,2 @@
+"use strict";
+//# sourceMappingURL=INode.js.map

+ 2 - 0
src/interfaces/INodeObfuscator.js

@@ -0,0 +1,2 @@
+"use strict";
+//# sourceMappingURL=INodeObfuscator.js.map

+ 2 - 0
src/interfaces/INodesGroup.js

@@ -0,0 +1,2 @@
+"use strict";
+//# sourceMappingURL=INodesGroup.js.map

+ 8 - 0
src/node-groups/NodesGroup.js

@@ -0,0 +1,8 @@
+"use strict";
+class NodesGroup {
+    getNodes() {
+        return this.nodes;
+    }
+}
+exports.NodesGroup = NodesGroup;
+//# sourceMappingURL=NodesGroup.js.map

+ 29 - 0
src/node-groups/UnicodeArrayNodesGroup.js

@@ -0,0 +1,29 @@
+"use strict";
+const NodesGroup_1 = require('./NodesGroup');
+const UnicodeArrayNode_1 = require('../nodes/UnicodeArrayNode');
+const UnicodeArrayRotateFunctionCallNode_1 = require('../nodes/UnicodeArrayRotateFunctionCallNode');
+const UnicodeArrayRotateFunctionNode_1 = require('../nodes/UnicodeArrayRotateFunctionNode');
+const Utils_1 = require('../Utils');
+class UnicodeArrayNodesGroup extends NodesGroup_1.NodesGroup {
+    constructor(astTree) {
+        super();
+        this.unicodeArrayRotateFunctionIdentifier = Utils_1.Utils.getRandomVariableName();
+        let unicodeArrayName = Utils_1.Utils.getRandomVariableName(UnicodeArrayNode_1.UnicodeArrayNode.UNICODE_ARRAY_RANDOM_LENGTH), unicodeArrayRotateValue = Utils_1.Utils.getRandomInteger(100, 500);
+        this.nodes = new Map([
+            [
+                'unicodeArrayNode',
+                new UnicodeArrayNode_1.UnicodeArrayNode(astTree, unicodeArrayName, unicodeArrayRotateValue)
+            ],
+            [
+                'unicodeArrayRotateFunctionNode',
+                new UnicodeArrayRotateFunctionNode_1.UnicodeArrayRotateFunctionNode(astTree, this.unicodeArrayRotateFunctionIdentifier, unicodeArrayName)
+            ],
+            [
+                'unicodeArrayRotateFunctionCallNode',
+                new UnicodeArrayRotateFunctionCallNode_1.UnicodeArrayRotateFunctionCallNode(astTree, this.unicodeArrayRotateFunctionIdentifier, unicodeArrayName, unicodeArrayRotateValue)
+            ]
+        ]);
+    }
+}
+exports.UnicodeArrayNodesGroup = UnicodeArrayNodesGroup;
+//# sourceMappingURL=UnicodeArrayNodesGroup.js.map

+ 37 - 0
src/node-obfuscators/FunctionDeclarationObfuscator.js

@@ -0,0 +1,37 @@
+"use strict";
+const NodeObfuscator_1 = require('./NodeObfuscator');
+const Utils_1 = require('../Utils');
+let estraverse = require('estraverse');
+class FunctionDeclarationObfuscator extends NodeObfuscator_1.NodeObfuscator {
+    constructor(...args) {
+        super(...args);
+        this.functionName = new Map();
+    }
+    obfuscateNode(functionDeclarationNode, parentNode) {
+        if (parentNode.type === 'Program') {
+            return;
+        }
+        this.replaceFunctionName(functionDeclarationNode);
+        this.replaceFunctionCalls(parentNode);
+    }
+    replaceFunctionName(functionDeclarationNode) {
+        estraverse.replace(functionDeclarationNode.id, {
+            leave: (node) => {
+                if (node.type !== 'Identifier') {
+                    return;
+                }
+                this.functionName.set(node.name, Utils_1.Utils.getRandomVariableName());
+                node.name = this.functionName.get(node.name);
+            }
+        });
+    }
+    replaceFunctionCalls(functionParentNode) {
+        estraverse.replace(functionParentNode, {
+            leave: (node, parentNode) => {
+                this.replaceNodeIdentifierByNewValue(node, parentNode, this.functionName);
+            }
+        });
+    }
+}
+exports.FunctionDeclarationObfuscator = FunctionDeclarationObfuscator;
+//# sourceMappingURL=FunctionDeclarationObfuscator.js.map

+ 36 - 0
src/node-obfuscators/FunctionObfuscator.js

@@ -0,0 +1,36 @@
+"use strict";
+const NodeObfuscator_1 = require('./NodeObfuscator');
+const Utils_1 = require('../Utils');
+let estraverse = require('estraverse');
+class FunctionObfuscator extends NodeObfuscator_1.NodeObfuscator {
+    constructor(...args) {
+        super(...args);
+        this.functionParams = new Map();
+    }
+    obfuscateNode(functionNode) {
+        this.replaceFunctionParams(functionNode);
+        this.replaceFunctionParamsInBody(functionNode);
+    }
+    replaceFunctionParams(functionNode) {
+        functionNode.params.forEach((paramsNode) => {
+            estraverse.replace(paramsNode, {
+                leave: (node, parentNode) => {
+                    if (node.type !== 'Identifier') {
+                        return;
+                    }
+                    this.functionParams.set(node.name, Utils_1.Utils.getRandomVariableName());
+                    node.name = this.functionParams.get(node.name);
+                }
+            });
+        });
+    }
+    replaceFunctionParamsInBody(functionNode) {
+        estraverse.replace(functionNode.body, {
+            leave: (node, parentNode) => {
+                this.replaceNodeIdentifierByNewValue(node, parentNode, this.functionParams);
+            }
+        });
+    }
+}
+exports.FunctionObfuscator = FunctionObfuscator;
+//# sourceMappingURL=FunctionObfuscator.js.map

+ 23 - 0
src/node-obfuscators/LiteralObfuscator.js

@@ -0,0 +1,23 @@
+"use strict";
+const NodeObfuscator_1 = require('./NodeObfuscator');
+let escodegen = require('escodegen'), estraverse = require('estraverse');
+class LiteralObfuscator extends NodeObfuscator_1.NodeObfuscator {
+    obfuscateNode(literalNode, parentNode) {
+        if (parentNode.type === 'Property' && parentNode.key === literalNode) {
+            return;
+        }
+        switch (typeof literalNode.value) {
+            case 'string':
+                if (literalNode['x-verbatim-property']) {
+                    break;
+                }
+                literalNode['x-verbatim-property'] = {
+                    content: this.replaceLiteralStringByArrayElement(literalNode.value),
+                    precedence: escodegen.Precedence.Primary
+                };
+                break;
+        }
+    }
+}
+exports.LiteralObfuscator = LiteralObfuscator;
+//# sourceMappingURL=LiteralObfuscator.js.map

+ 49 - 0
src/node-obfuscators/MemberExpressionObfuscator.js

@@ -0,0 +1,49 @@
+"use strict";
+const NodeObfuscator_1 = require('./NodeObfuscator');
+let escodegen = require('escodegen'), estraverse = require('estraverse');
+class MemberExpressionObfuscator extends NodeObfuscator_1.NodeObfuscator {
+    obfuscateNode(memberExpressionNode) {
+        estraverse.replace(memberExpressionNode.property, {
+            leave: (node, parentNode) => {
+                switch (node.type) {
+                    case 'Literal':
+                        this.literalNodeController(node);
+                        break;
+                    case 'Identifier':
+                        if (memberExpressionNode.computed) {
+                            break;
+                        }
+                        memberExpressionNode.computed = true;
+                        this.identifierNodeController(node);
+                        break;
+                }
+            }
+        });
+    }
+    identifierNodeController(node) {
+        let nodeValue = node['name'];
+        node['type'] = 'Literal';
+        node['value'] = nodeValue;
+        node['raw'] = `'${nodeValue}'`;
+        node['x-verbatim-property'] = {
+            content: this.replaceLiteralStringByArrayElement(nodeValue),
+            precedence: escodegen['Precedence']['Primary']
+        };
+        delete node['name'];
+    }
+    literalNodeController(node) {
+        switch (typeof node.value) {
+            case 'string':
+                if (node['x-verbatim-property']) {
+                    break;
+                }
+                node['x-verbatim-property'] = {
+                    content: this.replaceLiteralStringByArrayElement(node.value),
+                    precedence: escodegen['Precedence']['Primary']
+                };
+                break;
+        }
+    }
+}
+exports.MemberExpressionObfuscator = MemberExpressionObfuscator;
+//# sourceMappingURL=MemberExpressionObfuscator.js.map

+ 28 - 0
src/node-obfuscators/MethodDefinitionObfuscator.js

@@ -0,0 +1,28 @@
+"use strict";
+const NodeObfuscator_1 = require('./NodeObfuscator');
+let estraverse = require('estraverse');
+class MethodDefinitionObfuscator extends NodeObfuscator_1.NodeObfuscator {
+    constructor(...args) {
+        super(...args);
+        this.methodName = new Map();
+        this.ignoredNames = ['constructor'];
+    }
+    obfuscateNode(methodDefinitionNode, parentNode) {
+        this.replaceMethodName(methodDefinitionNode);
+    }
+    replaceMethodName(methodDefinitionNode) {
+        estraverse.replace(methodDefinitionNode.key, {
+            leave: (node) => {
+                if (node.type !== 'Identifier' ||
+                    this.ignoredNames.indexOf(node.name) >= 0 ||
+                    methodDefinitionNode.computed === true) {
+                    return;
+                }
+                methodDefinitionNode.computed = true;
+                node.name = this.replaceLiteralStringByArrayElement(node.name);
+            }
+        });
+    }
+}
+exports.MethodDefinitionObfuscator = MethodDefinitionObfuscator;
+//# sourceMappingURL=MethodDefinitionObfuscator.js.map

+ 29 - 0
src/node-obfuscators/NodeObfuscator.js

@@ -0,0 +1,29 @@
+"use strict";
+const Utils_1 = require('../Utils');
+class NodeObfuscator {
+    constructor(nodes) {
+        this.nodes = nodes;
+    }
+    replaceNodeIdentifierByNewValue(node, parentNode, namesMap) {
+        if (node.type === 'Identifier' && namesMap.has(node.name)) {
+            if ((parentNode.type === 'Property' && parentNode.key === node) ||
+                (parentNode.type === 'MemberExpression' && parentNode.computed === false && parentNode.property === node)) {
+                return;
+            }
+            node.name = namesMap.get(node.name);
+        }
+    }
+    replaceLiteralStringByArrayElement(nodeValue) {
+        let value = Utils_1.Utils.stringToUnicode(nodeValue), unicodeArray = this.nodes.get('unicodeArrayNode').getNodeData(), sameIndex = unicodeArray.indexOf(value), index;
+        if (sameIndex < 0) {
+            index = unicodeArray.length;
+            unicodeArray.push(Utils_1.Utils.stringToUnicode(nodeValue));
+        }
+        else {
+            index = sameIndex;
+        }
+        return `${this.nodes.get('unicodeArrayNode').getNodeIdentifier()}[${index}]`;
+    }
+}
+exports.NodeObfuscator = NodeObfuscator;
+//# sourceMappingURL=NodeObfuscator.js.map

+ 48 - 0
src/node-obfuscators/ObjectExpressionObfuscator.js

@@ -0,0 +1,48 @@
+"use strict";
+const NodeObfuscator_1 = require('./NodeObfuscator');
+const Utils_1 = require('../Utils');
+let escodegen = require('escodegen'), estraverse = require('estraverse');
+class ObjectExpressionObfuscator extends NodeObfuscator_1.NodeObfuscator {
+    obfuscateNode(objectExpressionNode) {
+        objectExpressionNode.properties.forEach((property) => {
+            estraverse.replace(property.key, {
+                leave: (node, parentNode) => {
+                    switch (node.type) {
+                        case 'Literal':
+                            this.literalNodeController(node);
+                            break;
+                        case 'Identifier':
+                            this.identifierNodeController(node);
+                            break;
+                    }
+                }
+            });
+        });
+    }
+    literalNodeController(node) {
+        switch (typeof node.value) {
+            case 'string':
+                if (node['x-verbatim-property']) {
+                    break;
+                }
+                node['x-verbatim-property'] = {
+                    content: Utils_1.Utils.stringToUnicode(node.value),
+                    precedence: escodegen['Precedence']['Primary']
+                };
+                break;
+        }
+    }
+    identifierNodeController(node) {
+        let nodeValue = node['name'];
+        node['type'] = 'Literal';
+        node['value'] = nodeValue;
+        node['raw'] = `'${nodeValue}'`;
+        node['x-verbatim-property'] = {
+            content: Utils_1.Utils.stringToUnicode(nodeValue),
+            precedence: escodegen['Precedence']['Primary']
+        };
+        delete node['name'];
+    }
+}
+exports.ObjectExpressionObfuscator = ObjectExpressionObfuscator;
+//# sourceMappingURL=ObjectExpressionObfuscator.js.map

+ 43 - 0
src/node-obfuscators/VariableDeclarationObfuscator.js

@@ -0,0 +1,43 @@
+"use strict";
+const NodeObfuscator_1 = require('./NodeObfuscator');
+const Utils_1 = require('../Utils');
+let estraverse = require('estraverse');
+class VariableDeclarationObfuscator extends NodeObfuscator_1.NodeObfuscator {
+    constructor(...args) {
+        super(...args);
+        this.variableName = new Map();
+    }
+    obfuscateNode(variableDeclarationNode, parentNode) {
+        if (parentNode.type === 'Program') {
+            return;
+        }
+        this.replaceVariableName(variableDeclarationNode);
+        this.replaceVariableCalls(parentNode);
+    }
+    replaceVariableName(variableDeclarationNode) {
+        variableDeclarationNode.declarations.forEach((declarationNode) => {
+            estraverse.replace(declarationNode, {
+                leave: (node) => {
+                    if (node.type !== 'VariableDeclarator') {
+                        return;
+                    }
+                    estraverse.replace(node.id, {
+                        leave: (node) => {
+                            this.variableName.set(node.name, Utils_1.Utils.getRandomVariableName());
+                            node.name = this.variableName.get(node.name);
+                        }
+                    });
+                }
+            });
+        });
+    }
+    replaceVariableCalls(variableParentNode) {
+        estraverse.replace(variableParentNode, {
+            leave: (node, parentNode) => {
+                this.replaceNodeIdentifierByNewValue(node, parentNode, this.variableName);
+            }
+        });
+    }
+}
+exports.VariableDeclarationObfuscator = VariableDeclarationObfuscator;
+//# sourceMappingURL=VariableDeclarationObfuscator.js.map

+ 21 - 0
src/nodes/Node.js

@@ -0,0 +1,21 @@
+"use strict";
+const AppendState_1 = require('../enums/AppendState');
+class Node {
+    constructor() {
+        this.appendState = AppendState_1.AppendState.BeforeObfuscation;
+    }
+    getAppendState() {
+        return this.appendState;
+    }
+    getNode() {
+        return this.node;
+    }
+    setNode(node) {
+        this.node = node;
+    }
+    updateNode() {
+        this.node = this.getNodeStructure();
+    }
+}
+exports.Node = Node;
+//# sourceMappingURL=Node.js.map

+ 70 - 0
src/nodes/UnicodeArrayNode.js

@@ -0,0 +1,70 @@
+"use strict";
+const Node_1 = require('./Node');
+const Utils_1 = require('../Utils');
+const AppendState_1 = require('../enums/AppendState');
+let escodegen = require('escodegen'), estraverse = require('estraverse');
+class UnicodeArrayNode extends Node_1.Node {
+    constructor(astTree, unicodeArrayName, unicodeArrayRotateValue = 0) {
+        super();
+        this.appendState = AppendState_1.AppendState.AfterObfuscation;
+        this.unicodeArray = [];
+        this.astTree = astTree;
+        this.unicodeArrayName = unicodeArrayName;
+        this.unicodeArrayRotateValue = unicodeArrayRotateValue;
+        this.node = this.getNodeStructure();
+    }
+    appendNode() {
+        estraverse.replace(this.astTree, {
+            leave: (node, parent) => {
+                switch (node.type) {
+                    case 'Program':
+                        node.body.unshift(this.getNode());
+                        break;
+                }
+            }
+        });
+    }
+    getNodeIdentifier() {
+        return this.unicodeArrayName;
+    }
+    getNodeData() {
+        return this.unicodeArray;
+    }
+    getNode() {
+        Utils_1.Utils.arrayRotate(this.unicodeArray, this.unicodeArrayRotateValue);
+        this.updateNode();
+        return this.node;
+    }
+    getNodeStructure() {
+        return {
+            'type': 'VariableDeclaration',
+            'declarations': [
+                {
+                    'type': 'VariableDeclarator',
+                    'id': {
+                        'type': 'Identifier',
+                        'name': this.unicodeArrayName
+                    },
+                    'init': {
+                        'type': 'ArrayExpression',
+                        'elements': this.unicodeArray.map((value) => {
+                            return {
+                                'type': 'Literal',
+                                'value': value,
+                                'raw': `'${value}'`,
+                                'x-verbatim-property': {
+                                    'content': value,
+                                    precedence: escodegen.Precedence.Primary
+                                }
+                            };
+                        })
+                    }
+                }
+            ],
+            'kind': 'var'
+        };
+    }
+}
+UnicodeArrayNode.UNICODE_ARRAY_RANDOM_LENGTH = 4;
+exports.UnicodeArrayNode = UnicodeArrayNode;
+//# sourceMappingURL=UnicodeArrayNode.js.map

+ 54 - 0
src/nodes/UnicodeArrayRotateFunctionCallNode.js

@@ -0,0 +1,54 @@
+"use strict";
+const Node_1 = require('./Node');
+let estraverse = require('estraverse');
+class UnicodeArrayRotateFunctionCallNode extends Node_1.Node {
+    constructor(astTree, unicodeArrayRotateFunctionName, unicodeArrayName, unicodeArrayRotateValue) {
+        super();
+        this.astTree = astTree;
+        this.unicodeArrayRotateFunctionName = unicodeArrayRotateFunctionName;
+        this.unicodeArrayName = unicodeArrayName;
+        this.unicodeArrayRotateValue = unicodeArrayRotateValue;
+        this.node = this.getNodeStructure();
+    }
+    appendNode() {
+        estraverse.replace(this.astTree, {
+            leave: (node, parent) => {
+                switch (node.type) {
+                    case 'Program':
+                        node.body.unshift(this.getNode());
+                        break;
+                }
+            }
+        });
+    }
+    getNodeStructure() {
+        return {
+            'type': 'ExpressionStatement',
+            'expression': {
+                'type': 'CallExpression',
+                'callee': {
+                    'type': 'Identifier',
+                    'name': this.unicodeArrayRotateFunctionName
+                },
+                'arguments': [
+                    {
+                        'type': 'Identifier',
+                        'name': this.unicodeArrayName
+                    },
+                    {
+                        'type': 'Literal',
+                        'value': this.unicodeArrayRotateValue,
+                        'raw': `'${this.unicodeArrayRotateValue}'`
+                    },
+                    {
+                        'type': 'Literal',
+                        'value': true,
+                        'raw': 'true'
+                    }
+                ]
+            }
+        };
+    }
+}
+exports.UnicodeArrayRotateFunctionCallNode = UnicodeArrayRotateFunctionCallNode;
+//# sourceMappingURL=UnicodeArrayRotateFunctionCallNode.js.map

+ 269 - 0
src/nodes/UnicodeArrayRotateFunctionNode.js

@@ -0,0 +1,269 @@
+"use strict";
+const Node_1 = require('./Node');
+const Utils_1 = require('../Utils');
+let estraverse = require('estraverse');
+class UnicodeArrayRotateFunctionNode extends Node_1.Node {
+    constructor(astTree, unicodeArrayRotateFunctionName, unicodeArrayName) {
+        super();
+        this.astTree = astTree;
+        this.unicodeArrayRotateFunctionName = unicodeArrayRotateFunctionName;
+        this.unicodeArrayName = unicodeArrayName;
+        this.node = this.getNodeStructure();
+    }
+    appendNode() {
+        estraverse.replace(this.astTree, {
+            leave: (node, parent) => {
+                switch (node.type) {
+                    case 'Program':
+                        node.body.push(this.getNode());
+                        break;
+                }
+            }
+        });
+    }
+    getNodeIdentifier() {
+        return this.unicodeArrayRotateFunctionName;
+    }
+    getNodeStructure() {
+        return {
+            'type': 'FunctionExpression',
+            'id': {
+                'type': 'Identifier',
+                'name': this.unicodeArrayRotateFunctionName
+            },
+            'params': [
+                {
+                    'type': 'Identifier',
+                    'name': 'array'
+                },
+                {
+                    'type': 'Identifier',
+                    'name': 'times'
+                },
+                {
+                    'type': 'Identifier',
+                    'name': 'reverse'
+                }
+            ],
+            'defaults': [],
+            'body': {
+                'type': 'BlockStatement',
+                'body': [
+                    {
+                        'type': 'IfStatement',
+                        'test': {
+                            'type': 'BinaryExpression',
+                            'operator': '<',
+                            'left': {
+                                'type': 'Identifier',
+                                'name': 'times'
+                            },
+                            'right': {
+                                'type': 'Literal',
+                                'value': 0,
+                                'raw': '0'
+                            }
+                        },
+                        'consequent': {
+                            'type': 'BlockStatement',
+                            'body': [
+                                {
+                                    'type': 'ReturnStatement',
+                                    'argument': null
+                                }
+                            ]
+                        },
+                        'alternate': null
+                    },
+                    {
+                        'type': 'ExpressionStatement',
+                        'expression': {
+                            'type': 'AssignmentExpression',
+                            'operator': '=',
+                            'left': {
+                                'type': 'Identifier',
+                                'name': 'reverse'
+                            },
+                            'right': {
+                                'type': 'LogicalExpression',
+                                'operator': '||',
+                                'left': {
+                                    'type': 'Identifier',
+                                    'name': 'reverse'
+                                },
+                                'right': {
+                                    'type': 'Literal',
+                                    'value': false,
+                                    'raw': 'false'
+                                }
+                            }
+                        }
+                    },
+                    {
+                        'type': 'VariableDeclaration',
+                        'declarations': [
+                            {
+                                'type': 'VariableDeclarator',
+                                'id': {
+                                    'type': 'Identifier',
+                                    'name': 'temp'
+                                },
+                                'init': null
+                            }
+                        ],
+                        'kind': 'var'
+                    },
+                    {
+                        'type': 'WhileStatement',
+                        'test': {
+                            'type': 'UpdateExpression',
+                            'operator': '--',
+                            'argument': {
+                                'type': 'Identifier',
+                                'name': 'times'
+                            },
+                            'prefix': false
+                        },
+                        'body': {
+                            'type': 'BlockStatement',
+                            'body': [
+                                {
+                                    'type': 'IfStatement',
+                                    'test': {
+                                        'type': 'UnaryExpression',
+                                        'operator': '!',
+                                        'argument': {
+                                            'type': 'Identifier',
+                                            'name': 'reverse'
+                                        },
+                                        'prefix': true
+                                    },
+                                    'consequent': {
+                                        'type': 'BlockStatement',
+                                        'body': [
+                                            {
+                                                'type': 'ExpressionStatement',
+                                                'expression': {
+                                                    'type': 'AssignmentExpression',
+                                                    'operator': '=',
+                                                    'left': {
+                                                        'type': 'Identifier',
+                                                        'name': 'temp'
+                                                    },
+                                                    'right': {
+                                                        'type': 'CallExpression',
+                                                        'callee': {
+                                                            'type': 'MemberExpression',
+                                                            'computed': true,
+                                                            'object': {
+                                                                'type': 'Identifier',
+                                                                'name': 'array'
+                                                            },
+                                                            'property': {
+                                                                'type': 'Literal',
+                                                                'name': 'pop',
+                                                                'x-verbatim-property': Utils_1.Utils.stringToUnicode('pop')
+                                                            }
+                                                        },
+                                                        'arguments': []
+                                                    }
+                                                }
+                                            },
+                                            {
+                                                'type': 'ExpressionStatement',
+                                                'expression': {
+                                                    'type': 'CallExpression',
+                                                    'callee': {
+                                                        'type': 'MemberExpression',
+                                                        'computed': true,
+                                                        'object': {
+                                                            'type': 'Identifier',
+                                                            'name': 'array'
+                                                        },
+                                                        'property': {
+                                                            'type': 'Literal',
+                                                            'name': 'unshift',
+                                                            'x-verbatim-property': Utils_1.Utils.stringToUnicode('unshift')
+                                                        }
+                                                    },
+                                                    'arguments': [
+                                                        {
+                                                            'type': 'Identifier',
+                                                            'name': 'temp'
+                                                        }
+                                                    ]
+                                                }
+                                            }
+                                        ]
+                                    },
+                                    'alternate': {
+                                        'type': 'BlockStatement',
+                                        'body': [
+                                            {
+                                                'type': 'ExpressionStatement',
+                                                'expression': {
+                                                    'type': 'AssignmentExpression',
+                                                    'operator': '=',
+                                                    'left': {
+                                                        'type': 'Identifier',
+                                                        'name': 'temp'
+                                                    },
+                                                    'right': {
+                                                        'type': 'CallExpression',
+                                                        'callee': {
+                                                            'type': 'MemberExpression',
+                                                            'computed': true,
+                                                            'object': {
+                                                                'type': 'Identifier',
+                                                                'name': 'array'
+                                                            },
+                                                            'property': {
+                                                                'type': 'Literal',
+                                                                'name': 'shift',
+                                                                'x-verbatim-property': Utils_1.Utils.stringToUnicode('shift')
+                                                            }
+                                                        },
+                                                        'arguments': []
+                                                    }
+                                                }
+                                            },
+                                            {
+                                                'type': 'ExpressionStatement',
+                                                'expression': {
+                                                    'type': 'CallExpression',
+                                                    'callee': {
+                                                        'type': 'MemberExpression',
+                                                        'computed': true,
+                                                        'object': {
+                                                            'type': 'Identifier',
+                                                            'name': 'array'
+                                                        },
+                                                        'property': {
+                                                            'type': 'Literal',
+                                                            'name': 'push',
+                                                            'x-verbatim-property': Utils_1.Utils.stringToUnicode('push')
+                                                        }
+                                                    },
+                                                    'arguments': [
+                                                        {
+                                                            'type': 'Identifier',
+                                                            'name': 'temp'
+                                                        }
+                                                    ]
+                                                }
+                                            }
+                                        ]
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                ]
+            },
+            'generator': false,
+            'expression': false
+        };
+    }
+}
+exports.UnicodeArrayRotateFunctionNode = UnicodeArrayRotateFunctionNode;
+//# sourceMappingURL=UnicodeArrayRotateFunctionNode.js.map