Skip to content

Commit

Permalink
feat(transformer): apply jsx self and source plugin inside jsx transf…
Browse files Browse the repository at this point in the history
…orm (#2966)
  • Loading branch information
Boshen authored Apr 14, 2024
1 parent 10814d5 commit 3a6eae1
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 23 deletions.
18 changes: 17 additions & 1 deletion crates/oxc_transformer/src/react/jsx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
///
Expand All @@ -27,6 +31,9 @@ pub struct ReactJsx<'a> {

ctx: Ctx<'a>,

jsx_self: ReactJsxSelf<'a>,
jsx_source: ReactJsxSource<'a>,

// States
imports: std::vec::Vec<Statement<'a>>,
require_jsx_runtime: bool,
Expand All @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down
14 changes: 12 additions & 2 deletions crates/oxc_transformer/src/react/jsx_self/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -17,7 +19,6 @@ use crate::context::Ctx;
/// 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> {
ctx: Ctx<'a>,
}
Expand All @@ -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> {
/// `<div __self={this} />`
/// ^^^^^^^^^^^^^
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);
Expand Down
32 changes: 21 additions & 11 deletions crates/oxc_transformer/src/react/jsx_source/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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> {
/// `<sometag __source={ { fileName: 'this/file.js', lineNumber: 10, columnNumber: 1 } } />`
/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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 = {
Expand Down Expand Up @@ -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)
}
}
12 changes: 5 additions & 7 deletions crates/oxc_transformer/src/react/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
6 changes: 4 additions & 2 deletions tasks/transform_conformance/babel.snap.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Passed: 131/392
Passed: 129/392

# All Passed:
* babel-plugin-transform-react-jsx-source
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 3a6eae1

Please sign in to comment.