{"record":{"id":"0036a6a8227d7bfb","repo":"swc-project/swc","slug":"jsxnamespacedname-jsxobject","errorCode":null,"errorMessage":"JSXNamespacedName -> JSXObject","messagePattern":"JSXNamespacedName -> JSXObject","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_ecma_lexer/src/common/parser/jsx.rs","lineNumber":114,"sourceCode":"/// identifier.\nfn parse_jsx_element_name<'a, P: Parser<'a>>(p: &mut P) -> PResult<JSXElementName> {\n    debug_assert!(p.input().syntax().jsx());\n    trace_cur!(p, parse_jsx_element_name);\n    let start = p.input().cur_pos();\n    let mut node = match parse_jsx_namespaced_name(p)? {\n        JSXAttrName::Ident(i) => JSXElementName::Ident(i.into()),\n        JSXAttrName::JSXNamespacedName(i) => JSXElementName::JSXNamespacedName(i),\n        #[cfg(swc_ast_unknown)]\n        _ => unreachable!(),\n    };\n    while p.input_mut().eat(&P::Token::DOT) {\n        let prop = parse_jsx_ident(p).map(IdentName::from)?;\n        let new_node = JSXElementName::JSXMemberExpr(JSXMemberExpr {\n            span: p.span(start),\n            obj: match node {\n                JSXElementName::Ident(i) => JSXObject::Ident(i),\n                JSXElementName::JSXMemberExpr(i) => JSXObject::JSXMemberExpr(Box::new(i)),\n                _ => unimplemented!(\"JSXNamespacedName -> JSXObject\"),\n            },\n            prop,\n        });\n        node = new_node;\n    }\n    Ok(node)\n}\n\n/// JSXEmptyExpression is unique type since it doesn't actually parse\n/// anything, and so it should start at the end of last read token (left\n/// brace) and finish at the beginning of the next one (right brace).\npub fn parse_jsx_empty_expr<'a>(p: &mut impl Parser<'a>) -> JSXEmptyExpr {\n    debug_assert!(p.input().syntax().jsx());\n    let start = p.input().cur_pos();\n    JSXEmptyExpr {\n        span: Span::new_with_checked(start, start),\n    }\n}","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/swc-project/swc/blob/d7d74346665e36e692aa07e13d4ee3ee692ee35c/crates/swc_ecma_lexer/src/common/parser/jsx.rs#L96-L132","documentation":"In the JSX parser, after a tag name is parsed you may continue with `.prop` segments (`<Foo.Bar />`). When the already-parsed node is a `JSXNamespacedName` (`<ns:tag>`) and a dot follows, converting the namespaced name into the `JSXObject` of a member expression is unsupported and the parser panics with `unimplemented!`.","triggerScenarios":"Parse JSX containing a namespaced tag immediately followed by member access, e.g. `<svg:use.x />` — i.e. the shape `<ns:name.prop>`, which is not valid JSX to begin with.","commonSituations":"Malformed JSX produced by template engines or string concatenation; fuzzers; editor auto-complete inserting a dot after a namespaced tag; programmatic JSX construction.","solutions":["Fix the JSX: use either `<ns:tag />` or `<Obj.tag />`, never `<ns:tag.prop />`","Pre-validate generated JSX before handing it to swc","Report upstream if you believe the input is spec-valid"],"exampleFix":"// before\nconst el = <svg:circle.cx />;\n\n// after\nconst el = <circle cx={cx} />;","handlingStrategy":"validation","validationCode":"// Reject namespaced-then-member JSX tags before parsing\nconst malformed = /<[A-Za-z][\\w.-]*:[\\w-]+\\./;\nif (malformed.test(jsxSource)) throw new Error('namespaced tag with member access is not valid JSX');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate template-generated JSX with a parser linter before compilation","Never construct `<ns:tag.prop>` shapes in string-built JSX"],"tags":["jsx","parser","namespaced-name","malformed-input"],"backgroundTag":null,"analyzedSha":"d7d74346665e36e692aa07e13d4ee3ee692ee35c","analyzedAt":"2026-08-16T12:41:13.160Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}