swc-project/swc · error
failed to swcify arguments
Error message
failed to swcify arguments
What it means
`swc_estree_compat` converts Babel (ESTree) ASTs into swc ASTs via the `Swcify` trait. For `CallExpression`, each Babel `Arg` maps to `Option<ExprOrSpread>`; the impl (crates/swc_estree_compat/src/swcify/expr.rs:265) returns `None` for `Arg::Placeholder` and wraps every arg with `expect("failed to swcify arguments")`. So the panic fires when a call expression's argument list contains a Babel Placeholder node, which has no swc equivalent.
Source
Thrown at crates/swc_estree_compat/src/swcify/expr.rs:257
Expression::Import(s) => Callee::Import(s.swcify(ctx)),
_ => Callee::Expr(e.swcify(ctx)),
},
}
}
}
impl Swcify for CallExpression {
type Output = CallExpr;
fn swcify(self, ctx: &Context) -> Self::Output {
CallExpr {
span: ctx.span(&self.base),
callee: self.callee.swcify(ctx),
args: self
.arguments
.swcify(ctx)
.into_iter()
.map(|v| v.expect("failed to swcify arguments"))
.collect(),
type_args: self.type_parameters.swcify(ctx).map(Box::new),
..Default::default()
}
}
}
impl Swcify for Arg {
type Output = Option<ExprOrSpread>;
fn swcify(self, ctx: &Context) -> Self::Output {
Some(match self {
Arg::Spread(s) => ExprOrSpread {
spread: Some(ctx.span(&s.base)),
expr: s.argument.swcify(ctx),
},
Arg::JSXName(e) => ExprOrSpread {
spread: None,View on GitHub (pinned to 5176682b65)
Solutions
- Do not enable the Babel parser's placeholder option (or strip `%%...%%` placeholders) before converting the AST.
- Pre-process the Babel AST: replace Placeholder args with real expressions or remove them, then call swcify.
- If you truly need templated call sites, keep the tree on the Babel side; swc's AST has no placeholder node for arguments.
Example fix
// before let parser = Parser::new(...).with_placeholder_plugin(); // enables %%x%% args let swc_ast = babel_call_expr.swcify(&ctx); // Arg::Placeholder -> panic // after // parse without the placeholder plugin, or replace placeholder args first let swc_ast = babel_call_expr.swcify(&ctx);
Defensive patterns
Strategy: type-guard
Type guard
// Reject Babel CallExpressions containing Placeholder args before swcify.
fn call_args_convertible(call: &swc_estree_compat::babel_ast::CallExpression) -> bool {
call.arguments.iter().all(|arg| {
!matches!(
arg,
swc_estree_compat::babel_ast::Arg::Placeholder(_)
)
})
} Prevention
- Do not enable Babel's placeholder syntax when producing ASTs destined for swcify.
- Sanitize third-party Babel JSON: scan arguments arrays for type Placeholder and reject or transform them first.
- Add a guard pass over the tree before conversion so failures are actionable errors, not panics.
When it happens
Trigger: Calling `ast.swcify(&ctx)` on a Babel AST parsed with the `placeholders` feature (syntax like `foo(%%x%%)`), so call arguments carry `Arg::Placeholder` nodes. Any other argument kind (Expr, Spread, JSXName) converts fine.
Common situations: Consuming Babel fixture ASTs or parser output that enables placeholder syntax (used by Babel's own tests for template holes); deserializing Babel JSON containing `"Placeholder"` argument nodes and converting it to swc.
Related errors
- Babel doesn't support this right now.
- module string names unimplemented
- swcify: {:?}
- swcify: {:?}
- flow types
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/9c533b0ed5d6549e.
Report an issue: GitHub.