All files / src JavaScriptObfuscatorInternal.ts

100% Statements 23/23
100% Branches 4/4
100% Functions 1/1
100% Lines 22/22
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 105 106 107 1081x 1x   1x 1x                     1x       1x                                                           6254x 6254x 6254x                 6254x     6254x     6254x   6254x               6254x       6254x 9x 9x     6254x       6254x   6254x   6254x               6254x            
import { injectable, inject } from 'inversify';
import { ServiceIdentifiers } from './container/ServiceIdentifiers';
 
import * as esprima from 'esprima';
import * as escodegen from 'escodegen';
import * as ESTree from 'estree';
 
import { IGeneratorOutput } from './interfaces/IGeneratorOutput';
import { IJavaScriptObfuscator } from './interfaces/IJavaScriptObfsucator';
import { IObfuscationResult } from './interfaces/IObfuscationResult';
import { IObfuscator } from './interfaces/IObfuscator';
import { IOptions } from './interfaces/options/IOptions';
import { ISourceMapCorrector } from './interfaces/ISourceMapCorrector';
 
@injectable()
export class JavaScriptObfuscatorInternal implements IJavaScriptObfuscator {
    /**
     * @type {GenerateOptions}
     */
    private static readonly escodegenParams: escodegen.GenerateOptions = {
        verbatim: 'x-verbatim-property',
        sourceMapWithCode: true
    };
 
    /**
     * @type {IObfuscator}
     */
    private readonly obfuscator: IObfuscator;
 
    /**
     * @type {IOptions}
     */
    private readonly options: IOptions;
 
    /**
     * @type {ISourceMapCorrector}
     */
    private readonly sourceMapCorrector: ISourceMapCorrector;
 
    /**
     * @param obfuscator
     * @param sourceMapCorrector
     * @param options
     */
    constructor (
        @inject(ServiceIdentifiers.IObfuscator) obfuscator: IObfuscator,
        @inject(ServiceIdentifiers.ISourceMapCorrector) sourceMapCorrector: ISourceMapCorrector,
        @inject(ServiceIdentifiers.IOptions) options: IOptions
    ) {
        this.obfuscator = obfuscator;
        this.sourceMapCorrector = sourceMapCorrector;
        this.options = options;
    }
 
    /**
     * @param sourceCode
     * @returns {IObfuscationResult}
     */
    public obfuscate (sourceCode: string): IObfuscationResult {
        // parse AST tree
        const astTree: ESTree.Program = esprima.parse(sourceCode, { loc: this.options.sourceMap });
 
        // obfuscate AST tree
        const obfuscatedAstTree: ESTree.Program = this.obfuscator.obfuscateAstTree(astTree);
 
        // generate code
        const generatorOutput: IGeneratorOutput = this.generateCode(sourceCode, obfuscatedAstTree);
 
        return this.getObfuscationResult(generatorOutput);
    }
 
    /**
     * @param sourceCode
     * @param astTree
     */
    private generateCode (sourceCode: string, astTree: ESTree.Program): IGeneratorOutput {
        const escodegenParams: escodegen.GenerateOptions = {
            ...JavaScriptObfuscatorInternal.escodegenParams
        };
 
        if (this.options.sourceMap) {
            escodegenParams.sourceMap = 'sourceMap';
            escodegenParams.sourceContent = sourceCode;
        }
 
        escodegenParams.format = {
            compact: this.options.compact
        };
 
        const generatorOutput: IGeneratorOutput = escodegen.generate(astTree, escodegenParams);
 
        generatorOutput.map = generatorOutput.map ? generatorOutput.map.toString() : '';
 
        return generatorOutput;
    }
 
    /**
     * @param generatorOutput
     * @returns {IObfuscationResult}
     */
    private getObfuscationResult (generatorOutput: IGeneratorOutput): IObfuscationResult {
        return this.sourceMapCorrector.correct(
            generatorOutput.code,
            generatorOutput.map
        );
    }
}