diff --git a/crates/oxc_ast/src/ast/jsx.rs b/crates/oxc_ast/src/ast/jsx.rs
index 3d6711112..d41e78c23 100644
--- a/crates/oxc_ast/src/ast/jsx.rs
+++ b/crates/oxc_ast/src/ast/jsx.rs
@@ -227,6 +227,12 @@ pub struct JSXIdentifier<'a> {
pub name: Atom<'a>,
}
+impl<'a> JSXIdentifier<'a> {
+ pub fn new(span: Span, name: Atom<'a>) -> Self {
+ Self { span, name }
+ }
+}
+
// 1.4 JSX Children
/// JSX Child
diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs
index 2029c6ec4..827f0afd1 100644
--- a/crates/oxc_transformer/src/lib.rs
+++ b/crates/oxc_transformer/src/lib.rs
@@ -122,4 +122,9 @@ impl<'a> VisitMut<'a> for Transformer<'a> {
self.x1_react.transform_export_default_declaration(decl);
walk_mut::walk_export_default_declaration_mut(self, decl);
}
+
+ fn visit_jsx_opening_element(&mut self, elem: &mut JSXOpeningElement<'a>) {
+ self.x1_react.transform_jsx_opening_element(elem);
+ walk_mut::walk_jsx_opening_element_mut(self, elem);
+ }
}
diff --git a/crates/oxc_transformer/src/react/jsx_self/mod.rs b/crates/oxc_transformer/src/react/jsx_self/mod.rs
index d89121625..19b9d7a1d 100644
--- a/crates/oxc_transformer/src/react/jsx_self/mod.rs
+++ b/crates/oxc_transformer/src/react/jsx_self/mod.rs
@@ -1,5 +1,8 @@
use std::rc::Rc;
+use oxc_ast::ast::*;
+use oxc_span::SPAN;
+
use crate::context::Ctx;
/// [plugin-transform-react-jsx-self](https://babeljs.io/docs/babel-plugin-transform-react-jsx-self)
@@ -10,13 +13,46 @@ use crate::context::Ctx;
///
/// In: ``
/// Out: ``
+///
+/// TODO:
+/// *. Omit adding `this` in some conditions
+///
#[allow(unused)]
pub struct ReactJsxSelf<'a> {
+ development: bool,
+
ctx: Ctx<'a>,
}
impl<'a> ReactJsxSelf<'a> {
- pub fn new(ctx: &Ctx<'a>) -> Self {
- Self { ctx: Rc::clone(ctx) }
+ pub fn new(development: bool, ctx: &Ctx<'a>) -> Self {
+ Self { development, ctx: Rc::clone(ctx) }
+ }
+
+ pub fn transform_jsx_opening_element(&self, elem: &mut JSXOpeningElement<'a>) {
+ if self.development {
+ self.add_self_this_attribute(elem);
+ }
+ }
+}
+
+impl<'a> ReactJsxSelf<'a> {
+ /// ``
+ /// ^^^^^^^^^^^^^
+ fn add_self_this_attribute(&self, elem: &mut JSXOpeningElement<'a>) {
+ let name = {
+ let name = self.ctx.ast.new_atom("__self");
+ JSXAttributeName::Identifier(JSXIdentifier::new(SPAN, name))
+ };
+ let value = {
+ let jsx_expr = JSXExpression::Expression(self.ctx.ast.this_expression(SPAN));
+ let container = self.ctx.ast.jsx_expression_container(SPAN, jsx_expr);
+ JSXAttributeValue::ExpressionContainer(container)
+ };
+ let attribute = {
+ let attribute = self.ctx.ast.jsx_attribute(SPAN, name, Some(value));
+ JSXAttributeItem::Attribute(attribute)
+ };
+ elem.attributes.push(attribute);
}
}
diff --git a/crates/oxc_transformer/src/react/mod.rs b/crates/oxc_transformer/src/react/mod.rs
index b176ba915..40a5a380e 100644
--- a/crates/oxc_transformer/src/react/mod.rs
+++ b/crates/oxc_transformer/src/react/mod.rs
@@ -35,10 +35,11 @@ pub struct React<'a> {
// Constructors
impl<'a> React<'a> {
pub fn new(options: ReactOptions, ctx: &Ctx<'a>) -> Self {
+ let development = options.development;
Self {
ctx: Rc::clone(ctx),
jsx: ReactJsx::new(options, ctx),
- jsx_self: ReactJsxSelf::new(ctx),
+ jsx_self: ReactJsxSelf::new(development, ctx),
jsx_source: ReactJsxSource::new(ctx),
display_name: ReactDisplayName::new(ctx),
}
@@ -76,4 +77,8 @@ impl<'a> React<'a> {
) {
self.display_name.transform_export_default_declaration(decl);
}
+
+ pub fn transform_jsx_opening_element(&mut self, elem: &mut JSXOpeningElement<'a>) {
+ self.jsx_self.transform_jsx_opening_element(elem);
+ }
}
diff --git a/tasks/transform_conformance/babel.snap.md b/tasks/transform_conformance/babel.snap.md
index 4a2f73753..8e51e47b9 100644
--- a/tasks/transform_conformance/babel.snap.md
+++ b/tasks/transform_conformance/babel.snap.md
@@ -1,4 +1,4 @@
-Passed: 75/174
+Passed: 76/177
# All Passed:
@@ -107,3 +107,7 @@ Passed: 75/174
# babel-plugin-transform-react-display-name (15/16)
* display-name/nested/input.js
+# babel-plugin-transform-react-jsx-self (1/3)
+* react-source/arrow-function/input.js
+* react-source/disable-with-super/input.js
+
diff --git a/tasks/transform_conformance/src/lib.rs b/tasks/transform_conformance/src/lib.rs
index 8df21dfec..4a1f8c9a7 100644
--- a/tasks/transform_conformance/src/lib.rs
+++ b/tasks/transform_conformance/src/lib.rs
@@ -94,6 +94,7 @@ const CASES: &[&str] = &[
// React
// "babel-plugin-transform-react-jsx",
"babel-plugin-transform-react-display-name",
+ "babel-plugin-transform-react-jsx-self",
// // Proposal
// "babel-plugin-proposal-decorators",
];