swc-project/swc · error

not implemented

Error message

not implemented

What it means

`RefRewriter` in swc_ecma_utils replaces identifiers with expressions according to a `QueryRef` mapping (`query_jsx` for JSX positions). When rewriting the object position of a JSX member element (`<Foo.Bar />`), a `query_jsx` result of `JSXElementName::JSXNamespacedName` has no `JSXObject` equivalent, so `exit_jsx_object` panics via `unimplemented!()`. No in-tree query implementation returns namespaced names for that position.

Source

Thrown at crates/swc_ecma_utils/src/lib.rs:2564

            }
        };
    }

    pub fn exit_jsx_element_name(&mut self, n: &mut JSXElementName) {
        if let JSXElementName::Ident(ident) = n {
            if let Some(expr) = self.query.query_jsx(ident) {
                *n = expr;
            }
        }
    }

    pub fn exit_jsx_object(&mut self, n: &mut JSXObject) {
        if let JSXObject::Ident(ident) = n {
            if let Some(expr) = self.query.query_jsx(ident) {
                *n = match expr {
                    JSXElementName::Ident(ident) => ident.into(),
                    JSXElementName::JSXMemberExpr(expr) => Box::new(expr).into(),
                    JSXElementName::JSXNamespacedName(..) => unimplemented!(),
                    #[cfg(swc_ast_unknown)]
                    _ => return,
                }
            }
        }
    }

    pub fn exit_object_pat_prop(&mut self, n: &mut ObjectPatProp) {
        if let ObjectPatProp::Assign(AssignPatProp { key, value, .. }) = n {
            if let Some(expr) = self.query.query_lhs(&key.id) {
                let value = value
                    .take()
                    .map(|default_value| {
                        let left = expr.clone().try_into().unwrap();
                        Box::new(default_value.make_assign_to(op!("="), left))
                    })
                    .unwrap_or(expr);

View on GitHub (pinned to d7d7434666)

Solutions

  1. In your `query_jsx`, return only `Ident` or `JSXMemberExpr` — e.g. encode a namespace as the member expression `ns.tag`
  2. Skip replacement when the identifier may appear as a JSX member object
  3. Report upstream to turn the panic into a graceful skip

Example fix

// Rust QueryRef impl
// before
fn query_jsx(&self, i: &Ident) -> Option<JSXElementName> {
    Some(JSXElementName::JSXNamespacedName(...)) // panics in <Foo.Bar />
}

// after
fn query_jsx(&self, i: &Ident) -> Option<JSXElementName> {
    Some(JSXElementName::Ident(make_replacement_ident(i)))
}
Defensive patterns

Strategy: type-guard

Type guard

// Rust: guard query_jsx results so they are usable in member-object position
fn jsx_name_usable_as_object(n: &JSXElementName) -> bool {
    matches!(n, JSXElementName::Ident(..) | JSXElementName::JSXMemberExpr(..))
}

Prevention

When it happens

Trigger: Provide a custom `QueryRef` implementation whose `query_jsx` returns `JSXNamespacedName` for an identifier that appears as the object of `<Foo.Bar />` in JSX using the RefRewriter.

Common situations: Custom bundler or plugin code using RefRewriter for aliasing/inlining in JSX-heavy codebases; replacing JSX tag aliases with namespaced names.

Related errors


AI-assisted analysis of swc-project/swc@d7d7434666 (2026-08-16). Data as JSON: /api/errors/5c3b6198132f427a. Report an issue: GitHub.