diff --git a/nix-js/src/codegen.rs b/nix-js/src/codegen.rs index ddbeaaa..f69712d 100644 --- a/nix-js/src/codegen.rs +++ b/nix-js/src/codegen.rs @@ -11,28 +11,29 @@ pub(crate) trait CodegenContext { fn get_sym(&self, id: SymId) -> &str; } +fn escape_quote_string(s: &str) -> String { + let mut escaped = String::with_capacity(s.len() + 2); + escaped.push('"'); + for c in s.chars() { + match c { + '\\' => escaped.push_str("\\\\"), + '\"' => escaped.push_str("\\\""), + '\n' => escaped.push_str("\\n"), + '\r' => escaped.push_str("\\r"), + '\t' => escaped.push_str("\\t"), + _ => escaped.push(c), + } + } + escaped.push('"'); + escaped +} + impl Compile for Ir { fn compile(&self, ctx: &Ctx) -> String { match self { Ir::Int(int) => format!("{int}n"), // Generate BigInt literal Ir::Float(float) => float.to_string(), - Ir::Str(s) => { - // Escape string for JavaScript - let mut escaped = String::with_capacity(s.val.len() + 2); - escaped.push('"'); - for c in s.val.chars() { - match c { - '\\' => escaped.push_str("\\\\"), - '\"' => escaped.push_str("\\\""), - '\n' => escaped.push_str("\\n"), - '\r' => escaped.push_str("\\r"), - '\t' => escaped.push_str("\\t"), - _ => escaped.push(c), - } - } - escaped.push('"'); - escaped - } + Ir::Str(s) => escape_quote_string(&s.val), Ir::Path(p) => { // Path needs runtime resolution for interpolated paths let path_expr = ctx.get_ir(p.expr).compile(ctx); @@ -259,7 +260,7 @@ impl Compile for AttrSet { for (&sym, &expr) in &self.stcs { let key = ctx.get_sym(sym); let value = ctx.get_ir(expr).compile(ctx); - attrs.push(format!("\"{}\": {}", key, value)); + attrs.push(format!("{}: {}", escape_quote_string(key), value)); } for (key_expr, value_expr) in &self.dyns {