Skip to content

Commit

Permalink
feat(transformer): implement react-jsx-self (#2946)
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen authored Apr 12, 2024
1 parent ba2121f commit f903a22
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 4 deletions.
6 changes: 6 additions & 0 deletions crates/oxc_ast/src/ast/jsx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
40 changes: 38 additions & 2 deletions crates/oxc_transformer/src/react/jsx_self/mod.rs
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -10,13 +13,46 @@ use crate::context::Ctx;
///
/// In: `<sometag />`
/// Out: `<sometag __self={this} />`
///
/// TODO:
/// *. Omit adding `this` in some conditions
/// <https://github.com/babel/babel/blob/9cd048b5ad45eafd157c4f9968343e36170a66c1/packages/babel-plugin-transform-react-jsx-self/src/index.ts#L78>
#[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> {
/// `<div __self={this} />`
/// ^^^^^^^^^^^^^
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);
}
}
7 changes: 6 additions & 1 deletion crates/oxc_transformer/src/react/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
Expand Down Expand Up @@ -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);
}
}
6 changes: 5 additions & 1 deletion tasks/transform_conformance/babel.snap.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Passed: 75/174
Passed: 76/177

# All Passed:

Expand Down Expand Up @@ -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

1 change: 1 addition & 0 deletions tasks/transform_conformance/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
];
Expand Down

0 comments on commit f903a22

Please sign in to comment.