From a22ced78f14a87a8559572c0c9e46a1817fca3e2 Mon Sep 17 00:00:00 2001 From: Dunqing Date: Sat, 11 Nov 2023 13:31:45 +0800 Subject: [PATCH] feat(transformer/react-jsx): implement `throwIfNamespace` option (#1220) --- crates/oxc_transformer/src/react_jsx/mod.rs | 18 +++++++++++------- .../oxc_transformer/src/react_jsx/options.rs | 9 +++++++-- tasks/transform_conformance/babel.snap.md | 8 ++------ 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/crates/oxc_transformer/src/react_jsx/mod.rs b/crates/oxc_transformer/src/react_jsx/mod.rs index 52c89af79..3ad5edb16 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}; +use oxc_span::{Atom, Span, SPAN}; use oxc_syntax::{ identifier::{is_irregular_whitespace, is_line_terminator}, xml_entities::XML_ENTITIES, @@ -22,6 +22,11 @@ use crate::context::TransformerCtx; #[diagnostic(severity(warning), help("Remove `pragma` and `pragmaFrag` options."))] struct PragmaAndPragmaFragCannotBeSet; +#[derive(Debug, Error, Diagnostic)] +#[error("Namespace tags are not supported by default. React's JSX doesn't support namespace tags. You can set `throwIfNamespace: false` to bypass this warning.")] +#[diagnostic(severity(warning))] +struct NamespaceDoesNotSupport(#[label] Span); + /// Transform React JSX /// /// References: @@ -519,7 +524,7 @@ impl<'a> ReactJsx<'a> { } } - fn transform_element_name(&self, name: &JSXElementName<'a>) -> Expression<'a> { + fn transform_element_name(&mut self, name: &JSXElementName<'a>) -> Expression<'a> { match name { JSXElementName::Identifier(ident) => { let name = ident.name.clone(); @@ -533,11 +538,10 @@ impl<'a> ReactJsx<'a> { self.transform_jsx_member_expression(member_expr) } JSXElementName::NamespacedName(name) => { - // TODO - // If the flag "throwIfNamespace" is false - // print XMLNamespace like string literal - // if self.options.throw_if_namespace.is_some_and(|v| !v) { - // } + if self.options.throw_if_namespace { + self.ctx.error(NamespaceDoesNotSupport(name.span)); + } + let string_literal = StringLiteral::new(SPAN, Atom::from(name.to_string())); self.ast.literal_string_expression(string_literal) } diff --git a/crates/oxc_transformer/src/react_jsx/options.rs b/crates/oxc_transformer/src/react_jsx/options.rs index dd89d4266..5bc38fcde 100644 --- a/crates/oxc_transformer/src/react_jsx/options.rs +++ b/crates/oxc_transformer/src/react_jsx/options.rs @@ -10,7 +10,8 @@ pub struct ReactJsxOptions { pub runtime: ReactJsxRuntime, /// Toggles whether or not to throw an error if an XML namespaced tag name is used. e.g. `` /// Though the JSX spec allows this, it is disabled by default since React's JSX does not currently have support for it. - pub throw_if_namespace: Option, + #[serde(default = "default_throw_if_namespace")] + pub throw_if_namespace: bool, /// Replaces the import source when importing functions. default to `react` #[serde(default = "default_import_source")] pub import_source: Cow<'static, str>, @@ -26,6 +27,10 @@ pub struct ReactJsxOptions { pub pragma_frag: Cow<'static, str>, } +fn default_throw_if_namespace() -> bool { + true +} + fn default_import_source() -> Cow<'static, str> { Cow::Borrowed("react") } @@ -42,7 +47,7 @@ impl Default for ReactJsxOptions { fn default() -> Self { Self { runtime: ReactJsxRuntime::Classic, - throw_if_namespace: None, + throw_if_namespace: default_throw_if_namespace(), import_source: default_import_source(), pragma: default_pragma(), pragma_frag: default_pragma_frag(), diff --git a/tasks/transform_conformance/babel.snap.md b/tasks/transform_conformance/babel.snap.md index 16cf7dfd9..9f20b3eb5 100644 --- a/tasks/transform_conformance/babel.snap.md +++ b/tasks/transform_conformance/babel.snap.md @@ -1,4 +1,4 @@ -Passed: 267/1113 +Passed: 271/1113 # All Passed: * babel-plugin-transform-numeric-separator @@ -852,7 +852,7 @@ Passed: 267/1113 * regression/11061/input.mjs * variable-declaration/non-null-in-optional-chain/input.ts -# babel-plugin-transform-react-jsx (132/170) +# babel-plugin-transform-react-jsx (136/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 @@ -865,8 +865,6 @@ Passed: 267/1113 * react/should-add-quotes-es3/input.js * react/should-disallow-spread-children/input.js * react/should-disallow-valueless-key/input.js -* react/should-disallow-xml-namespacing/input.js -* react/should-throw-error-namespaces-if-not-flag/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 @@ -877,9 +875,7 @@ Passed: 267/1113 * 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-disallow-xml-namespacing/input.js * react-automatic/should-handle-attributed-elements/input.js -* react-automatic/should-throw-error-namespaces-if-not-flag/input.js * react-automatic/should-throw-when-filter-is-specified/input.js * regression/issue-12478-automatic/input.js * regression/issue-12478-classic/input.js