Skip to content

Commit

Permalink
feat(transformer): implement @babel/plugin-transform-react-jsx-self
Browse files Browse the repository at this point in the history
  • Loading branch information
fireairforce committed Mar 28, 2024
1 parent 2c6bfa3 commit 005d12e
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 1 deletion.
5 changes: 5 additions & 0 deletions crates/oxc_transformer/examples/test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function App() {
return (
<sometag />
)
}
1 change: 1 addition & 0 deletions crates/oxc_transformer/examples/transformer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ fn main() {
target: TransformTarget::ES5,
react_jsx: Some(ReactJsxOptions {
runtime: Some(ReactJsxRuntimeOption::Valid(ReactJsxRuntime::Classic)),
development: Some(true),
..ReactJsxOptions::default()
}),
..TransformOptions::default()
Expand Down
8 changes: 7 additions & 1 deletion crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ use crate::{
es2021::{LogicalAssignmentOperators, NumericSeparator},
es2022::ClassStaticBlock,
es3::PropertyLiteral,
react_jsx::ReactJsx,
react_jsx::{JsxSelf, ReactJsx},
regexp::RegexpFlags,
typescript::TypeScript,
utils::CreateVars,
Expand All @@ -72,6 +72,7 @@ pub struct Transformer<'a> {
decorators: Option<Decorators<'a>>,
#[allow(unused)]
typescript: Option<TypeScript<'a>>,
jsx_self: Option<JsxSelf<'a>>,
react_jsx: Option<ReactJsx<'a>>,
regexp_flags: Option<RegexpFlags<'a>>,
// es2022
Expand Down Expand Up @@ -140,6 +141,7 @@ impl<'a> Transformer<'a> {
es2015_new_target: NewTarget::new(ctx.clone()),
// other
es3_property_literal: PropertyLiteral::new(ctx.clone()),
jsx_self: JsxSelf::new(ctx.clone()),
react_jsx: ReactJsx::new(ctx.clone()),
// original context
ctx,
Expand Down Expand Up @@ -202,6 +204,10 @@ impl<'a> VisitMut<'a> for Transformer<'a> {
self.decorators.as_mut().map(|t| t.transform_declaration(decl));
}

fn visit_jsx_opening_element(&mut self, elem: &mut JSXOpeningElement<'a>) {
self.jsx_self.as_mut().map(|t| t.transform_jsx_opening_element(elem));
}

fn visit_expression(&mut self, expr: &mut Expression<'a>) {
// self.typescript.as_mut().map(|t| t.transform_expression(expr));
self.react_jsx.as_mut().map(|t| t.transform_expression(expr));
Expand Down
2 changes: 2 additions & 0 deletions crates/oxc_transformer/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ pub struct TransformOptions {
pub target: TransformTarget,
pub assumptions: CompilerAssumptions,

pub jsx_self: Option<ReactJsxOptions>,

pub react_jsx: Option<ReactJsxOptions>,

pub typescript: Option<TypescriptOptions>,
Expand Down
35 changes: 35 additions & 0 deletions crates/oxc_transformer/src/react_jsx/jsx_self.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::{context::TransformerCtx, ReactJsxOptions};
use oxc_ast::ast::*;
use oxc_span::SPAN;

/// @babel/plugin-transform-react-jsx-self
///
/// References:
/// * <https://babeljs.io/docs/babel-plugin-transform-react-jsx-self>
/// * <https://github.com/babel/babel/tree/main/packages/babel-plugin-transform-react-jsx-self>
///
pub struct JsxSelf<'a> {
ctx: TransformerCtx<'a>,
options: ReactJsxOptions,
}

impl<'a> JsxSelf<'a> {
pub fn new(ctx: TransformerCtx<'a>) -> Option<Self> {
let jsx_options = ctx.options.react_jsx.clone()?;
Some(Self { ctx, options: jsx_options })
}
pub fn transform_jsx_opening_element(&mut self, elem: &mut JSXOpeningElement<'a>) {
if self.options.development != Some(true) {
return;
}

elem.attributes.push(JSXAttributeItem::Attribute(self.ctx.ast.jsx_attribute(
SPAN,
JSXAttributeName::Identifier(self.ctx.ast.jsx_identifier(SPAN, "__self".into())),
Some(JSXAttributeValue::ExpressionContainer(self.ctx.ast.jsx_expression_container(
SPAN,
JSXExpression::Expression(self.ctx.ast.this_expression(SPAN)),
))),
)));
}
}
2 changes: 2 additions & 0 deletions crates/oxc_transformer/src/react_jsx/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod jsx_self;
mod options;

use oxc_allocator::Vec;
Expand All @@ -12,6 +13,7 @@ use oxc_syntax::{
xml_entities::XML_ENTITIES,
};

pub use self::jsx_self::JsxSelf;
pub use self::options::{ReactJsxOptions, ReactJsxRuntime, ReactJsxRuntimeOption};
use crate::context::TransformerCtx;

Expand Down
5 changes: 5 additions & 0 deletions crates/oxc_transformer/src/react_jsx/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ pub struct ReactJsxOptions {
/// Use `Some<T>` instead of `bool` because we want to know if user set this field explicitly,
/// which used for creating warning, <https://github.com/oxc-project/oxc/blob/c3e2098c04d8916cb812bdd16d2026bb430ac25f/crates/oxc_transformer/src/react_jsx/mod.rs#L111-L114>
pub use_spread: Option<bool>,

/// enable development transform for jsx transform
#[serde(default)]
pub development: Option<bool>,
}

fn default_throw_if_namespace() -> bool {
Expand Down Expand Up @@ -62,6 +66,7 @@ impl Default for ReactJsxOptions {
pragma_frag: default_pragma_frag(),
use_built_ins: None,
use_spread: None,
development: None,
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions tasks/transform_conformance/src/test_case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ pub trait TestCase {
decorators: options
.get_plugin("proposal-decorators")
.map(get_options::<DecoratorsOptions>),
jsx_self: options
.get_plugin("transform-react-jsx-self")
.map(get_options::<ReactJsxOptions>),
react_jsx: options
.get_plugin("transform-react-jsx")
.map(get_options::<ReactJsxOptions>),
Expand Down

0 comments on commit 005d12e

Please sign in to comment.