
pass-workflow
by leolovenet
unmangleJS is a human-readability heuristic JavaScript deobfuscator built on Babel + TypeScript, with a multi-pass processing model.
SKILL.md
name: pass-workflow description: "Universal guide for all unmangleJS pass development tasks. Covers creating, modifying, debugging, refactoring, reviewing, and documenting passes. Integrates with existing project documentation - see CLAUDE.md for complete Pass System guide."
Pass Development Workflow
Universal guide for all unmangleJS pass operations.
📚 Essential Prerequisites
Before working on passes, read these:
-
- Complete guide to pass architecture and lifecycle
- Development workflow and best practices
- Five-file sync rule
-
Babel API Gotchas → docs/en/babel-api-gotchas.md
- Critical pitfalls when working with Babel
- Scope and binding issues
- Reference invalidation
-
Utils Overview → docs/en/utils-overview.md
- Available utility functions
- When to use utils vs implementing in pass
🎯 Quick Task Navigator
What do you want to do?
🆕 Create New Pass
Step-by-step workflow:
- Design: What obfuscation pattern does this pass target?
- Implement: See Pass Structure → references/pass-structure.md
- Test: See Testing Guide → references/testing-guide.md
- Document: Follow pattern in
docs/en/passes/constant-folding.md - Register: Add to
src/passes/registry.tsandsrc/passes/index.ts
Quick Template:
# Copy existing pass as template
cp src/passes/constant-folding.ts src/passes/my-pass.ts
# Edit to implement your transformation
Validation:
npm test tests/passes/my-pass.test.ts
npm run lint
npm run build
✏️ Modify Existing Pass
When adding transformations or fixing bugs:
-
Read current implementation:
# View all files for the pass ls -1 src/passes/<name>.ts \ tests/passes/<name>.test.ts \ examples/<name>.js \ docs/en/passes/<name>.md \ docs/zh-CN/passes/<name>.md -
Add tests first (TDD):
// tests/passes/<name>.test.ts it("should handle new pattern", async () => { const input = "<obfuscated>"; const { code } = await unmangle(input, [yourPass]); expect(code).toContain("<deobfuscated>"); }); -
Implement transformation:
- See Babel patterns → CLAUDE.md
- Use utils from
src/utils/(see Utils Overview → docs/en/utils-overview.md) - Mark dirty:
ctx.markAstDirty(),ctx.markScopeDirty()
-
Update all 5 files:
- Implementation
- Tests
- Examples
- English docs
- Chinese docs
Validation:
npm test tests/passes/<name>.test.ts
./bin/unmanglejs.js examples/<name>.js -p
🐛 Debug Pass Issues
Debugging workflow:
-
Isolate the issue:
cat > tmp/debug.js << 'EOF' // Minimal reproduction const x = <problematic code>; EOF ./bin/unmanglejs.js tmp/debug.js -p -d -
Check common issues:
- ❌ Forgot
ctx.markAstDirty()? - ❌ Using
path.nodeafterreplaceWith()? - ❌ Missing
path.skip()after replacement? - ❌ Scope issues? Read Babel API Gotchas → docs/en/babel-api-gotchas.md
- ❌ Forgot
-
Add logging:
ctx.log.at(path).debug("Checking pattern"); ctx.log.at(path).debug("Pattern matched, transforming"); -
Test with single pass:
./bin/unmanglejs.js input.js -p <pass-name> -d
Common debugging scenarios:
- Infinite loop: Missing
path.skip()→ see Babel Gotchas → docs/en/babel-api-gotchas.md - Wrong transformations: Check transformation logic, verify with
tryEvaluateConstant() - Scope errors: Read Scope Management → docs/en/babel-api-gotchas.md
🔄 Refactor Pass Code
When to refactor:
- Code duplication across passes → extract to
src/utils/ - Complex visitor logic → simplify with helper functions
- Performance issues → see CLI Performance → docs/en/cli.md
Extraction workflow:
- Identify reusable logic
- Extract to
src/utils/<name>.ts - Create utils tests:
tests/utils/<name>.test.ts - Update imports in all passes using the logic
- Validate:
npm test tests/utils/ npm test
Example:
// BEFORE: In multiple passes
if (path.node.type === "Identifier" && path.node.name.length > 10) { }
// AFTER: Extract to utils
// src/utils/identifier.ts
export function isLongIdentifier(path: NodePath<t.Identifier>): boolean {
return path.node.name.length > 10;
}
// In pass
import { isLongIdentifier } from "../utils/identifier.js";
if (isLongIdentifier(path)) { }
📝 Update Pass Documentation
Documentation resources:
For structure reference:
- constant-folding.md → docs/en/passes/constant-folding.md
- proxy-object-removal.md → docs/en/passes/proxy-object-removal.md
Five-file sync checklist:
-
src/passes/<name>.ts- Implementation -
tests/passes/<name>.test.ts- Tests -
examples/<name>.js- Examples -
docs/en/passes/<name>.md- English docs -
docs/zh-CN/passes/<name>.md- Chinese docs
Validation:
# Test examples match docs
./bin/unmanglejs.js examples/<name>.js -p
# Verify structure
grep "^##" docs/en/passes/<name>.md
grep "^##" docs/zh-CN/passes/<name>.md
# Should have matching section counts
🧪 Fix Pass Tests
Testing resources:
Common test issues:
-
Tests timeout (>10s):
- Cause: Infinite loop in visitor
- Fix: Add
path.skip()after replacement
-
Transformation not applied:
- Cause: Pattern matching too restrictive
- Fix: Adjust conditions, use
tryEvaluateConstant()
-
Test expects wrong output:
- Cause: Test is brittle or outdated
- Fix: Update test to match actual deobfuscation behavior
⚙️ Adjust Pass Execution Order
Pass order is defined in: src/passes/registry.ts
Current order:
export const PASS_REGISTRY: Record<string, Pass> = {
"string-array-decode": allPasses.stringArrayDecodePass,
"proxy-object-removal": allPasses.proxyObjectRemoval,
"array-unpacking": allPasses.arrayUnpacking,
// ... (see full file)
};
To change order:
- Edit
src/passes/registry.ts - Reorder keys (object key insertion order defines execution order)
- Test with specific passes:
./bin/unmanglejs.js input.js -p pass1,pass2,pass3
Verification:
./bin/unmanglejs.js --list-passes
🗑️ Remove Deprecated Pass
Safe removal workflow:
-
Remove from registry:
# src/passes/registry.ts - remove pass from PASS_REGISTRY # src/passes/index.ts - remove export -
Delete all 5 files:
rm src/passes/<name>.ts rm tests/passes/<name>.test.ts rm examples/<name>.js rm docs/en/passes/<name>.md rm docs/zh-CN/passes/<name>.md -
Validate:
npm test npm run build ./bin/unmanglejs.js --list-passes # Verify removed
🔧 Essential Quick Reference
The Five-File Rule
Each public pass SHOULD maintain 5 files:
src/passes/<pass-name>.ts- Implementationtests/passes/<pass-name>.test.ts- Testsexamples/<pass-name>.js- Examplesdocs/en/passes/<pass-name>.md- English docsdocs/zh-CN/passes/<pass-name>.md- Chinese docs
Note: Internal utility passes or helper transformations may omit documentation files.
Critical Commands
# Test single pass
npm test tests/passes/<name>.test.ts
# Run with custom passes
./bin/unmanglejs.js input.js -p pass1,pass2,pass3
# Check pass order
./bin/unmanglejs.js --list-passes
# Debug output
./bin/unmanglejs.js input.js -p -d
# Test examples
./bin/unmanglejs.js examples/<name>.js -p
Common Gotchas
- ❌ Don't forget
ctx.markAstDirty()after modifications - ❌ Don't use
path.nodeafterreplaceWith() - ❌ Don't call other passes directly
- ❌ Don't share context across passes
- ✅ Do use
tryEvaluateConstant()for literals - ✅ Do use
getIdentifierBinding()for function names - ✅ Do clone nodes with
t.cloneNode()when reusing - ✅ Do use
path.skip()after replacement
Utils Available
Import from src/utils/:
tryEvaluateConstant(path)- Safely evaluate literalsgetIdentifierBinding(path)- Handle hoisting correctlyvalueToExpression(value, node)- Convert values to ASTgenerateUniqueName(scope)- Create non-colliding names
See Utils Overview → docs/en/utils-overview.md for complete reference.
📖 Detailed References
Core Project Documentation
- CLAUDE.md - Pass System - Complete pass development guide
- Babel API Gotchas - Critical Babel pitfalls
- Passes Overview - All passes with examples
- Utils Overview - Available utilities
- CLI Reference - Command-line usage
Skill-Specific References
- Pass Structure → references/pass-structure.md - Implementation patterns
- Testing Guide → references/testing-guide.md - Test strategies
- Checklists → workflows/checklist.md - Universal checklists
Example Pass Documentation
Use these as templates for documenting new passes:
- constant-folding.md → docs/en/passes/constant-folding.md
- proxy-object-removal.md → docs/en/passes/proxy-object-removal.md
- sequence-flattening.md → docs/en/passes/sequence-flattening.md
🚀 Getting Started
New to pass development?
- Read Pass System → CLAUDE.md
- Read Babel API Gotchas → docs/en/babel-api-gotchas.md
- Study example:
src/passes/constant-folding.ts - Follow Create New Pass workflow above
Experienced developer?
Jump to the task navigator above.
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon