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                                                           6265x 6265x 6265x                 6265x     6265x     6265x   6265x               6265x       6265x 9x 9x     6265x       6265x   6265x   6265x               6265x            
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
        );
    }
}