swc-project/swc · error

invalid syntax

Error message

invalid syntax

What it means

The React display_name pass scans object literals (e.g. options passed to forwardRef/memo/createReactClass-like calls) for a `displayName` key. While matching property keys it treats Prop::Assign as impossible: `{a = 1}` assignment shorthand is cover grammar that is only valid inside destructuring patterns, so an object literal expression containing it is invalid syntax, hence unreachable!("invalid syntax").

Source

Thrown at crates/swc_ecma_transforms_react/src/display_name/mod.rs:215

fn is_key_display_name(prop: &PropOrSpread) -> bool {
    match *prop {
        PropOrSpread::Prop(ref prop) => match **prop {
            Prop::Shorthand(ref i) => i.sym == "displayName",
            Prop::Method(MethodProp { ref key, .. })
            | Prop::Getter(GetterProp { ref key, .. })
            | Prop::Setter(SetterProp { ref key, .. })
            | Prop::KeyValue(KeyValueProp { ref key, .. }) => match *key {
                PropName::Ident(ref i) => i.sym == "displayName",
                PropName::Str(ref s) => {
                    matches!(s.value.as_str(), Some(value) if value == "displayName")
                }
                PropName::Num(..) => false,
                PropName::BigInt(..) => false,
                PropName::Computed(..) => false,
                #[cfg(swc_ast_unknown)]
                _ => panic!("unable to access unknown nodes"),
            },
            Prop::Assign(..) => unreachable!("invalid syntax"),
            #[cfg(swc_ast_unknown)]
            _ => panic!("unable to access unknown nodes"),
        },
        _ => false,
        // TODO(kdy1): maybe.. handle spread
    }
}

View on GitHub (pinned to 5176682b65)

Solutions

  1. Normalize the AST before the React transform: convert Prop::Assign to Prop::KeyValue (and bare shorthand to key:value).
  2. Fix the generator/codemod that produced `{a = b}` in expression position — it is invalid JavaScript.
  3. Report to the producer tool, not swc, when the AST provably contains Prop::Assign in an expression.

Example fix

// before: cover-grammar node left in an object expression
// ast: ObjectLit { props: [Prop::Assign { key: displayName, value }) }] }

// after
// ast: ObjectLit { props: [Prop::KeyValue { key: displayName, value }) }] }
// source equivalent: ({ displayName: 'Foo' })
Defensive patterns

Strategy: type-guard

Validate before calling

use swc_ecma_ast::{ObjectLit, Prop, PropOrSpread};
fn no_assign_props(o: &ObjectLit) -> bool {
    o.props.iter().all(|p| !matches!(p, PropOrSpread::Prop(p) if matches!(**p, Prop::Assign(_))))
}

Type guard

fn is_plain_object_expr(o: &ObjectLit) -> bool {
    o.props.iter().all(|p| match p {
        PropOrSpread::Prop(p) => !matches!(**p, Prop::Assign(_)),
        PropOrSpread::Spread(_) => true,
    })
}

Prevention

When it happens

Trigger: Feeding the React display_name transform an object expression containing Prop::Assign nodes — produced by custom transforms that turn object/array patterns into object literals, by lenient parsers, or by hand-built ASTs. Not reproducible from normal parsed source because the parser rejects it.

Common situations: Codemods migrating destructuring patterns into object expressions; ESLint/AST tooling feeding modified ASTs back into swc; tests constructing ObjectLit props manually.

Related errors


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/84baa88ce628a3fd. Report an issue: GitHub.