diff --git a/crates/oxc_transformer/src/react/jsx/mod.rs b/crates/oxc_transformer/src/react/jsx/mod.rs index c8eaaf6c590e1..d2d1506d60f85 100644 --- a/crates/oxc_transformer/src/react/jsx/mod.rs +++ b/crates/oxc_transformer/src/react/jsx/mod.rs @@ -10,7 +10,11 @@ use oxc_syntax::{ use crate::context::Ctx; -pub use super::options::{ReactJsxRuntime, ReactOptions}; +pub use super::{ + jsx_self::ReactJsxSelf, + jsx_source::ReactJsxSource, + options::{ReactJsxRuntime, ReactOptions}, +}; /// [plugin-transform-react-jsx](https://babeljs.io/docs/babel-plugin-transform-react-jsx) /// @@ -27,6 +31,9 @@ pub struct ReactJsx<'a> { ctx: Ctx<'a>, + jsx_self: ReactJsxSelf<'a>, + jsx_source: ReactJsxSource<'a>, + // States imports: std::vec::Vec>, require_jsx_runtime: bool, @@ -53,6 +60,8 @@ impl<'a> ReactJsx<'a> { Self { options: Rc::clone(options), ctx: Rc::clone(ctx), + jsx_self: ReactJsxSelf::new(ctx), + jsx_source: ReactJsxSource::new(ctx), imports: vec![], require_jsx_runtime: false, jsx_runtime_importer, @@ -374,6 +383,13 @@ impl<'a> ReactJsx<'a> { } } + if self.options.is_jsx_self_plugin_enabled() { + properties.push(self.jsx_self.get_object_property_kind_for_jsx_plugin()); + } + if self.options.is_jsx_source_plugin_enabled() { + properties.push(self.jsx_source.get_object_property_kind_for_jsx_plugin()); + } + self.add_import(e, has_key_after_props_spread, need_jsxs); if !properties.is_empty() || is_automatic { diff --git a/crates/oxc_transformer/src/react/jsx_self/mod.rs b/crates/oxc_transformer/src/react/jsx_self/mod.rs index 1a26f92f9b2e3..d160eea952bd6 100644 --- a/crates/oxc_transformer/src/react/jsx_self/mod.rs +++ b/crates/oxc_transformer/src/react/jsx_self/mod.rs @@ -5,6 +5,8 @@ use oxc_span::SPAN; use crate::context::Ctx; +const SELF: &str = "__self"; + /// [plugin-transform-react-jsx-self](https://babeljs.io/docs/babel-plugin-transform-react-jsx-self) /// /// This plugin is included in `preset-react` and only enabled in development mode. @@ -17,7 +19,6 @@ use crate::context::Ctx; /// TODO: /// *. Omit adding `this` in some conditions /// -#[allow(unused)] pub struct ReactJsxSelf<'a> { ctx: Ctx<'a>, } @@ -30,13 +31,22 @@ impl<'a> ReactJsxSelf<'a> { pub fn transform_jsx_opening_element(&self, elem: &mut JSXOpeningElement<'a>) { self.add_self_this_attribute(elem); } + + pub fn get_object_property_kind_for_jsx_plugin(&self) -> ObjectPropertyKind<'a> { + let kind = PropertyKind::Init; + let ident = IdentifierName::new(SPAN, SELF.into()); + let key = self.ctx.ast.property_key_identifier(ident); + let value = self.ctx.ast.this_expression(SPAN); + let obj = self.ctx.ast.object_property(SPAN, kind, key, value, None, false, false, false); + ObjectPropertyKind::ObjectProperty(obj) + } } impl<'a> ReactJsxSelf<'a> { /// `
` /// ^^^^^^^^^^^^^ fn add_self_this_attribute(&self, elem: &mut JSXOpeningElement<'a>) { - let name = JSXAttributeName::Identifier(JSXIdentifier::new(SPAN, "__self".into())); + let name = JSXAttributeName::Identifier(JSXIdentifier::new(SPAN, SELF.into())); let value = { let jsx_expr = JSXExpression::Expression(self.ctx.ast.this_expression(SPAN)); let container = self.ctx.ast.jsx_expression_container(SPAN, jsx_expr); diff --git a/crates/oxc_transformer/src/react/jsx_source/mod.rs b/crates/oxc_transformer/src/react/jsx_source/mod.rs index 828247dc897a9..03171aa697eb2 100644 --- a/crates/oxc_transformer/src/react/jsx_source/mod.rs +++ b/crates/oxc_transformer/src/react/jsx_source/mod.rs @@ -6,6 +6,8 @@ use oxc_syntax::NumberBase; use crate::context::Ctx; +const SOURCE: &str = "__source"; + /// [plugin-transform-react-jsx-source](https://babeljs.io/docs/babel-plugin-transform-react-jsx-source) /// /// This plugin is included in `preset-react` and only enabled in development mode. @@ -28,12 +30,30 @@ impl<'a> ReactJsxSource<'a> { pub fn transform_jsx_opening_element(&self, elem: &mut JSXOpeningElement<'a>) { self.add_source_attribute(elem); } + + pub fn get_object_property_kind_for_jsx_plugin(&self) -> ObjectPropertyKind<'a> { + let kind = PropertyKind::Init; + let ident = IdentifierName::new(SPAN, SOURCE.into()); + let key = self.ctx.ast.property_key_identifier(ident); + let value = self.get_source_object(); + let obj = self.ctx.ast.object_property(SPAN, kind, key, value, None, false, false, false); + ObjectPropertyKind::ObjectProperty(obj) + } } impl<'a> ReactJsxSource<'a> { /// `` /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fn add_source_attribute(&self, elem: &mut JSXOpeningElement<'a>) { + let key = JSXAttributeName::Identifier(self.ctx.ast.jsx_identifier(SPAN, SOURCE.into())); + let object = self.get_source_object(); + let expr = self.ctx.ast.jsx_expression_container(SPAN, JSXExpression::Expression(object)); + let value = JSXAttributeValue::ExpressionContainer(expr); + let attribute_item = self.ctx.ast.jsx_attribute(SPAN, key, Some(value)); + elem.attributes.push(JSXAttributeItem::Attribute(attribute_item)); + } + + fn get_source_object(&self) -> Expression<'a> { let kind = PropertyKind::Init; let filename = { @@ -64,16 +84,6 @@ impl<'a> ReactJsxSource<'a> { properties.push(ObjectPropertyKind::ObjectProperty(filename)); properties.push(ObjectPropertyKind::ObjectProperty(line_number)); properties.push(ObjectPropertyKind::ObjectProperty(column_number)); - - let attribute_item = self.ctx.ast.jsx_attribute( - SPAN, - JSXAttributeName::Identifier(self.ctx.ast.jsx_identifier(SPAN, "__source".into())), - Some(JSXAttributeValue::ExpressionContainer(self.ctx.ast.jsx_expression_container( - SPAN, - JSXExpression::Expression(self.ctx.ast.object_expression(SPAN, properties, None)), - ))), - ); - - elem.attributes.push(JSXAttributeItem::Attribute(attribute_item)); + self.ctx.ast.object_expression(SPAN, properties, None) } } diff --git a/crates/oxc_transformer/src/react/mod.rs b/crates/oxc_transformer/src/react/mod.rs index 3340e69d39b43..f1050de99f72e 100644 --- a/crates/oxc_transformer/src/react/mod.rs +++ b/crates/oxc_transformer/src/react/mod.rs @@ -99,13 +99,11 @@ impl<'a> React<'a> { } pub fn transform_jsx_opening_element(&self, elem: &mut JSXOpeningElement<'a>) { - if self.development { - if self.options.jsx_self_plugin { - self.jsx_self.transform_jsx_opening_element(elem); - } - if self.options.jsx_source_plugin { - self.jsx_source.transform_jsx_opening_element(elem); - } + if self.options.is_jsx_self_plugin_enabled() { + self.jsx_self.transform_jsx_opening_element(elem); + } + if self.options.is_jsx_source_plugin_enabled() { + self.jsx_source.transform_jsx_opening_element(elem); } } } diff --git a/tasks/transform_conformance/babel.snap.md b/tasks/transform_conformance/babel.snap.md index 924c5932da405..0ed67457e28ca 100644 --- a/tasks/transform_conformance/babel.snap.md +++ b/tasks/transform_conformance/babel.snap.md @@ -1,4 +1,4 @@ -Passed: 131/392 +Passed: 129/392 # All Passed: * babel-plugin-transform-react-jsx-source @@ -125,11 +125,13 @@ Passed: 131/392 * regression/15768/input.ts * variable-declaration/non-null-in-optional-chain/input.ts -# babel-preset-react (4/13) +# babel-preset-react (2/13) * preset-options/development/input.js * preset-options/development-runtime-automatic/input.js * preset-options/development-runtime-automatic-windows/input.js * preset-options/development-windows/input.js +* preset-options/empty-options/input.js +* preset-options/runtime-automatic/input.js * preset-options/runtime-classic/input.js * preset-options/runtime-classic-pragma-no-frag/input.js * regression/11294/input.mjs