{"record":{"id":"6697c936ed19b24c","repo":"swc-project/swc","slug":"add-effects-for-class-expression","errorCode":null,"errorMessage":"add_effects for class expression","messagePattern":"add_effects for class expression","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_ecma_utils/src/lib.rs","lineNumber":2021,"sourceCode":"                    self.extract_side_effects_to(v, *e.expr);\n\n                    v\n                });\n            }\n\n            Expr::TaggedTpl(TaggedTpl { tag, tpl, .. }) => {\n                self.extract_side_effects_to(to, *tag);\n\n                tpl.exprs\n                    .into_iter()\n                    .for_each(|e| self.extract_side_effects_to(to, *e));\n            }\n            Expr::Tpl(Tpl { exprs, .. }) => {\n                exprs\n                    .into_iter()\n                    .for_each(|e| self.extract_side_effects_to(to, *e));\n            }\n            Expr::Class(ClassExpr { .. }) => unimplemented!(\"add_effects for class expression\"),\n\n            Expr::JSXMember(..)\n            | Expr::JSXNamespacedName(..)\n            | Expr::JSXEmpty(..)\n            | Expr::JSXElement(..)\n            | Expr::JSXFragment(..) => to.push(Box::new(expr)),\n\n            Expr::TsTypeAssertion(TsTypeAssertion { expr, .. })\n            | Expr::TsNonNull(TsNonNullExpr { expr, .. })\n            | Expr::TsAs(TsAsExpr { expr, .. })\n            | Expr::TsConstAssertion(TsConstAssertion { expr, .. })\n            | Expr::TsInstantiation(TsInstantiation { expr, .. })\n            | Expr::TsSatisfies(TsSatisfiesExpr { expr, .. }) => {\n                self.extract_side_effects_to(to, *expr)\n            }\n            Expr::OptChain(..) => to.push(Box::new(expr)),\n\n            Expr::Invalid(..) => unreachable!(),","sourceCodeStart":2003,"sourceCodeEnd":2039,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_ecma_utils/src/lib.rs#L2003-L2039","documentation":"ExprExt::extract_side_effects_to in swc_ecma_utils recursively splits an expression into its side-effecting subexpressions (used by transforms that reorder or eliminate expressions). It handles most expression kinds but class expressions (Expr::Class, i.e. an anonymous `class {}` used as a value) hit `unimplemented!(\"add_effects for class expression\")` because nobody contributed that arm.","triggerScenarios":"A transform or utility that calls extract_side_effects_to on an expression tree containing an anonymous class expression in value position, e.g. `x = (class { ... }, y)` or an inlined IIFE result where a class expression remains.","commonSituations":"Custom passes built on ExprExt that feed arbitrary user code through extract_side_effects_to; optimization/inlining scenarios where a class expression survives to the extraction step.","solutions":["Guard the call site: skip or specially handle `matches!(expr, Expr::Class(_))` before calling extract_side_effects_to","Rewrite the input so the class expression is hoisted into a variable (`const C = class {};`) before the transform runs","Upgrade swc_ecma_utils, or if you own the fork, implement the Expr::Class arm (push the class expr itself or its computed keys/superclass)"],"exampleFix":"// before\nlet mut effects = Vec::new();\nexpr.extract_side_effects_to(&mut effects);\n\n// after\nlet mut effects = Vec::new();\nif matches!(&*expr, Expr::Class(_)) {\n    effects.push(expr); // preserve the whole class expression\n} else {\n    expr.extract_side_effects_to(&mut effects);\n}","handlingStrategy":"type-guard","validationCode":"// Rust: pre-walk the expression and bail out early\nfn contains_class_expr(e: &swc_ecma_ast::Expr) -> bool {\n    if matches!(e, swc_ecma_ast::Expr::Class(_)) { return true; }\n    // also check immediate children relevant to your pass\n    false\n}","typeGuard":"fn is_class_expr(e: &swc_ecma_ast::Expr) -> bool {\n    matches!(e, swc_ecma_ast::Expr::Class(_))\n}","tryCatchPattern":"// Wrap library calls in catch_unwind when feeding third-party code through\n// transform pipelines that use extract_side_effects_to\nlet result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    run_transform(program)\n}));\nif result.is_err() { /* log node span, skip this module, fail loudly */ }","preventionTips":["Hoist class expressions to named consts in input code before running effect-extraction passes","Guard every call to extract_side_effects_to with a matches!(expr, Expr::Class(_)) check","Use catch_unwind at the module boundary of batch compilers so one bad module does not kill the whole run"],"tags":["swc","ast-utils","class-expression","side-effects","rust"],"backgroundTag":"unsupported-syntax-feature","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}