Skip to main content

js_deobfuscator/ast/
codegen.rs

1//! AST-to-text conversion. Thin wrapper around OXC Codegen.
2//!
3//! Used for eval caching keys and debug output.
4
5use oxc::ast::ast::{Expression, Function, Statement};
6use oxc::codegen::{Codegen, Context, Gen, GenExpr};
7use oxc::syntax::precedence::Precedence;
8
9/// Generate JavaScript source from a statement.
10pub fn stmt_to_code(stmt: &Statement) -> String {
11    let mut cg = Codegen::new();
12    stmt.print(&mut cg, Context::empty());
13    cg.into_source_text()
14}
15
16/// Generate JavaScript source from an expression.
17pub fn expr_to_code(expr: &Expression) -> String {
18    let mut cg = Codegen::new();
19    expr.print_expr(&mut cg, Precedence::Lowest, Context::empty());
20    cg.into_source_text()
21}
22
23/// Generate JavaScript source from a function.
24pub fn function_to_code(func: &Function) -> String {
25    let mut cg = Codegen::new();
26    func.print(&mut cg, Context::empty());
27    cg.into_source_text()
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33    use oxc::allocator::Allocator;
34    use oxc::parser::Parser;
35    use oxc::span::SourceType;
36
37    #[test]
38    fn test_expr_to_code() {
39        let a = Allocator::default();
40        let expr = Parser::new(&a, "1 + 2", SourceType::mjs())
41            .parse_expression()
42            .unwrap();
43        let code = expr_to_code(&expr);
44        assert_eq!(code, "1 + 2");
45    }
46
47    #[test]
48    fn test_stmt_to_code() {
49        let a = Allocator::default();
50        let program = Parser::new(&a, "var x = 42;", SourceType::mjs()).parse().program;
51        let stmt = &program.body[0];
52        let code = stmt_to_code(stmt);
53        assert!(code.contains("var x = 42"), "got: {code}");
54    }
55}