javascript-obfuscator 4.1.1 → 4.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/.eslintrc.js +245 -289
  2. package/.prettierignore +34 -0
  3. package/.prettierrc.js +50 -0
  4. package/CHANGELOG.md +17 -0
  5. package/CLAUDE.md +1478 -0
  6. package/dist/index.browser.js +1 -1
  7. package/dist/index.browser.js.LICENSE.txt +0 -7
  8. package/dist/index.browser.js.map +1 -1
  9. package/dist/index.cli.js +1 -1
  10. package/dist/index.cli.js.map +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/index_debug.js +14907 -0
  14. package/dist/index_debug.js.LICENSE.txt +23 -0
  15. package/dist/index_debug.js.map +1 -0
  16. package/package.json +59 -53
  17. package/typings/src/cli/JavaScriptObfuscatorCLI.d.ts +0 -1
  18. package/typings/src/constants/EcmaVersion.d.ts +2 -1
  19. package/typings/src/custom-nodes/control-flow-flattening-nodes/CallExpressionFunctionNode.d.ts +2 -1
  20. package/typings/src/enums/node/NodeType.d.ts +1 -0
  21. package/typings/src/enums/node-transformers/preparing-transformers/obfuscating-guards/ObfuscatingGuard.d.ts +1 -0
  22. package/typings/src/interfaces/node-transformers/INodeTransformer.d.ts +0 -1
  23. package/typings/src/interfaces/node-transformers/IVisitor.d.ts +0 -1
  24. package/typings/src/interfaces/utils/IRandomGenerator.d.ts +0 -1
  25. package/typings/src/node/NodeFactory.d.ts +1 -0
  26. package/typings/src/node/NodeGuards.d.ts +2 -0
  27. package/typings/src/node-transformers/AbstractNodeTransformer.d.ts +0 -1
  28. package/typings/src/node-transformers/control-flow-transformers/FunctionControlFlowTransformer.d.ts +0 -1
  29. package/typings/src/node-transformers/control-flow-transformers/StringArrayControlFlowTransformer.d.ts +0 -1
  30. package/typings/src/node-transformers/dead-code-injection-transformers/DeadCodeInjectionTransformer.d.ts +0 -1
  31. package/typings/src/node-transformers/preparing-transformers/obfuscating-guards/ImportMetaObfuscationGuard.d.ts +6 -0
  32. package/typings/src/node-transformers/simplifying-transformers/ExpressionStatementsMergeTransformer.d.ts +0 -1
  33. package/typings/src/node-transformers/simplifying-transformers/VariableDeclarationsMergeTransformer.d.ts +0 -1
  34. package/typings/src/types/node/TNodeWithSingleStatementBody.d.ts +2 -2
  35. package/typings/src/types/node-transformers/TVisitorResult.d.ts +0 -1
  36. package/typings/src/types/utils/TTypeFromEnum.d.ts +1 -1
  37. package/typings/src/utils/RandomGenerator.d.ts +0 -1
  38. package/index.cli.ts +0 -5
  39. package/index.ts +0 -44
package/CLAUDE.md ADDED
@@ -0,0 +1,1478 @@
1
+ # JavaScript Obfuscator - Project Documentation
2
+
3
+ ## Project Overview
4
+
5
+ **JavaScript Obfuscator** is a powerful, enterprise-grade code obfuscation tool for JavaScript and Node.js applications. It transforms readable JavaScript code into a protected, difficult-to-understand format while maintaining full functionality. The project is widely used for protecting intellectual property and preventing reverse engineering.
6
+
7
+ - **Version**: 4.1.1
8
+ - **Author**: Timofey Kachalov (@sanex3339)
9
+ - **License**: BSD-2-Clause
10
+ - **Repository**: https://github.com/javascript-obfuscator/javascript-obfuscator
11
+ - **Homepage**: https://obfuscator.io/
12
+ - **Node Requirement**: >=18.0.0
13
+
14
+ ## Key Features
15
+
16
+ ### Core Obfuscation Techniques
17
+
18
+ 1. **Variable & Function Renaming**: Replaces identifiable names with cryptic hexadecimal or mangled identifiers
19
+ 2. **String Extraction & Encryption**: Moves string literals to an encoded array with base64/rc4 encryption
20
+ 3. **Dead Code Injection**: Inserts non-functional code blocks to confuse static analysis
21
+ 4. **Control Flow Flattening**: Restructures code flow using switch statements to obscure logic
22
+ 5. **Code Transformations**: Multiple AST-level transformations including:
23
+ - Boolean literal obfuscation
24
+ - Number to expression conversion
25
+ - Object key transformation
26
+ - Template literal transformation
27
+ - Property renaming (safe/unsafe modes)
28
+
29
+ ### Advanced Protection Features
30
+
31
+ - **Self-Defending Code**: Code that breaks when beautified or modified
32
+ - **Debug Protection**: Anti-debugging mechanisms to prevent DevTools usage
33
+ - **Domain Lock**: Restricts code execution to specific domains/subdomains
34
+ - **Console Output Disabling**: Removes console.* functionality
35
+ - **Unicode Escape Sequences**: Additional string obfuscation layer
36
+
37
+ ## Architecture Overview
38
+
39
+ ### Technology Stack
40
+
41
+ - **Language**: TypeScript 4.9.5
42
+ - **Parser**: Acorn 8.8.2 (ES3-ES2020 support)
43
+ - **Code Generator**: @javascript-obfuscator/escodegen 2.3.0
44
+ - **AST Traversal**: @javascript-obfuscator/estraverse 5.4.0
45
+ - **DI Framework**: InversifyJS 6.0.1
46
+ - **Testing**: Mocha 10.4.0 + Chai 4.3.7
47
+ - **Build System**: Webpack 5.75.0
48
+
49
+ ### Project Structure
50
+
51
+ ```
52
+ javascript-obfuscator/
53
+ ├── src/ # Source code
54
+ │ ├── JavaScriptObfuscator.ts # Main obfuscator class
55
+ │ ├── JavaScriptObfuscatorFacade.ts # Public API facade
56
+ │ ├── JavaScriptObfuscatorCLIFacade.ts # CLI interface
57
+ │ ├── ASTParserFacade.ts # AST parsing wrapper
58
+ │ │
59
+ │ ├── analyzers/ # Code analysis components
60
+ │ │ ├── calls-graph-analyzer/ # Function call graph analysis
61
+ │ │ ├── scope-analyzer/ # Variable scope analysis
62
+ │ │ ├── string-array-storage-analyzer/ # String array optimization
63
+ │ │ ├── number-numerical-expression-analyzer/
64
+ │ │ └── prevailing-kind-of-variables-analyzer/
65
+ │ │
66
+ │ ├── node-transformers/ # AST transformation pipeline
67
+ │ │ ├── AbstractNodeTransformer.ts
68
+ │ │ ├── NodeTransformersRunner.ts
69
+ │ │ ├── converting-transformers/ # Node type conversions
70
+ │ │ ├── control-flow-transformers/ # Control flow flattening
71
+ │ │ ├── dead-code-injection-transformers/ # Dead code generation
72
+ │ │ ├── finalizing-transformers/ # Post-processing transforms
73
+ │ │ ├── initializing-transformers/ # Pre-processing transforms
74
+ │ │ ├── preparing-transformers/ # Preparation phase
75
+ │ │ ├── rename-identifiers-transformers/ # Variable renaming
76
+ │ │ ├── rename-properties-transformers/ # Property renaming
77
+ │ │ ├── simplifying-transformers/ # Code simplification
78
+ │ │ └── string-array-transformers/ # String array handling
79
+ │ │
80
+ │ ├── code-transformers/ # Code-level (not AST) transformers
81
+ │ │ ├── AbstractCodeTransformer.ts
82
+ │ │ ├── CodeTransformersRunner.ts
83
+ │ │ └── CodeTransformerNamesGroupsBuilder.ts
84
+ │ │
85
+ │ ├── custom-code-helpers/ # Injectable code helpers
86
+ │ │ ├── common/ # Global variable templates
87
+ │ │ ├── console-output/ # Console disabling templates
88
+ │ │ ├── debug-protection/ # Anti-debugging templates
89
+ │ │ ├── domain-lock/ # Domain restriction templates
90
+ │ │ ├── self-defending/ # Self-defense templates
91
+ │ │ └── string-array/ # String array wrapper templates
92
+ │ │
93
+ │ ├── custom-nodes/ # Custom AST node generators
94
+ │ │ ├── control-flow-flattening-nodes/
95
+ │ │ ├── dead-code-injection-nodes/
96
+ │ │ ├── object-expression-keys-transformer-nodes/
97
+ │ │ └── string-array-nodes/
98
+ │ │
99
+ │ ├── container/ # Dependency injection
100
+ │ │ ├── InversifyContainerFacade.ts
101
+ │ │ ├── ServiceIdentifiers.ts
102
+ │ │ └── modules/ # DI module definitions
103
+ │ │
104
+ │ ├── options/ # Configuration system
105
+ │ │ ├── Options.ts
106
+ │ │ ├── OptionsNormalizer.ts
107
+ │ │ ├── validators/ # Option validation
108
+ │ │ ├── normalizer-rules/ # Option normalization
109
+ │ │ └── presets/ # Obfuscation presets
110
+ │ │
111
+ │ ├── storages/ # Data storage components
112
+ │ │ ├── string-array-transformers/
113
+ │ │ ├── control-flow-transformers/
114
+ │ │ ├── custom-code-helpers/
115
+ │ │ └── identifier-names-cache/
116
+ │ │
117
+ │ ├── node/ # AST node utilities
118
+ │ │ ├── NodeGuards.ts # Type guards
119
+ │ │ ├── NodeFactory.ts # Node creation
120
+ │ │ ├── NodeAppender.ts # Node insertion
121
+ │ │ ├── NodeStatementUtils.ts
122
+ │ │ └── NodeUtils.ts
123
+ │ │
124
+ │ ├── generators/ # Name/value generators
125
+ │ │ ├── identifier-names-generators/
126
+ │ │ └── string-array-index-nodes-generators/
127
+ │ │
128
+ │ ├── utils/ # Utility functions
129
+ │ │ ├── RandomGenerator.ts
130
+ │ │ ├── ArrayUtils.ts
131
+ │ │ ├── CryptUtils.ts
132
+ │ │ ├── LevelledTopologicalSorter.ts
133
+ │ │ └── Utils.ts
134
+ │ │
135
+ │ ├── cli/ # CLI utilities
136
+ │ │ ├── sanitizers/ # Input sanitizers
137
+ │ │ └── utils/ # File handling
138
+ │ │
139
+ │ ├── enums/ # Enumerations
140
+ │ ├── interfaces/ # TypeScript interfaces
141
+ │ ├── types/ # Type definitions
142
+ │ ├── constants/ # Constants
143
+ │ ├── decorators/ # Decorators
144
+ │ └── logger/ # Logging system
145
+
146
+ ├── test/ # Test suite
147
+ │ ├── functional-tests/ # Feature tests
148
+ │ ├── unit-tests/ # Unit tests
149
+ │ ├── performance-tests/ # Performance benchmarks
150
+ │ └── index.spec.ts
151
+
152
+ ├── webpack/ # Build configurations
153
+ │ ├── webpack.node.config.js
154
+ │ └── webpack.browser.config.js
155
+
156
+ ├── dist/ # Compiled output
157
+ │ ├── index.js # Node.js bundle
158
+ │ └── index.browser.js # Browser bundle
159
+
160
+ ├── bin/ # CLI executable
161
+ │ └── javascript-obfuscator
162
+
163
+ └── typings/ # TypeScript declarations
164
+ ```
165
+
166
+ ## Core Workflow
167
+
168
+ ### Obfuscation Pipeline
169
+
170
+ The obfuscation process follows a multi-stage pipeline defined in `JavaScriptObfuscator.ts`:
171
+
172
+ ```
173
+ 1. Code Transformation Stage: PreparingTransformers
174
+ └─> Raw code preprocessing (e.g., hashbang handling)
175
+
176
+ 2. AST Parsing
177
+ └─> Parse source code into ESTree-compliant AST using Acorn
178
+
179
+ 3. Node Transformation Stages (sequential):
180
+ ├─> Initializing
181
+ │ └─> Initial AST setup, parentification, metadata
182
+ ├─> Preparing
183
+ │ └─> Scope analysis, obfuscating guards, identifier collection
184
+ ├─> DeadCodeInjection (optional)
185
+ │ └─> Insert dead code blocks
186
+ ├─> ControlFlowFlattening (optional)
187
+ │ └─> Flatten control flow with switch statements
188
+ ├─> RenameProperties (optional)
189
+ │ └─> Rename object properties
190
+ ├─> Converting
191
+ │ └─> Transform nodes (literals, expressions, etc.)
192
+ ├─> RenameIdentifiers
193
+ │ └─> Rename variables and functions
194
+ ├─> StringArray
195
+ │ └─> Extract strings to array, add wrappers
196
+ ├─> Simplifying (optional)
197
+ │ └─> Simplify and merge statements
198
+ └─> Finalizing
199
+ └─> Final cleanup, directive placement
200
+
201
+ 4. Code Generation
202
+ └─> Generate obfuscated code using escodegen
203
+
204
+ 5. Code Transformation Stage: FinalizingTransformers
205
+ └─> Post-processing on generated code
206
+
207
+ 6. Source Map Generation (optional)
208
+ └─> Create source maps for debugging
209
+ ```
210
+
211
+ ### Dependency Injection Architecture
212
+
213
+ The project uses **InversifyJS** for dependency injection, providing:
214
+
215
+ - **Modularity**: Clean separation of concerns
216
+ - **Testability**: Easy mocking and testing
217
+ - **Flexibility**: Runtime configuration of transformers
218
+ - **Scalability**: Easy addition of new transformers
219
+
220
+ All components are registered in container modules located in `src/container/modules/`.
221
+
222
+ ## Key Components Deep Dive
223
+
224
+ ### 1. JavaScriptObfuscator (Main Engine)
225
+
226
+ **Location**: `src/JavaScriptObfuscator.ts`
227
+
228
+ The core orchestrator that:
229
+ - Manages the complete obfuscation pipeline
230
+ - Coordinates code and node transformers
231
+ - Handles AST parsing and code generation
232
+ - Integrates with logger and random generator
233
+
234
+ **Key Methods**:
235
+ - `obfuscate(sourceCode: string): IObfuscationResult` - Main entry point
236
+ - `parseCode()` - AST parsing with Acorn
237
+ - `transformAstTree()` - Applies transformation stages
238
+ - `generateCode()` - Code generation with escodegen
239
+
240
+ ### 2. Node Transformers
241
+
242
+ **Location**: `src/node-transformers/`
243
+
244
+ Each transformer implements `INodeTransformer` interface with:
245
+ - `getVisitor(stage): IVisitor | null` - Returns visitor for specific stage
246
+ - `transformNode(node, parent): Node` - Transforms individual AST node
247
+
248
+ **Key Transformers**:
249
+
250
+ - **StringArrayTransformer**: Extracts string literals to centralized array
251
+ - **BooleanLiteralTransformer**: Converts true/false to `!![]` and `![]`
252
+ - **NumberToNumericalExpressionTransformer**: Converts numbers to expressions
253
+ - **BlockStatementControlFlowTransformer**: Implements control flow flattening
254
+ - **DeadCodeInjectionTransformer**: Injects dead code blocks
255
+ - **RenamePropertiesTransformer**: Renames object properties
256
+ - **ScopeIdentifiersTransformer**: Renames variables based on scope
257
+
258
+ ### 3. Analyzers
259
+
260
+ **Location**: `src/analyzers/`
261
+
262
+ - **CallsGraphAnalyzer**: Builds function call dependency graph
263
+ - **ScopeAnalyzer**: Analyzes variable scopes using eslint-scope
264
+ - **StringArrayStorageAnalyzer**: Optimizes string array storage
265
+ - **PrevailingKindOfVariablesAnalyzer**: Determines var/let/const usage
266
+ - **NumberNumericalExpressionAnalyzer**: Analyzes numeric expressions
267
+
268
+ ### 4. Custom Code Helpers
269
+
270
+ **Location**: `src/custom-code-helpers/`
271
+
272
+ Injectable runtime helpers that provide:
273
+ - **String Array Decoders**: Base64/RC4 decoding functions
274
+ - **Debug Protection**: Anti-debugging wrapper code
275
+ - **Domain Lock**: Domain validation code
276
+ - **Self-Defending**: Code integrity checks
277
+ - **Console Output Disable**: Console method replacements
278
+
279
+ ### 5. Options System
280
+
281
+ **Location**: `src/options/`
282
+
283
+ Sophisticated configuration system with:
284
+ - **Validation**: Using class-validator decorators
285
+ - **Normalization**: Automatic option interdependency handling
286
+ - **Presets**: Default, low, medium, and high obfuscation presets
287
+ - **Type Safety**: Full TypeScript support
288
+
289
+ **Key Option Categories**:
290
+ - Code output (compact, target)
291
+ - String transformations (stringArray*, splitStrings)
292
+ - Control flow (controlFlowFlattening, deadCodeInjection)
293
+ - Naming (identifierNamesGenerator, renameGlobals, renameProperties)
294
+ - Protection (selfDefending, debugProtection, domainLock)
295
+ - Advanced (numbersToExpressions, simplify, transformObjectKeys)
296
+
297
+ ## Important Patterns and Conventions
298
+
299
+ ### 1. Visitor Pattern
300
+
301
+ Transformers use the visitor pattern for AST traversal:
302
+
303
+ ```typescript
304
+ interface IVisitor {
305
+ enter?: (node: Node, parent: Node) => Node | VisitorOption;
306
+ leave?: (node: Node, parent: Node) => Node | VisitorOption;
307
+ }
308
+ ```
309
+
310
+ ### 2. Initializable Pattern
311
+
312
+ Many components implement `IInitializable` for lazy initialization:
313
+
314
+ ```typescript
315
+ interface IInitializable {
316
+ initialize(...args: any[]): void;
317
+ }
318
+ ```
319
+
320
+ Managed via `@Initializable()` decorator.
321
+
322
+ ### 3. Stage-Based Processing
323
+
324
+ Both code and node transformers operate in stages:
325
+
326
+ **Code Transformation Stages**:
327
+ - PreparingTransformers
328
+ - FinalizingTransformers
329
+
330
+ **Node Transformation Stages**:
331
+ - Initializing
332
+ - Preparing
333
+ - DeadCodeInjection
334
+ - ControlFlowFlattening
335
+ - RenameProperties
336
+ - Converting
337
+ - RenameIdentifiers
338
+ - StringArray
339
+ - Simplifying
340
+ - Finalizing
341
+
342
+ ### 4. Factory Pattern
343
+
344
+ Extensive use of factories for object creation:
345
+ - `TObfuscationResultFactory`
346
+ - Custom node factories
347
+ - Identifier name generators
348
+
349
+ ### 5. Storage Pattern
350
+
351
+ Centralized storages for shared data:
352
+ - String array storage
353
+ - Custom code helpers storage
354
+ - Identifier names cache storage
355
+ - Control flow transformers storage
356
+
357
+ ## CLI Usage
358
+
359
+ **Location**: `bin/javascript-obfuscator`, `src/JavaScriptObfuscatorCLIFacade.ts`
360
+
361
+ ### Basic Commands
362
+
363
+ ```bash
364
+ # Obfuscate single file
365
+ javascript-obfuscator input.js --output output.js
366
+
367
+ # Obfuscate directory
368
+ javascript-obfuscator ./src --output ./dist
369
+
370
+ # Use configuration file
371
+ javascript-obfuscator input.js --config config.json
372
+
373
+ # High obfuscation preset
374
+ javascript-obfuscator input.js --options-preset high-obfuscation
375
+ ```
376
+
377
+ ### CLI Features
378
+
379
+ - Automatic identifier prefix for multiple files
380
+ - Glob pattern exclusions
381
+ - Source map support
382
+ - Identifier names cache (cross-file consistency)
383
+ - Progress logging
384
+
385
+ ## API Usage
386
+
387
+ ### Basic Obfuscation
388
+
389
+ ```javascript
390
+ const JavaScriptObfuscator = require('javascript-obfuscator');
391
+
392
+ const obfuscationResult = JavaScriptObfuscator.obfuscate(
393
+ `
394
+ var foo = 'Hello World';
395
+ console.log(foo);
396
+ `,
397
+ {
398
+ compact: true,
399
+ controlFlowFlattening: true
400
+ }
401
+ );
402
+
403
+ console.log(obfuscationResult.getObfuscatedCode());
404
+ console.log(obfuscationResult.getSourceMap());
405
+ console.log(obfuscationResult.getIdentifierNamesCache());
406
+ ```
407
+
408
+ ### Multiple Files
409
+
410
+ ```javascript
411
+ const sourceCodesObject = {
412
+ 'file1.js': 'var foo = 1;',
413
+ 'file2.js': 'var bar = 2;'
414
+ };
415
+
416
+ const obfuscationResults = JavaScriptObfuscator.obfuscateMultiple(
417
+ sourceCodesObject,
418
+ options
419
+ );
420
+ ```
421
+
422
+ ### Identifier Names Cache (Cross-File Consistency)
423
+
424
+ ```javascript
425
+ // First file
426
+ const result1 = JavaScriptObfuscator.obfuscate(code1, {
427
+ identifierNamesCache: {},
428
+ renameGlobals: true
429
+ });
430
+ const cache = result1.getIdentifierNamesCache();
431
+
432
+ // Second file using same cache
433
+ const result2 = JavaScriptObfuscator.obfuscate(code2, {
434
+ identifierNamesCache: cache,
435
+ renameGlobals: true
436
+ });
437
+ ```
438
+
439
+ ## Browser Support
440
+
441
+ The project includes a browser build at `dist/index.browser.js` that can be used in web environments:
442
+
443
+ ```html
444
+ <script src="https://cdn.jsdelivr.net/npm/javascript-obfuscator/dist/index.browser.js"></script>
445
+ <script>
446
+ const obfuscationResult = JavaScriptObfuscator.obfuscate(code, options);
447
+ </script>
448
+ ```
449
+
450
+ **Note**: No eval() in `browser-no-eval` target.
451
+
452
+ ## Build System
453
+
454
+ ### Webpack Configuration
455
+
456
+ - **Node.js build**: `webpack/webpack.node.config.js`
457
+ - Target: CommonJS module
458
+ - External dependencies: node_modules
459
+ - Output: `dist/index.js`
460
+
461
+ - **Browser build**: `webpack/webpack.browser.config.js`
462
+ - Target: UMD module
463
+ - Bundled dependencies
464
+ - Output: `dist/index.browser.js`
465
+
466
+ ### Build Scripts
467
+
468
+ ```bash
469
+ # Production build
470
+ npm run build
471
+
472
+ # Development watch mode
473
+ npm run watch
474
+
475
+ # Build TypeScript typings
476
+ npm run build:typings
477
+
478
+ # Linting
479
+ npm run eslint
480
+ ```
481
+
482
+ ## Testing
483
+
484
+ ### Test Structure
485
+
486
+ **Location**: `test/`
487
+
488
+ - **Functional tests**: Feature-level tests for transformers and options
489
+ - **Unit tests**: Component-level tests
490
+ - **Performance tests**: Memory and speed benchmarks
491
+
492
+ ### Running Tests
493
+
494
+ #### Quick Start
495
+
496
+ ```bash
497
+ # Install dependencies first
498
+ npm install
499
+ # or
500
+ yarn install
501
+
502
+ # Run all tests (includes dev test, coverage, and memory performance)
503
+ npm test
504
+ # or
505
+ yarn test
506
+ ```
507
+
508
+ #### Individual Test Commands
509
+
510
+ ```bash
511
+ # Run full test suite (test:dev + test:mocha-coverage + test:mocha-memory-performance). This is slow.
512
+ npm run test:full
513
+ yarn run test:full
514
+
515
+ # Run Mocha tests only (no coverage)
516
+ npm run test:mocha
517
+ yarn run test:mocha
518
+
519
+ # Run tests with coverage report
520
+ npm run test:mocha-coverage
521
+ yarn run test:mocha-coverage
522
+
523
+ # Generate detailed coverage report (after running test:mocha-coverage)
524
+ npm run test:mocha-coverage:report
525
+ yarn run test:mocha-coverage:report
526
+
527
+ # Run memory performance tests (tests memory constraints)
528
+ npm run test:mocha-memory-performance
529
+ yarn run test:mocha-memory-performance
530
+
531
+ # Run development test (custom dev test file)
532
+ npm run test:dev
533
+ yarn run test:dev
534
+
535
+ # Run compile performance test
536
+ npm run test:devCompilePerformance
537
+ yarn run test:devCompilePerformance
538
+
539
+ # Run runtime performance test
540
+ npm run test:devRuntimePerformance
541
+ yarn run test:devRuntimePerformance
542
+ ```
543
+
544
+ #### Test Details
545
+
546
+ **test:full**
547
+ - Runs the complete test suite
548
+ - Includes: development tests, coverage tests, and memory performance tests
549
+ - This is what runs when you execute `npm test`
550
+
551
+ **test:mocha**
552
+ - Runs all Mocha tests from `test/index.spec.ts`
553
+ - Uses ts-node for TypeScript execution
554
+ - No code coverage reporting
555
+
556
+ **test:mocha-coverage**
557
+ - Runs Mocha tests with NYC (Istanbul) code coverage
558
+ - Allocates up to 4GB memory (`--max-old-space-size=4096`)
559
+ - Generates coverage reports (text-summary by default)
560
+ - Use `test:mocha-coverage:report` to generate detailed lcov report
561
+
562
+ **test:mocha-memory-performance**
563
+ - Tests obfuscator memory usage under constraints
564
+ - Allocates only 280MB memory to test memory efficiency
565
+ - Located at: `test/performance-tests/JavaScriptObfuscatorMemory.spec.ts`
566
+
567
+ **test:dev**
568
+ - Custom development test script
569
+ - Located at: `test/dev/dev.ts`
570
+ - Useful for quick testing during development
571
+
572
+ ### Test Configuration Files
573
+
574
+ - **`.mocharc.json`**: Mocha test runner configuration
575
+ - **`.nycrc.json`**: NYC (Istanbul) coverage tool configuration
576
+ - **TypeScript**: Uses ts-node for direct TS execution without compilation
577
+
578
+ ### Running Specific Test Files
579
+
580
+ You can run individual test files or groups of tests for faster iteration during development.
581
+
582
+ #### Basic Command Format
583
+
584
+ ```bash
585
+ npx mocha --require ts-node/register --require source-map-support/register <path-to-test-file>
586
+ ```
587
+
588
+ #### Common Examples
589
+
590
+ ```bash
591
+ # Run a specific test file by exact path
592
+ npx mocha --require ts-node/register --require source-map-support/register test/functional-tests/options/Options.spec.ts
593
+
594
+ # Run CLI tests
595
+ npx mocha --require ts-node/register --require source-map-support/register test/functional-tests/cli/JavaScriptObfuscatorCLI.spec.ts
596
+
597
+ # Run a specific analyzer test
598
+ npx mocha --require ts-node/register --require source-map-support/register test/functional-tests/analyzers/calls-graph-analyzer/CallsGraphAnalyzer.spec.ts
599
+
600
+ # Run scope analyzer tests
601
+ npx mocha --require ts-node/register --require source-map-support/register test/functional-tests/analyzers/scope-analyzer/ScopeAnalyzer.spec.ts
602
+
603
+ # Run string array tests
604
+ npx mocha --require ts-node/register --require source-map-support/register test/functional-tests/custom-code-helpers/string-array/StringArrayCodeHelper.spec.ts
605
+
606
+ # Run self-defending code tests
607
+ npx mocha --require ts-node/register --require source-map-support/register test/functional-tests/custom-code-helpers/self-defending/SelfDefendingCodeHelper.spec.ts
608
+ ```
609
+
610
+ #### Pattern Matching
611
+
612
+ Use glob patterns to run multiple related test files:
613
+
614
+ ```bash
615
+ # Run all options-related tests
616
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/options/**/*.spec.ts"
617
+
618
+ # Run all analyzer tests
619
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/analyzers/**/*.spec.ts"
620
+
621
+ # Run all string array related tests
622
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/**/*StringArray*.spec.ts"
623
+
624
+ # Run all control flow tests
625
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/**/*ControlFlow*.spec.ts"
626
+
627
+ # Run all node transformer tests
628
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/node-transformers/**/*.spec.ts"
629
+
630
+ # Run all unit tests only
631
+ npx mocha --require ts-node/register --require source-map-support/register "test/unit-tests/**/*.spec.ts"
632
+
633
+ # Run all functional tests only
634
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/**/*.spec.ts"
635
+ ```
636
+
637
+ #### Running Tests by Category
638
+
639
+ The test suite is organized into these main categories:
640
+
641
+ **Functional Tests** (`test/functional-tests/`):
642
+ ```bash
643
+ # Options tests
644
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/options/**/*.spec.ts"
645
+
646
+ # Analyzers tests
647
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/analyzers/**/*.spec.ts"
648
+
649
+ # Node transformers tests
650
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/node-transformers/**/*.spec.ts"
651
+
652
+ # Code transformers tests
653
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/code-transformers/**/*.spec.ts"
654
+
655
+ # Custom code helpers tests
656
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/custom-code-helpers/**/*.spec.ts"
657
+
658
+ # Storage tests
659
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/storages/**/*.spec.ts"
660
+
661
+ # CLI tests
662
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/cli/**/*.spec.ts"
663
+
664
+ # Generator tests
665
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/generators/**/*.spec.ts"
666
+
667
+ # Main obfuscator tests
668
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/javascript-obfuscator/**/*.spec.ts"
669
+
670
+ # Issue regression tests
671
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/issues/**/*.spec.ts"
672
+ ```
673
+
674
+ **Unit Tests** (`test/unit-tests/`):
675
+ ```bash
676
+ # All unit tests
677
+ npx mocha --require ts-node/register --require source-map-support/register "test/unit-tests/**/*.spec.ts"
678
+
679
+ # Options unit tests
680
+ npx mocha --require ts-node/register --require source-map-support/register "test/unit-tests/options/**/*.spec.ts"
681
+
682
+ # Utils unit tests
683
+ npx mocha --require ts-node/register --require source-map-support/register "test/unit-tests/utils/**/*.spec.ts"
684
+
685
+ # Node utilities unit tests
686
+ npx mocha --require ts-node/register --require source-map-support/register "test/unit-tests/node/**/*.spec.ts"
687
+ ```
688
+
689
+ **Performance Tests** (`test/performance-tests/`):
690
+ ```bash
691
+ # Memory performance tests
692
+ npx mocha --require ts-node/register --require source-map-support/register test/performance-tests/JavaScriptObfuscatorMemory.spec.ts
693
+ ```
694
+
695
+ #### Using Mocha Options with Individual Tests
696
+
697
+ ```bash
698
+ # Run with grep to filter by test description
699
+ npx mocha --require ts-node/register --require source-map-support/register test/functional-tests/options/Options.spec.ts --grep "compact"
700
+
701
+ # Run and show slow tests
702
+ npx mocha --require ts-node/register --require source-map-support/register test/functional-tests/options/Options.spec.ts --reporter spec
703
+
704
+ # Run with timeout override (default is 10000ms)
705
+ npx mocha --require ts-node/register --require source-map-support/register test/functional-tests/options/Options.spec.ts --timeout 20000
706
+
707
+ # Run with bail (stop on first failure)
708
+ npx mocha --require ts-node/register --require source-map-support/register "test/functional-tests/**/*.spec.ts" --bail
709
+
710
+ # Run and watch for changes
711
+ npx mocha --require ts-node/register --require source-map-support/register test/functional-tests/options/Options.spec.ts --watch
712
+
713
+ # Run with specific reporter
714
+ npx mocha --require ts-node/register --require source-map-support/register test/functional-tests/options/Options.spec.ts --reporter json
715
+ ```
716
+
717
+ #### Creating Test Aliases (Optional)
718
+
719
+ For convenience, you can add these aliases to your `package.json` scripts:
720
+
721
+ ```json
722
+ {
723
+ "scripts": {
724
+ "test:options": "mocha --require ts-node/register --require source-map-support/register 'test/functional-tests/options/**/*.spec.ts'",
725
+ "test:analyzers": "mocha --require ts-node/register --require source-map-support/register 'test/functional-tests/analyzers/**/*.spec.ts'",
726
+ "test:transformers": "mocha --require ts-node/register --require source-map-support/register 'test/functional-tests/node-transformers/**/*.spec.ts'",
727
+ "test:unit": "mocha --require ts-node/register --require source-map-support/register 'test/unit-tests/**/*.spec.ts'",
728
+ "test:functional": "mocha --require ts-node/register --require source-map-support/register 'test/functional-tests/**/*.spec.ts'"
729
+ }
730
+ }
731
+ ```
732
+
733
+ Then run with:
734
+ ```bash
735
+ npm run test:options
736
+ npm run test:analyzers
737
+ npm run test:transformers
738
+ ```
739
+
740
+ #### Tips for Running Individual Tests
741
+
742
+ 1. **Use quotes around glob patterns** to prevent shell expansion:
743
+ ```bash
744
+ # Good
745
+ npx mocha "test/**/*.spec.ts"
746
+
747
+ # Bad (shell will expand the pattern)
748
+ npx mocha test/**/*.spec.ts
749
+ ```
750
+
751
+ 2. **Use --grep to run specific test cases** within a file:
752
+ ```bash
753
+ npx mocha --require ts-node/register test/functional-tests/options/Options.spec.ts --grep "should enable compact"
754
+ ```
755
+
756
+ 3. **Use --bail to stop on first failure** when debugging:
757
+ ```bash
758
+ npx mocha --require ts-node/register "test/**/*.spec.ts" --bail
759
+ ```
760
+
761
+ 4. **Check the exit code** to verify test success in scripts:
762
+ ```bash
763
+ npx mocha --require ts-node/register test/functional-tests/options/Options.spec.ts && echo "Tests passed!"
764
+ ```
765
+
766
+ 5. **Combine with watch mode** for TDD workflow:
767
+ ```bash
768
+ npx mocha --require ts-node/register test/functional-tests/options/Options.spec.ts --watch --reporter min
769
+ ```
770
+
771
+ ## Linting
772
+
773
+ ### Running ESLint
774
+
775
+ #### Quick Start
776
+
777
+ ```bash
778
+ # Lint all TypeScript files in src/
779
+ npm run eslint
780
+ yarn run eslint
781
+ ```
782
+
783
+ This runs: `eslint src/**/*.ts`
784
+
785
+ #### Linting Individual Files
786
+
787
+ You can lint specific files or directories for faster feedback during development.
788
+
789
+ **Basic Command Format:**
790
+ ```bash
791
+ npx eslint <path-to-file-or-directory>
792
+ ```
793
+
794
+ **Common Examples:**
795
+
796
+ ```bash
797
+ # Lint a specific file
798
+ npx eslint src/JavaScriptObfuscator.ts
799
+
800
+ # Lint the main facade file
801
+ npx eslint src/JavaScriptObfuscatorFacade.ts
802
+
803
+ # Lint a specific transformer
804
+ npx eslint src/node-transformers/converting-transformers/StringArrayTransformer.ts
805
+
806
+ # Lint a specific analyzer
807
+ npx eslint src/analyzers/calls-graph-analyzer/CallsGraphAnalyzer.ts
808
+
809
+ # Lint options file
810
+ npx eslint src/options/Options.ts
811
+
812
+ # Lint a custom code helper
813
+ npx eslint src/custom-code-helpers/string-array/StringArrayCodeHelper.ts
814
+
815
+ # Lint container files
816
+ npx eslint src/container/InversifyContainerFacade.ts
817
+ ```
818
+
819
+ #### Linting Multiple Files or Directories
820
+
821
+ ```bash
822
+ # Lint entire src directory
823
+ npx eslint src/
824
+
825
+ # Lint all files in a specific subdirectory
826
+ npx eslint src/node-transformers/
827
+
828
+ # Lint all analyzers
829
+ npx eslint src/analyzers/
830
+
831
+ # Lint all transformers
832
+ npx eslint src/node-transformers/**/*.ts
833
+
834
+ # Lint all options-related files
835
+ npx eslint src/options/
836
+
837
+ # Lint all custom code helpers
838
+ npx eslint src/custom-code-helpers/
839
+
840
+ # Lint all utils
841
+ npx eslint src/utils/
842
+
843
+ # Lint CLI files
844
+ npx eslint src/cli/
845
+
846
+ # Lint container modules
847
+ npx eslint src/container/
848
+
849
+ # Lint storage files
850
+ npx eslint src/storages/
851
+ ```
852
+
853
+ #### Using Glob Patterns
854
+
855
+ ```bash
856
+ # Lint all TypeScript files in src (same as npm run eslint)
857
+ npx eslint "src/**/*.ts"
858
+
859
+ # Lint all transformer files
860
+ npx eslint "src/**/*Transformer.ts"
861
+
862
+ # Lint all analyzer files
863
+ npx eslint "src/**/*Analyzer.ts"
864
+
865
+ # Lint all storage files
866
+ npx eslint "src/**/*Storage.ts"
867
+
868
+ # Lint all helper files
869
+ npx eslint "src/**/*Helper.ts"
870
+
871
+ # Lint all files containing "String" in the name
872
+ npx eslint "src/**/*String*.ts"
873
+
874
+ # Lint all files in node-transformers subdirectories
875
+ npx eslint "src/node-transformers/**/*.ts"
876
+ ```
877
+
878
+ #### Auto-fixing Issues
879
+
880
+ ESLint can automatically fix many issues:
881
+
882
+ ```bash
883
+ # Auto-fix all files in src/
884
+ npx eslint src/**/*.ts --fix
885
+
886
+ # Auto-fix a specific file
887
+ npx eslint src/JavaScriptObfuscator.ts --fix
888
+
889
+ # Auto-fix specific directory
890
+ npx eslint src/node-transformers/ --fix
891
+
892
+ # Auto-fix with glob pattern
893
+ npx eslint "src/analyzers/**/*.ts" --fix
894
+
895
+ # Auto-fix only safe fixes (no potentially breaking changes)
896
+ npx eslint src/JavaScriptObfuscator.ts --fix --fix-type suggestion,layout
897
+ ```
898
+
899
+ #### Checking Specific Rules
900
+
901
+ ```bash
902
+ # Show only errors (no warnings)
903
+ npx eslint src/JavaScriptObfuscator.ts --quiet
904
+
905
+ # Check specific rule only
906
+ npx eslint src/JavaScriptObfuscator.ts --rule 'no-console: error'
907
+
908
+ # Disable specific rules for a file check
909
+ npx eslint src/JavaScriptObfuscator.ts --rule 'no-console: off'
910
+
911
+ # Output format options
912
+ npx eslint src/JavaScriptObfuscator.ts --format stylish # Default
913
+ npx eslint src/JavaScriptObfuscator.ts --format json # JSON output
914
+ npx eslint src/JavaScriptObfuscator.ts --format compact # Compact output
915
+ npx eslint src/JavaScriptObfuscator.ts --format unix # Unix style
916
+ ```
917
+
918
+ #### Getting Detailed Information
919
+
920
+ ```bash
921
+ # Show more details about errors
922
+ npx eslint src/JavaScriptObfuscator.ts --format stylish
923
+
924
+ # List all files that would be linted (dry-run)
925
+ npx eslint src/ --debug 2>&1 | grep "Processing"
926
+
927
+ # Show timing information for rules
928
+ npx eslint src/JavaScriptObfuscator.ts --debug
929
+
930
+ # Get statistics about linting
931
+ npx eslint src/ --format json | jq '.[] | {file: .filePath, errors: .errorCount, warnings: .warningCount}'
932
+ ```
933
+
934
+ #### Linting by Component
935
+
936
+ Organized by project structure:
937
+
938
+ **Core Files:**
939
+ ```bash
940
+ npx eslint src/JavaScriptObfuscator.ts
941
+ npx eslint src/JavaScriptObfuscatorFacade.ts
942
+ npx eslint src/ASTParserFacade.ts
943
+ ```
944
+
945
+ **Node Transformers:**
946
+ ```bash
947
+ # All node transformers
948
+ npx eslint src/node-transformers/
949
+
950
+ # Converting transformers
951
+ npx eslint src/node-transformers/converting-transformers/
952
+
953
+ # Control flow transformers
954
+ npx eslint src/node-transformers/control-flow-transformers/
955
+
956
+ # String array transformers
957
+ npx eslint src/node-transformers/string-array-transformers/
958
+
959
+ # Rename transformers
960
+ npx eslint src/node-transformers/rename-identifiers-transformers/
961
+ npx eslint src/node-transformers/rename-properties-transformers/
962
+ ```
963
+
964
+ **Analyzers:**
965
+ ```bash
966
+ # All analyzers
967
+ npx eslint src/analyzers/
968
+
969
+ # Specific analyzers
970
+ npx eslint src/analyzers/calls-graph-analyzer/
971
+ npx eslint src/analyzers/scope-analyzer/
972
+ npx eslint src/analyzers/string-array-storage-analyzer/
973
+ ```
974
+
975
+ **Options System:**
976
+ ```bash
977
+ # All options files
978
+ npx eslint src/options/
979
+
980
+ # Core options
981
+ npx eslint src/options/Options.ts
982
+ npx eslint src/options/OptionsNormalizer.ts
983
+
984
+ # Validators
985
+ npx eslint src/options/validators/
986
+
987
+ # Presets
988
+ npx eslint src/options/presets/
989
+ ```
990
+
991
+ **Custom Code Helpers:**
992
+ ```bash
993
+ # All helpers
994
+ npx eslint src/custom-code-helpers/
995
+
996
+ # String array helpers
997
+ npx eslint src/custom-code-helpers/string-array/
998
+
999
+ # Debug protection helpers
1000
+ npx eslint src/custom-code-helpers/debug-protection/
1001
+
1002
+ # Self-defending helpers
1003
+ npx eslint src/custom-code-helpers/self-defending/
1004
+ ```
1005
+
1006
+ **Utilities:**
1007
+ ```bash
1008
+ # All utils
1009
+ npx eslint src/utils/
1010
+
1011
+ # Specific utils
1012
+ npx eslint src/utils/RandomGenerator.ts
1013
+ npx eslint src/utils/ArrayUtils.ts
1014
+ npx eslint src/utils/CryptUtils.ts
1015
+ ```
1016
+
1017
+ #### Integrating with Git
1018
+
1019
+ ```bash
1020
+ # Lint only staged files (useful for pre-commit)
1021
+ git diff --cached --name-only --diff-filter=ACM | grep '\.ts$' | xargs npx eslint
1022
+
1023
+ # Lint files changed in current branch
1024
+ git diff --name-only master | grep '\.ts$' | xargs npx eslint
1025
+
1026
+ # Lint files changed in last commit
1027
+ git diff HEAD~1 --name-only | grep '\.ts$' | xargs npx eslint
1028
+ ```
1029
+
1030
+ #### Creating Lint Aliases (Optional)
1031
+
1032
+ Add these to your `package.json` scripts for convenience:
1033
+
1034
+ ```json
1035
+ {
1036
+ "scripts": {
1037
+ "lint": "eslint src/**/*.ts",
1038
+ "lint:fix": "eslint src/**/*.ts --fix",
1039
+ "lint:transformers": "eslint src/node-transformers/**/*.ts",
1040
+ "lint:analyzers": "eslint src/analyzers/**/*.ts",
1041
+ "lint:options": "eslint src/options/**/*.ts",
1042
+ "lint:utils": "eslint src/utils/**/*.ts",
1043
+ "lint:quiet": "eslint src/**/*.ts --quiet",
1044
+ "lint:staged": "git diff --cached --name-only --diff-filter=ACM | grep '\\.ts$' | xargs eslint"
1045
+ }
1046
+ }
1047
+ ```
1048
+
1049
+ Then run with:
1050
+ ```bash
1051
+ npm run lint:transformers
1052
+ npm run lint:analyzers
1053
+ npm run lint:fix
1054
+ ```
1055
+
1056
+ ### ESLint Configuration
1057
+
1058
+ **Location**: `.eslintrc.js`
1059
+
1060
+ The project uses:
1061
+ - **@typescript-eslint**: TypeScript-specific linting rules
1062
+ - **eslint-plugin-import**: Import/export validation
1063
+ - **eslint-plugin-jsdoc**: JSDoc comment validation
1064
+ - **eslint-plugin-no-null**: Prevents null usage (prefer undefined)
1065
+ - **eslint-plugin-prefer-arrow**: Enforces arrow functions
1066
+ - **eslint-plugin-unicorn**: Additional code quality rules
1067
+
1068
+ **Ignored files**: `.eslintignore`
1069
+
1070
+ #### Viewing Current ESLint Config
1071
+
1072
+ ```bash
1073
+ # Print effective configuration for a file
1074
+ npx eslint --print-config src/JavaScriptObfuscator.ts
1075
+
1076
+ # List all rules being applied
1077
+ npx eslint --print-config src/JavaScriptObfuscator.ts | grep rules -A 1000
1078
+ ```
1079
+
1080
+ ### Code Quality Checks
1081
+
1082
+ ```bash
1083
+ # Run full build (includes webpack, eslint, and tests)
1084
+ npm run build
1085
+ yarn run build
1086
+
1087
+ # The build script runs:
1088
+ # 1. webpack:prod (production build)
1089
+ # 2. eslint (linting)
1090
+ # 3. test (full test suite)
1091
+ ```
1092
+
1093
+ ### Tips for Effective Linting
1094
+
1095
+ 1. **Lint before committing**: Always run linting before creating commits
1096
+ ```bash
1097
+ npx eslint src/ && git commit -m "Your message"
1098
+ ```
1099
+
1100
+ 2. **Use --fix cautiously**: Review changes before committing auto-fixes
1101
+ ```bash
1102
+ npx eslint src/MyFile.ts --fix
1103
+ git diff # Review changes
1104
+ ```
1105
+
1106
+ 3. **Focus on errors first**: Use `--quiet` to see only errors
1107
+ ```bash
1108
+ npx eslint src/ --quiet
1109
+ ```
1110
+
1111
+ 4. **Lint specific files during development**: Don't lint everything when working on one file
1112
+ ```bash
1113
+ npx eslint src/node-transformers/MyNewTransformer.ts
1114
+ ```
1115
+
1116
+ 5. **Check exit code**: Useful in scripts and CI/CD
1117
+ ```bash
1118
+ npx eslint src/ || echo "Linting failed!"
1119
+ ```
1120
+
1121
+ ## Development Workflow
1122
+
1123
+ ### Setting Up Development Environment
1124
+
1125
+ ```bash
1126
+ # 1. Clone the repository
1127
+ git clone https://github.com/javascript-obfuscator/javascript-obfuscator.git
1128
+ cd javascript-obfuscator
1129
+
1130
+ # 2. Install dependencies
1131
+ npm install
1132
+ # or
1133
+ yarn install
1134
+
1135
+ # 3. Install Husky hooks (for pre-commit checks)
1136
+ npm run prepare
1137
+ # or
1138
+ yarn run prepare
1139
+ ```
1140
+
1141
+ ### Development Commands
1142
+
1143
+ ```bash
1144
+ # Start development mode with watch (auto-recompile on changes)
1145
+ npm start
1146
+ # or
1147
+ npm run watch
1148
+ # or
1149
+ yarn run watch
1150
+
1151
+ # Build for production
1152
+ npm run webpack:prod
1153
+ yarn run webpack:prod
1154
+
1155
+ # Build TypeScript type definitions
1156
+ npm run build:typings
1157
+ yarn run build:typings
1158
+
1159
+ # Full build (webpack + eslint + tests)
1160
+ npm run build
1161
+ yarn run build
1162
+ ```
1163
+
1164
+ ### Pre-commit Hooks
1165
+
1166
+ The project uses **Husky** for git hooks:
1167
+
1168
+ - **pre-commit**: Automatically runs `npm run build` before each commit
1169
+ - Ensures code compiles
1170
+ - Ensures linting passes
1171
+ - Ensures all tests pass
1172
+
1173
+ **Configuration**: `.husky/` directory
1174
+
1175
+ ### Development Tips
1176
+
1177
+ 1. **Use watch mode during development**:
1178
+ ```bash
1179
+ npm run watch
1180
+ ```
1181
+ This rebuilds automatically when you save files.
1182
+
1183
+ 2. **Run specific tests during development**:
1184
+ ```bash
1185
+ npm run test:dev
1186
+ ```
1187
+ Faster than full test suite.
1188
+
1189
+ 3. **Check linting before committing**:
1190
+ ```bash
1191
+ npm run eslint
1192
+ ```
1193
+ Fix issues before the pre-commit hook runs.
1194
+
1195
+ 4. **Test memory usage**:
1196
+ ```bash
1197
+ npm run test:mocha-memory-performance
1198
+ ```
1199
+ Ensure your changes don't cause memory issues.
1200
+
1201
+ 5. **Generate coverage reports**:
1202
+ ```bash
1203
+ npm run test:mocha-coverage
1204
+ npm run test:mocha-coverage:report
1205
+ ```
1206
+ Check test coverage in the generated `coverage/` directory.
1207
+
1208
+ ## Performance Considerations
1209
+
1210
+ ### Impact on Code Size
1211
+
1212
+ - **Default**: ~15-30% increase
1213
+ - **Dead Code Injection**: Up to 200% increase
1214
+ - **String Array**: 20-50% increase
1215
+ - **Control Flow Flattening**: 30-80% increase
1216
+
1217
+ ### Runtime Performance
1218
+
1219
+ - **No obfuscation**: Baseline
1220
+ - **Low preset**: ~10-20% slower
1221
+ - **Medium preset**: ~30-50% slower
1222
+ - **High preset**: ~50-80% slower
1223
+
1224
+ ### Optimization Tips
1225
+
1226
+ 1. Use **thresholds** to apply transformations selectively:
1227
+ - `controlFlowFlatteningThreshold`
1228
+ - `deadCodeInjectionThreshold`
1229
+ - `stringArrayThreshold`
1230
+
1231
+ 2. Avoid obfuscating:
1232
+ - Third-party libraries
1233
+ - Polyfills
1234
+ - Large vendor bundles
1235
+
1236
+ 3. Use **seed** option for reproducible builds
1237
+
1238
+ 4. Enable **simplify** for better performance (enabled by default)
1239
+
1240
+ ## Security Considerations
1241
+
1242
+ ### What It Protects
1243
+
1244
+ - Makes reverse engineering harder
1245
+ - Prevents casual code inspection
1246
+ - Protects string literals and algorithms
1247
+ - Adds anti-debugging measures
1248
+ - Can lock code to specific domains
1249
+
1250
+ ### What It Doesn't Protect
1251
+
1252
+ - Determined attackers with time and tools
1253
+ - Network traffic and API endpoints
1254
+ - Runtime behavior analysis
1255
+ - Secrets embedded in code (use environment variables!)
1256
+
1257
+ ### Best Practices
1258
+
1259
+ 1. **Never obfuscate secrets**: Use environment variables or secure vaults
1260
+ 2. **Combine with other protections**: Minification, HTTPS, CSP headers
1261
+ 3. **Test thoroughly**: Obfuscation can introduce subtle bugs
1262
+ 4. **Monitor performance**: High obfuscation impacts runtime speed
1263
+ 5. **Use source maps carefully**: Keep them private for debugging
1264
+
1265
+ ## Conditional Comments
1266
+
1267
+ Control obfuscation for specific code sections:
1268
+
1269
+ ```javascript
1270
+ var foo = 1;
1271
+ // javascript-obfuscator:disable
1272
+ var bar = 2; // This won't be obfuscated
1273
+ // javascript-obfuscator:enable
1274
+ var baz = 3;
1275
+ ```
1276
+
1277
+ ## Integration with Build Tools
1278
+
1279
+ ### Webpack
1280
+
1281
+ Use [webpack-obfuscator](https://github.com/javascript-obfuscator/webpack-obfuscator) plugin
1282
+
1283
+ ### Gulp
1284
+
1285
+ Use [gulp-javascript-obfuscator](https://github.com/javascript-obfuscator/gulp-javascript-obfuscator)
1286
+
1287
+ ### Rollup
1288
+
1289
+ Use [rollup-plugin-javascript-obfuscator](https://github.com/javascript-obfuscator/rollup-plugin-javascript-obfuscator)
1290
+
1291
+ ### Grunt
1292
+
1293
+ Use [grunt-contrib-obfuscator](https://github.com/javascript-obfuscator/grunt-contrib-obfuscator)
1294
+
1295
+ ## Common Issues and Solutions
1296
+
1297
+ ### Issue: Code breaks after obfuscation
1298
+
1299
+ **Solutions**:
1300
+ - Add function/variable names to `reservedNames`
1301
+ - Add strings to `reservedStrings`
1302
+ - Use `renamePropertiesMode: 'safe'` instead of 'unsafe'
1303
+ - Disable `renameProperties` if safe mode doesn't work
1304
+ - Check for dynamic property access like `obj[dynamicKey]`
1305
+
1306
+ ### Issue: Performance is too slow
1307
+
1308
+ **Solutions**:
1309
+ - Use lower obfuscation preset
1310
+ - Reduce threshold values
1311
+ - Disable `controlFlowFlattening` and `deadCodeInjection`
1312
+ - Use `target: 'browser-no-eval'` if applicable
1313
+
1314
+ ### Issue: Code size is too large
1315
+
1316
+ **Solutions**:
1317
+ - Disable `deadCodeInjection`
1318
+ - Reduce `stringArrayWrappersCount`
1319
+ - Use lower `stringArrayThreshold`
1320
+ - Disable `unicodeEscapeSequence`
1321
+
1322
+ ### Issue: Source maps not working
1323
+
1324
+ **Solutions**:
1325
+ - Ensure `sourceMap: true` in options
1326
+ - Set correct `sourceMapMode` ('inline' or 'separate')
1327
+ - Specify `inputFileName` when using NodeJS API
1328
+ - Use `sourceMapSourcesMode: 'sources-content'` for embedded source
1329
+
1330
+ ### Issue: Domain lock not working
1331
+
1332
+ **Solutions**:
1333
+ - Don't use with `target: 'node'`
1334
+ - Test in actual browser environment
1335
+ - Check domain format (`.example.com` for all subdomains)
1336
+ - Ensure `domainLockRedirectUrl` is set
1337
+
1338
+ ## Extension Points
1339
+
1340
+ ### Adding Custom Transformers
1341
+
1342
+ 1. Create transformer class extending `AbstractNodeTransformer`
1343
+ 2. Implement `getVisitor()` and `transformNode()` methods
1344
+ 3. Register in appropriate module (`src/container/modules/node-transformers/`)
1345
+ 4. Add to transformer list in `JavaScriptObfuscator.ts`
1346
+ 5. Add to `NodeTransformer` enum
1347
+
1348
+ ### Adding Custom Options
1349
+
1350
+ 1. Add property to `IOptions` interface
1351
+ 2. Add validation decorator in `Options.ts`
1352
+ 3. Add normalizer rule if needed in `options/normalizer-rules/`
1353
+ 4. Add preset values if applicable
1354
+
1355
+ ### Adding Custom Code Helpers
1356
+
1357
+ 1. Create helper group extending `AbstractCustomCodeHelperGroup`
1358
+ 2. Create template files in `custom-code-helpers/[group]/templates/`
1359
+ 3. Register in `CustomCodeHelpersModule`
1360
+ 4. Add to `CustomCodeHelper` enum
1361
+
1362
+ ## TypeScript Configuration
1363
+
1364
+ ### Main Config
1365
+
1366
+ **Location**: `tsconfig.json`
1367
+
1368
+ - **Target**: ES2018
1369
+ - **Module**: CommonJS
1370
+ - **Strict mode**: Enabled
1371
+ - **Decorators**: Enabled (experimental)
1372
+ - **Emit decorator metadata**: Enabled
1373
+
1374
+ ### Special Configs
1375
+
1376
+ - `tsconfig.browser.json`: Browser-specific settings
1377
+ - `tsconfig.node.json`: Node.js-specific settings
1378
+ - `tsconfig.typings.json`: Type declarations generation
1379
+
1380
+ ## Dependencies Overview
1381
+
1382
+ ### Production Dependencies
1383
+
1384
+ - **@javascript-obfuscator/escodegen**: Modified escodegen for code generation
1385
+ - **@javascript-obfuscator/estraverse**: Modified estraverse for AST traversal
1386
+ - **acorn**: JavaScript parser (ES3-ES2020)
1387
+ - **inversify**: Dependency injection container
1388
+ - **eslint-scope**: Scope analysis (from ESLint)
1389
+ - **class-validator**: Options validation
1390
+ - **chance**: Random data generation
1391
+ - **commander**: CLI argument parsing
1392
+ - **chalk**: Terminal colors
1393
+ - **md5**: Hashing for identifiers
1394
+
1395
+ ### Development Dependencies
1396
+
1397
+ - **TypeScript**: Type system and compiler
1398
+ - **Webpack**: Module bundler
1399
+ - **Mocha + Chai**: Testing framework
1400
+ - **NYC**: Code coverage
1401
+ - **ESLint**: Code linting
1402
+ - **Sinon**: Test mocking
1403
+
1404
+ ## Contributing
1405
+
1406
+ **Location**: `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`
1407
+
1408
+ 1. Fork the repository
1409
+ 2. Create feature branch
1410
+ 3. Write tests for new features
1411
+ 4. Ensure all tests pass
1412
+ 5. Follow existing code style (ESLint)
1413
+ 6. Submit pull request
1414
+
1415
+ ## Versioning and Releases
1416
+
1417
+ - Follows semantic versioning (SemVer)
1418
+ - Changelog maintained in `CHANGELOG.md`
1419
+ - Precommit hooks run build and tests (Husky)
1420
+ - Automated CI/CD via GitHub Actions
1421
+
1422
+ ## Support and Community
1423
+
1424
+ - **GitHub Issues**: Bug reports and feature requests
1425
+ - **GitHub Discussions**: Questions and general discussion
1426
+ - **OpenCollective**: Financial support and sponsorship
1427
+ - **GitHub Sponsors**: Direct sponsorship
1428
+
1429
+ ## License
1430
+
1431
+ **BSD-2-Clause License**
1432
+
1433
+ Copyright (C) 2016-2024 Timofey Kachalov
1434
+
1435
+ See `LICENSE.BSD` for full license text.
1436
+
1437
+ ## Project Statistics
1438
+
1439
+ - **First Release**: 2016
1440
+ - **Language**: TypeScript (~90% of codebase)
1441
+ - **Test Coverage**: Extensive functional and unit test suite
1442
+ - **Supported JavaScript Versions**: ES3, ES5, ES2015-ES2019, partial ES2020
1443
+ - **Downloads**: Widely used in production applications
1444
+ - **Maintenance**: Actively maintained
1445
+
1446
+ ## Resources
1447
+
1448
+ - **Main Repository**: https://github.com/javascript-obfuscator/javascript-obfuscator
1449
+ - **Online Tool**: https://obfuscator.io
1450
+ - **NPM Package**: https://www.npmjs.com/package/javascript-obfuscator
1451
+ - **Documentation**: In README.md and inline code comments
1452
+
1453
+ ---
1454
+
1455
+ ## Quick Reference: File Locations
1456
+
1457
+ | Component | Primary Location |
1458
+ |-----------|------------------|
1459
+ | Main Obfuscator | `src/JavaScriptObfuscator.ts` |
1460
+ | Public API | `src/JavaScriptObfuscatorFacade.ts` |
1461
+ | CLI | `bin/javascript-obfuscator`, `src/JavaScriptObfuscatorCLIFacade.ts` |
1462
+ | Options | `src/options/Options.ts` |
1463
+ | Transformers | `src/node-transformers/` |
1464
+ | Analyzers | `src/analyzers/` |
1465
+ | DI Container | `src/container/InversifyContainerFacade.ts` |
1466
+ | Tests | `test/` |
1467
+ | Build Config | `webpack/` |
1468
+ | Distribution | `dist/` |
1469
+
1470
+ ## Quick Reference: Key Enums
1471
+
1472
+ - **CodeTransformationStage**: PreparingTransformers, FinalizingTransformers
1473
+ - **NodeTransformationStage**: Initializing, Preparing, DeadCodeInjection, ControlFlowFlattening, RenameProperties, Converting, RenameIdentifiers, StringArray, Simplifying, Finalizing
1474
+ - **OptionsPreset**: default, low-obfuscation, medium-obfuscation, high-obfuscation
1475
+ - **StringArrayEncoding**: none, base64, rc4
1476
+ - **IdentifierNamesGenerator**: hexadecimal, mangled, mangled-shuffled, dictionary
1477
+ - **RenamePropertiesMode**: safe, unsafe
1478
+ - **Target**: browser, browser-no-eval, node