• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

javascript-obfuscator / javascript-obfuscator / 20084197189

07 Dec 2025 08:42AM UTC coverage: 95.728%. Remained the same
20084197189

push

github

web-flow
Version 5.0.1 (#1344)

1792 of 1970 branches covered (90.96%)

Branch coverage included in aggregate %.

57 of 68 new or added lines in 5 files covered. (83.82%)

1 existing line in 1 file now uncovered.

5737 of 5895 relevant lines covered (97.32%)

33358411.57 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.45
/src/JavaScriptObfuscator.ts
1
import { inject, injectable } from 'inversify';
6✔
2
import { ServiceIdentifiers } from './container/ServiceIdentifiers';
6✔
3

4
import * as acorn from 'acorn';
5
import * as escodegen from '@javascript-obfuscator/escodegen';
6✔
6
import * as ESTree from 'estree';
7

8
import { TObfuscationResultFactory } from './types/container/source-code/TObfuscationResultFactory';
9

10
import { ICodeTransformersRunner } from './interfaces/code-transformers/ICodeTransformersRunner';
11
import { IGeneratorOutput } from './interfaces/IGeneratorOutput';
12
import { IJavaScriptObfuscator } from './interfaces/IJavaScriptObfsucator';
13
import { ILogger } from './interfaces/logger/ILogger';
14
import { IObfuscationResult } from './interfaces/source-code/IObfuscationResult';
15
import { IOptions } from './interfaces/options/IOptions';
16
import { IRandomGenerator } from './interfaces/utils/IRandomGenerator';
17
import { INodeTransformersRunner } from './interfaces/node-transformers/INodeTransformersRunner';
18

19
import { CodeTransformer } from './enums/code-transformers/CodeTransformer';
6✔
20
import { CodeTransformationStage } from './enums/code-transformers/CodeTransformationStage';
6✔
21
import { LoggingMessage } from './enums/logger/LoggingMessage';
6✔
22
import { NodeTransformer } from './enums/node-transformers/NodeTransformer';
6✔
23
import { NodeTransformationStage } from './enums/node-transformers/NodeTransformationStage';
6✔
24
import { SourceMapSourcesMode } from './enums/source-map/SourceMapSourcesMode';
6✔
25

26
import { ecmaVersion } from './constants/EcmaVersion';
6✔
27

28
import { ASTParserFacade } from './ASTParserFacade';
6✔
29
import { NodeGuards } from './node/NodeGuards';
6✔
30
import { Utils } from './utils/Utils';
6✔
31
import { AdvertisementUtils } from './utils/AdvertisementUtils';
6✔
32

33
@injectable()
34
export class JavaScriptObfuscator implements IJavaScriptObfuscator {
6✔
35
    /**
36
     * @type {Options}
37
     */
38
    private static readonly parseOptions: acorn.Options = {
6✔
39
        ecmaVersion,
40
        allowHashBang: true,
41
        allowImportExportEverywhere: true,
42
        allowReturnOutsideFunction: true,
43
        locations: true,
44
        ranges: true
45
    };
46

47
    /**
48
     * @type {GenerateOptions}
49
     */
50
    private static readonly escodegenParams: escodegen.GenerateOptions = {
6✔
51
        comment: true,
52
        verbatim: 'x-verbatim-property',
53
        sourceMapWithCode: true
54
    };
55

56
    /**
57
     * @type {CodeTransformer[]}
58
     */
59
    private static readonly codeTransformersList: CodeTransformer[] = [CodeTransformer.HashbangOperatorTransformer];
6✔
60

61
    /**
62
     * @type {NodeTransformer[]}
63
     */
64
    private static readonly nodeTransformersList: NodeTransformer[] = [
6✔
65
        NodeTransformer.BooleanLiteralTransformer,
66
        NodeTransformer.BlockStatementControlFlowTransformer,
67
        NodeTransformer.BlockStatementSimplifyTransformer,
68
        NodeTransformer.ClassFieldTransformer,
69
        NodeTransformer.CommentsTransformer,
70
        NodeTransformer.CustomCodeHelpersTransformer,
71
        NodeTransformer.DeadCodeInjectionTransformer,
72
        NodeTransformer.EscapeSequenceTransformer,
73
        NodeTransformer.EvalCallExpressionTransformer,
74
        NodeTransformer.ExportSpecifierTransformer,
75
        NodeTransformer.ExpressionStatementsMergeTransformer,
76
        NodeTransformer.FunctionControlFlowTransformer,
77
        NodeTransformer.IfStatementSimplifyTransformer,
78
        NodeTransformer.LabeledStatementTransformer,
79
        NodeTransformer.RenamePropertiesTransformer,
80
        NodeTransformer.MemberExpressionTransformer,
81
        NodeTransformer.MetadataTransformer,
82
        NodeTransformer.NumberLiteralTransformer,
83
        NodeTransformer.NumberToNumericalExpressionTransformer,
84
        NodeTransformer.ObfuscatingGuardsTransformer,
85
        NodeTransformer.ObjectExpressionKeysTransformer,
86
        NodeTransformer.ObjectExpressionTransformer,
87
        NodeTransformer.ObjectPatternPropertiesTransformer,
88
        NodeTransformer.ParentificationTransformer,
89
        NodeTransformer.ScopeIdentifiersTransformer,
90
        NodeTransformer.ScopeThroughIdentifiersTransformer,
91
        NodeTransformer.SplitStringTransformer,
92
        NodeTransformer.StringArrayControlFlowTransformer,
93
        NodeTransformer.StringArrayRotateFunctionTransformer,
94
        NodeTransformer.StringArrayScopeCallsWrapperTransformer,
95
        NodeTransformer.StringArrayTransformer,
96
        NodeTransformer.TemplateLiteralTransformer,
97
        NodeTransformer.DirectivePlacementTransformer,
98
        NodeTransformer.VariableDeclarationsMergeTransformer,
99
        NodeTransformer.VariablePreserveTransformer
100
    ];
101

102
    /**
103
     * @type {ICodeTransformersRunner}
104
     */
105
    private readonly codeTransformersRunner: ICodeTransformersRunner;
106

107
    /**
108
     * @type {ILogger}
109
     */
110
    private readonly logger: ILogger;
111

112
    /**
113
     * @type {TObfuscationResultFactory}
114
     */
115
    private readonly obfuscationResultFactory: TObfuscationResultFactory;
116

117
    /**
118
     * @type {IOptions}
119
     */
120
    private readonly options: IOptions;
121

122
    /**
123
     * @type {IRandomGenerator}
124
     */
125
    private readonly randomGenerator: IRandomGenerator;
126

127
    /**
128
     * @type {INodeTransformersRunner}
129
     */
130
    private readonly nodeTransformersRunner: INodeTransformersRunner;
131

132
    /**
133
     * @param {ICodeTransformersRunner} codeTransformersRunner
134
     * @param {INodeTransformersRunner} nodeTransformersRunner
135
     * @param {IRandomGenerator} randomGenerator
136
     * @param {TObfuscationResultFactory} obfuscatedCodeFactory
137
     * @param {ILogger} logger
138
     * @param {IOptions} options
139
     */
140
    public constructor(
141
        @inject(ServiceIdentifiers.ICodeTransformersRunner) codeTransformersRunner: ICodeTransformersRunner,
142
        @inject(ServiceIdentifiers.INodeTransformersRunner) nodeTransformersRunner: INodeTransformersRunner,
143
        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
144
        @inject(ServiceIdentifiers.Factory__IObfuscationResult) obfuscatedCodeFactory: TObfuscationResultFactory,
145
        @inject(ServiceIdentifiers.ILogger) logger: ILogger,
146
        @inject(ServiceIdentifiers.IOptions) options: IOptions
147
    ) {
148
        this.codeTransformersRunner = codeTransformersRunner;
197,760✔
149
        this.nodeTransformersRunner = nodeTransformersRunner;
197,760✔
150
        this.randomGenerator = randomGenerator;
197,760✔
151
        this.obfuscationResultFactory = obfuscatedCodeFactory;
197,760✔
152
        this.logger = logger;
197,760✔
153
        this.options = options;
197,760✔
154
    }
155

156
    /**
157
     * @param {string} sourceCode
158
     * @returns {IObfuscationResult}
159
     */
160
    public obfuscate(sourceCode: string): IObfuscationResult {
161
        if (AdvertisementUtils.shouldShowAdvertisement()) {
197,760!
NEW
162
            this.logger.advertise(LoggingMessage.JavaScriptObfuscatorProAdFirstPart);
×
NEW
163
            this.logger.advertise(LoggingMessage.JavaScriptObfuscatorProAdSecondPart);
×
164
        }
165

166
        if (typeof sourceCode !== 'string') {
197,760✔
167
            sourceCode = '';
6✔
168
        }
169

170
        const timeStart: number = Date.now();
197,760✔
171
        this.logger.info(
197,760✔
172
            LoggingMessage.Version,
173
            Utils.buildVersionMessage(process.env.VERSION, process.env.BUILD_TIMESTAMP)
174
        );
175
        this.logger.info(LoggingMessage.ObfuscationStarted);
197,760✔
176
        this.logger.info(LoggingMessage.RandomGeneratorSeed, this.randomGenerator.getInputSeed());
197,760✔
177

178
        // preparing code transformations
179
        sourceCode = this.runCodeTransformationStage(sourceCode, CodeTransformationStage.PreparingTransformers);
197,760✔
180

181
        // parse AST tree
182
        const astTree: ESTree.Program = this.parseCode(sourceCode);
197,760✔
183

184
        // obfuscate AST tree
185
        const obfuscatedAstTree: ESTree.Program = this.transformAstTree(astTree);
197,754✔
186

187
        // generate code
188
        const generatorOutput: IGeneratorOutput = this.generateCode(sourceCode, obfuscatedAstTree);
197,754✔
189

190
        // finalizing code transformations
191
        generatorOutput.code = this.runCodeTransformationStage(
197,754✔
192
            generatorOutput.code,
193
            CodeTransformationStage.FinalizingTransformers
194
        );
195

196
        const obfuscationTime: number = (Date.now() - timeStart) / 1000;
197,754✔
197
        this.logger.success(LoggingMessage.ObfuscationCompleted, obfuscationTime);
197,754✔
198

199
        return this.getObfuscationResult(generatorOutput);
197,754✔
200
    }
201

202
    /**
203
     * @param {string} sourceCode
204
     * @returns {Program}
205
     */
206
    private parseCode(sourceCode: string): ESTree.Program {
207
        return ASTParserFacade.parse(sourceCode, JavaScriptObfuscator.parseOptions);
197,760✔
208
    }
209

210
    /**
211
     * @param {Program} astTree
212
     * @returns {Program}
213
     */
214
    private transformAstTree(astTree: ESTree.Program): ESTree.Program {
215
        astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.Initializing);
197,754✔
216

217
        const isEmptyAstTree: boolean =
218
            NodeGuards.isProgramNode(astTree) &&
197,754✔
219
            !astTree.body.length &&
220
            !astTree.leadingComments &&
221
            !astTree.trailingComments;
222

223
        if (isEmptyAstTree) {
197,754✔
224
            this.logger.warn(LoggingMessage.EmptySourceCode);
132✔
225

226
            return astTree;
132✔
227
        }
228

229
        astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.Preparing);
197,622✔
230

231
        if (this.options.deadCodeInjection) {
197,622✔
232
            astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.DeadCodeInjection);
10,359✔
233
        }
234

235
        astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.ControlFlowFlattening);
197,622✔
236

237
        if (this.options.renameProperties) {
197,622✔
238
            astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.RenameProperties);
1,290✔
239
        }
240

241
        astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.Converting);
197,622✔
242
        astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.RenameIdentifiers);
197,622✔
243
        astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.StringArray);
197,622✔
244

245
        if (this.options.simplify) {
197,622✔
246
            astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.Simplifying);
19,494✔
247
        }
248

249
        astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.Finalizing);
197,622✔
250

251
        return astTree;
197,622✔
252
    }
253

254
    /**
255
     * @param {string} sourceCode
256
     * @param {Program} astTree
257
     * @returns {IGeneratorOutput}
258
     */
259
    private generateCode(sourceCode: string, astTree: ESTree.Program): IGeneratorOutput {
260
        const escodegenParams: escodegen.GenerateOptions = {
197,754✔
261
            ...JavaScriptObfuscator.escodegenParams,
262
            format: {
263
                compact: this.options.compact
264
            },
265
            ...(this.options.sourceMap && {
197,988✔
266
                ...(this.options.sourceMapSourcesMode === SourceMapSourcesMode.SourcesContent
267
                    ? {
234✔
268
                          sourceMap: 'sourceMap',
269
                          sourceContent: sourceCode
270
                      }
271
                    : {
272
                          sourceMap: this.options.inputFileName || 'sourceMap'
42!
273
                      })
274
            })
275
        };
276

277
        const generatorOutput: IGeneratorOutput = escodegen.generate(astTree, escodegenParams);
197,754✔
278

279
        generatorOutput.map = generatorOutput.map ? generatorOutput.map.toString() : '';
197,754✔
280

281
        return generatorOutput;
197,754✔
282
    }
283

284
    /**
285
     * @param {IGeneratorOutput} generatorOutput
286
     * @returns {IObfuscationResult}
287
     */
288
    private getObfuscationResult(generatorOutput: IGeneratorOutput): IObfuscationResult {
289
        return this.obfuscationResultFactory(generatorOutput.code, generatorOutput.map);
197,754✔
290
    }
291

292
    /**
293
     * @param {string} code
294
     * @param {CodeTransformationStage} codeTransformationStage
295
     * @returns {string}
296
     */
297
    private runCodeTransformationStage(code: string, codeTransformationStage: CodeTransformationStage): string {
298
        this.logger.info(LoggingMessage.CodeTransformationStage, codeTransformationStage);
395,514✔
299

300
        return this.codeTransformersRunner.transform(
395,514✔
301
            code,
302
            JavaScriptObfuscator.codeTransformersList,
303
            codeTransformationStage
304
        );
305
    }
306

307
    /**
308
     * @param {Program} astTree
309
     * @param {NodeTransformationStage} nodeTransformationStage
310
     * @returns {Program}
311
     */
312
    private runNodeTransformationStage(
313
        astTree: ESTree.Program,
314
        nodeTransformationStage: NodeTransformationStage
315
    ): ESTree.Program {
316
        this.logger.info(LoggingMessage.NodeTransformationStage, nodeTransformationStage);
1,414,629✔
317

318
        return this.nodeTransformersRunner.transform(
1,414,629✔
319
            astTree,
320
            JavaScriptObfuscator.nodeTransformersList,
321
            nodeTransformationStage
322
        );
323
    }
324
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc