Code coverage report for src/node-transformers/node-obfuscators/VariableDeclarationObfuscator.ts

# All files / src/node-transformers/node-obfuscators VariableDeclarationObfuscator.ts

100% Statements 27/27
100% Branches 8/8
100% Functions 3/3
100% Lines 26/26

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    1051x
    1x

    1x

    1x
    1x

    1x

    1x
    1x
    1x

    1x
    1x

    2614x

    2614x

    28109x

    28109x

    28109x
    1579x

    26530x

    26530x
    26530x

    26530x

    30596x
    30596x

    26530x

    3324545x
    796660x

     import { injectable, inject } from 'inversify';
    import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';

    import * as estraverse from 'estraverse';
    import * as ESTree from 'estree';

    import { TNodeWithBlockStatement } from '../../types/node/TNodeWithBlockStatement';

    import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
    import { IOptions } from '../../interfaces/options/IOptions';
    import { IReplacer } from '../../interfaces/node-transformers/IReplacer';
    import { IStorage } from '../../interfaces/storages/IStorage';

    import { NodeObfuscatorsReplacers } from '../../enums/container/NodeObfuscatorsReplacers';
    import { NodeType } from '../../enums/NodeType';

    import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
    import { IdentifierReplacer } from './replacers/IdentifierReplacer';
    import { Node } from '../../node/Node';
    import { NodeUtils } from '../../node/NodeUtils';
    import { Utils } from '../../Utils';

    /**
     * replaces:
     *     var variable = 1;
     *     variable++;
     *
     * on:
     *     var _0x12d45f = 1;
     *     _0x12d45f++;
     *
     */
    @injectable()
    export class VariableDeclarationObfuscator extends AbstractNodeTransformer {
        /**
         * @type {IdentifierReplacer}
         */
        private readonly identifierReplacer: IReplacer & IdentifierReplacer;

        /**
         * @param customNodesStorage
         * @param replacersFactory
         * @param options
         */
        constructor(
            @inject(ServiceIdentifiers['IStorage<ICustomNode>']) customNodesStorage: IStorage<ICustomNode>,
            @inject(ServiceIdentifiers['Factory<IReplacer>']) replacersFactory: (replacer: NodeObfuscatorsReplacers) => IReplacer,
            @inject(ServiceIdentifiers.IOptions) options: IOptions
        ) {
            super(customNodesStorage, options);

            this.identifierReplacer = <IdentifierReplacer>replacersFactory(NodeObfuscatorsReplacers.IdentifierReplacer);
        }

        /**
         * @param variableDeclarationNode
         * @param parentNode
         */
        public transformNode (variableDeclarationNode: ESTree.VariableDeclaration, parentNode: ESTree.Node): void {
            this.identifierReplacer.setPrefix(Utils.getRandomGenerator().string({
                length: 5,
                pool: Utils.randomGeneratorPool
            }));

            const blockScopeOfVariableDeclarationNode: TNodeWithBlockStatement = NodeUtils
                .getBlockScopeOfNode(variableDeclarationNode);

            if (blockScopeOfVariableDeclarationNode.type === NodeType.Program) {
                return;
            }

            const scopeNode: ESTree.Node = variableDeclarationNode.kind === 'var'
                ? blockScopeOfVariableDeclarationNode
                : parentNode;

            this.storeVariableNames(variableDeclarationNode);
            this.replaceVariableNames(scopeNode);
        }

        /**
         * @param variableDeclarationNode
         */
        private storeVariableNames (variableDeclarationNode: ESTree.VariableDeclaration): void {
            variableDeclarationNode.declarations
                .forEach((declarationNode: ESTree.VariableDeclarator) => {
                    NodeUtils.typedTraverse(declarationNode.id, NodeType.Identifier, {
                        enter: (node: ESTree.Identifier) => this.identifierReplacer.storeNames(node.name)
                    });
                });
        }

        /**
         * @param scopeNode
         */
        private replaceVariableNames (scopeNode: ESTree.Node): void {
            estraverse.replace(scopeNode, {
                enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
                    if (!node.obfuscated && Node.isReplaceableIdentifierNode(node, parentNode)) {
                        node.name = this.identifierReplacer.replace(node.name);
                    }
                }
            });
        }
    }