diff --git a/crates/oxc_transformer/src/react_jsx/mod.rs b/crates/oxc_transformer/src/react_jsx/mod.rs index 3ad5edb16..86447172f 100644 --- a/crates/oxc_transformer/src/react_jsx/mod.rs +++ b/crates/oxc_transformer/src/react_jsx/mod.rs @@ -8,7 +8,7 @@ use oxc_diagnostics::{ miette::{self, Diagnostic}, thiserror::Error, }; -use oxc_span::{Atom, Span, SPAN}; +use oxc_span::{Atom, GetSpan, Span, SPAN}; use oxc_syntax::{ identifier::{is_irregular_whitespace, is_line_terminator}, xml_entities::XML_ENTITIES, @@ -27,6 +27,11 @@ struct PragmaAndPragmaFragCannotBeSet; #[diagnostic(severity(warning))] struct NamespaceDoesNotSupport(#[label] Span); +#[derive(Debug, Error, Diagnostic)] +#[error("Please provide an explicit key value. Using \"key\" as a shorthand for \"key={{true}}\" is not allowed.")] +#[diagnostic(severity(warning))] +struct ValuelessKey(#[label] Span); + /// Transform React JSX /// /// References: @@ -43,7 +48,6 @@ pub struct ReactJsx<'a> { import_fragment: bool, import_create_element: bool, require_jsx_runtime: bool, - // Will be store jsx runtime importer, like `react/jsx-runtime` jsx_runtime_importer: Atom, } @@ -335,11 +339,14 @@ impl<'a> ReactJsx<'a> { } } } - // In automatic mode, extract the key before spread prop, - // and add it to the third argument later. - if is_automatic && !has_key_after_props_spread { - if let JSXAttributeItem::Attribute(attr) = attribute { - if attr.is_key() { + if let JSXAttributeItem::Attribute(attr) = attribute { + if attr.is_key() { + if attr.value.is_none() { + self.ctx.error(ValuelessKey(attr.name.span())); + } + // In automatic mode, extract the key before spread prop, + // and add it to the third argument later. + if is_automatic && !has_key_after_props_spread { key_prop = attr.value.as_ref(); continue; } diff --git a/tasks/transform_conformance/babel.snap.md b/tasks/transform_conformance/babel.snap.md index 9f20b3eb5..e1a0844ad 100644 --- a/tasks/transform_conformance/babel.snap.md +++ b/tasks/transform_conformance/babel.snap.md @@ -1,4 +1,4 @@ -Passed: 271/1113 +Passed: 273/1113 # All Passed: * babel-plugin-transform-numeric-separator @@ -852,7 +852,7 @@ Passed: 271/1113 * regression/11061/input.mjs * variable-declaration/non-null-in-optional-chain/input.ts -# babel-plugin-transform-react-jsx (136/170) +# babel-plugin-transform-react-jsx (138/170) * autoImport/after-polyfills-compiled-to-cjs/input.mjs * autoImport/complicated-scope-module/input.js * react/adds-appropriate-newlines-when-using-spread-attribute-babel-7/input.js @@ -864,7 +864,6 @@ Passed: 271/1113 * react/optimisation.react.constant-elements/input.js * react/should-add-quotes-es3/input.js * react/should-disallow-spread-children/input.js -* react/should-disallow-valueless-key/input.js * react/should-warn-when-importSource-is-set/input.js * react/should-warn-when-importSource-pragma-is-set/input.js * react/wraps-props-in-react-spread-for-first-spread-attributes-babel-7/input.js @@ -874,7 +873,6 @@ Passed: 271/1113 * react-automatic/optimisation.react.constant-elements/input.js * react-automatic/should-add-quotes-es3/input.js * react-automatic/should-disallow-spread-children/input.js -* react-automatic/should-disallow-valueless-key/input.js * react-automatic/should-handle-attributed-elements/input.js * react-automatic/should-throw-when-filter-is-specified/input.js * regression/issue-12478-automatic/input.js