# Build release binary
cargo build --release
# Run all tests
cargo test --lib
# Check for warnings
cargo build --release 2>&1 | grep warning
# Run specific test
cargo test test_name./target/release/jsbeautify input.js -o output.js./target/release/jsbeautify input.js --deobfuscate -o output.js# Extract chunk metadata to JSON
./target/release/jsbeautify app.js --split-chunks --chunk-map chunks.json
# Split embedded chunks (if bundle contains code)
./target/release/jsbeautify app.js --split-chunks --chunk-dir ./chunks/cat input.js | ./target/release/jsbeautify - > output.js# Line counts
wc -l original.js deobfuscated.js
# Property access patterns
grep -o '\.[a-zA-Z_][a-zA-Z0-9_]*' deobfuscated.js | wc -l
# Remaining obfuscation
grep -c 'try {' deobfuscated.jspython3 -m json.tool chunks.json | head -50The --deobfuscate flag enables 15 transformation passes:
- Inline decoded strings
- Unflatten control flow
- Simplify expressions
- Fold constants
- Remove dead code
- Remove dead conditionals
- Inline object dispatchers
- Inline call proxies
- Inline operator proxies
- Inline single-use functions ⬅️ NEW
- Convert dynamic properties ⬅️ NEW (obj["x"] → obj.x)
- Remove empty try-catch ⬅️ NEW
- Simplify ternary chains ⬅️ NEW (true ? a : b → a)
- Consolidate sparse objects
- Normalize unicode
- Replace boolean literals (!0 → true)
- Replace void(0) (→ undefined)
Based on Intelius bundles:
- Small files (<50KB): ~0.01s
- Medium files (500KB-1MB): ~0.1s
- Large files (5-6MB): ~0.09s
- Very large (3-4MB vendors): ~7.7s
src/
├── bin/
│ └── jsbeautify.rs - CLI interface
├── deobfuscate/
│ ├── mod.rs - Pipeline orchestration
│ ├── function_inline.rs - Single-use function inlining
│ ├── dynamic_property.rs - Property access conversion
│ ├── try_catch.rs - Empty try-catch removal
│ ├── ternary.rs - Constant ternary simplification
│ └── [11 other passes]
├── chunk_detector.rs - Webpack metadata extraction
├── chunk_splitter.rs - Chunk file writing
└── beautifier/
├── mod.rs - Main beautification logic
└── webpack.rs - Webpack integration
- Create new file:
src/deobfuscate/your_pass.rs - Implement function:
pub fn your_pass(tokens: Vec<Token>) -> Result<Vec<Token>, BeautifyError> - Add to pipeline in
src/deobfuscate/mod.rs - Add tests at bottom of your file
- Run:
cargo test your_pass
- ❌ Never use:
unwrap(),expect(),panic!() - ✅ Always use:
.checked_add(),.checked_sub(),.checked_mul() - ✅ Handle all errors with
ResultorOption - ✅ Add
debug_assert!()every 3-5 lines - ✅ Use
#[cfg(debug_assertions)]for debug-only code
trace_inline!("inlined function '{}' at position {}", name, pos);
trace_prop!("converted obj[\"x\"] to obj.x at {}", pos);
trace_try!("removed try-catch at {}", pos);
trace_ternary!("simplified ternary at {}", pos);All trace macros compile to nothing in release builds.
# View recent commits
git log --oneline -10
# Check status
git status
# View specific commit
git show <commit-hash>
# Compare files
git diff src/file.rscargo clean && cargo build --release# Run with output
cargo test -- --nocapture
# Run single test
cargo test test_name -- --nocapture- If variable is only used in trace macros, prefix with
_ - Example:
let _pos = ...;then use_posintrace_macro!(..., _pos)
- Session Summary:
SESSION_SUMMARY.md - Main README:
README.md - Test Examples: See bottom of each
src/deobfuscate/*.rsfile