diff --git a/crates/oxc_ast/src/ast_builder.rs b/crates/oxc_ast/src/ast_builder.rs index 1b10a1d50..f014ac01e 100644 --- a/crates/oxc_ast/src/ast_builder.rs +++ b/crates/oxc_ast/src/ast_builder.rs @@ -966,6 +966,14 @@ impl<'a> AstBuilder<'a> { self.alloc(RestElement { span, argument }) } + pub fn property_key_identifier(&self, ident: IdentifierName) -> PropertyKey<'a> { + PropertyKey::Identifier(self.alloc(ident)) + } + + pub fn property_key_expression(&self, expr: Expression<'a>) -> PropertyKey<'a> { + PropertyKey::Expression(expr) + } + /* ---------- Modules ---------- */ pub fn module_declaration(&self, decl: ModuleDeclaration<'a>) -> Statement<'a> { diff --git a/crates/oxc_transformer/src/react_jsx/mod.rs b/crates/oxc_transformer/src/react_jsx/mod.rs index adb799b70..a86aea5c3 100644 --- a/crates/oxc_transformer/src/react_jsx/mod.rs +++ b/crates/oxc_transformer/src/react_jsx/mod.rs @@ -186,15 +186,7 @@ impl<'a> ReactJsx<'a> { let kind = PropertyKind::Init; match attribute { JSXAttributeItem::Attribute(attr) => { - let key = match &attr.name { - JSXAttributeName::Identifier(ident) => PropertyKey::Identifier( - self.ast.alloc(IdentifierName::new(SPAN, ident.name.clone())), - ), - JSXAttributeName::NamespacedName(_ident) => { - /* TODO */ - continue; - } - }; + let key = self.get_attribute_name(&attr.name); let value = match &attr.value { Some(value) => { match value { @@ -250,9 +242,8 @@ impl<'a> ReactJsx<'a> { } if self.options.runtime.is_automatic() && !children.is_empty() { - let key = PropertyKey::Identifier( - self.ast.alloc(IdentifierName::new(SPAN, "children".into())), - ); + let key = + self.ast.property_key_identifier(IdentifierName::new(SPAN, "children".into())); let value = if children.len() == 1 { self.transform_jsx_child(&children[0])? } else { @@ -330,6 +321,26 @@ impl<'a> ReactJsx<'a> { } } + fn get_attribute_name(&self, name: &JSXAttributeName<'a>) -> PropertyKey<'a> { + match name { + JSXAttributeName::Identifier(ident) => { + let name = ident.name.clone(); + if ident.name.contains('-') { + let expr = self.ast.literal_string_expression(StringLiteral::new(SPAN, name)); + self.ast.property_key_expression(expr) + } else { + self.ast.property_key_identifier(IdentifierName::new(SPAN, name)) + } + } + JSXAttributeName::NamespacedName(name) => { + let name = format!("{}:{}", name.namespace.name, name.property.name); + let expr = + self.ast.literal_string_expression(StringLiteral::new(SPAN, name.into())); + self.ast.property_key_expression(expr) + } + } + } + fn transform_element_name(&self, name: &JSXElementName<'a>) -> Option> { match name { JSXElementName::Identifier(ident) => { diff --git a/tasks/transform_conformance/babel.snap.md b/tasks/transform_conformance/babel.snap.md index 5d33b1d54..ed12f7393 100644 --- a/tasks/transform_conformance/babel.snap.md +++ b/tasks/transform_conformance/babel.snap.md @@ -1,4 +1,4 @@ -Passed: 208/1083 +Passed: 214/1083 # All Passed: * babel-plugin-transform-numeric-separator @@ -804,7 +804,7 @@ Passed: 208/1083 * regression/11061/input.mjs * variable-declaration/non-null-in-optional-chain/input.ts -# babel-plugin-transform-react-jsx (59/172) +# babel-plugin-transform-react-jsx (65/172) * autoImport/after-polyfills/input.mjs * autoImport/after-polyfills-2/input.mjs * autoImport/after-polyfills-compiled-to-cjs/input.mjs @@ -857,11 +857,8 @@ Passed: 208/1083 * react/should-escape-xhtml-jsxtext/input.js * react/should-escape-xhtml-jsxtext-babel-7/input.js * react/should-handle-attributed-elements/input.js -* react/should-not-add-quotes-to-identifier-names/input.js -* react/should-not-mangle-expressioncontainer-attribute-values/input.js * react/should-not-strip-nbsp-even-coupled-with-other-whitespace/input.js * react/should-not-strip-tags-with-a-single-child-of-nbsp/input.js -* react/should-quote-jsx-attributes/input.js * react/should-support-xml-namespaces-if-flag/input.js * react/should-warn-when-importSource-is-set/input.js * react/should-warn-when-importSource-pragma-is-set/input.js @@ -892,13 +889,10 @@ Passed: 208/1083 * react-automatic/should-handle-attributed-elements/input.js * react-automatic/should-have-correct-comma-in-nested-children/input.js * react-automatic/should-insert-commas-after-expressions-before-whitespace/input.js -* react-automatic/should-not-add-quotes-to-identifier-names/input.js -* react-automatic/should-not-mangle-expressioncontainer-attribute-values/input.js * react-automatic/should-not-strip-nbsp-even-coupled-with-other-whitespace/input.js * react-automatic/should-not-strip-tags-with-a-single-child-of-nbsp/input.js * react-automatic/should-properly-handle-comments-between-props/input.js * react-automatic/should-properly-handle-keys/input.js -* react-automatic/should-quote-jsx-attributes/input.js * react-automatic/should-support-xml-namespaces-if-flag/input.js * react-automatic/should-throw-when-filter-is-specified/input.js * react-automatic/should-use-jsx-when-key-comes-before-spread/input.js