mirror of
https://github.com/danbulant/oxc
synced 2026-05-25 04:42:10 +00:00
feat(transformer): apply jsx self and source plugin inside jsx transform (#2966)
This commit is contained in:
parent
10814d5331
commit
3a6eae1abd
5 changed files with 59 additions and 23 deletions
|
|
@ -10,7 +10,11 @@ use oxc_syntax::{
|
||||||
|
|
||||||
use crate::context::Ctx;
|
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)
|
/// [plugin-transform-react-jsx](https://babeljs.io/docs/babel-plugin-transform-react-jsx)
|
||||||
///
|
///
|
||||||
|
|
@ -27,6 +31,9 @@ pub struct ReactJsx<'a> {
|
||||||
|
|
||||||
ctx: Ctx<'a>,
|
ctx: Ctx<'a>,
|
||||||
|
|
||||||
|
jsx_self: ReactJsxSelf<'a>,
|
||||||
|
jsx_source: ReactJsxSource<'a>,
|
||||||
|
|
||||||
// States
|
// States
|
||||||
imports: std::vec::Vec<Statement<'a>>,
|
imports: std::vec::Vec<Statement<'a>>,
|
||||||
require_jsx_runtime: bool,
|
require_jsx_runtime: bool,
|
||||||
|
|
@ -53,6 +60,8 @@ impl<'a> ReactJsx<'a> {
|
||||||
Self {
|
Self {
|
||||||
options: Rc::clone(options),
|
options: Rc::clone(options),
|
||||||
ctx: Rc::clone(ctx),
|
ctx: Rc::clone(ctx),
|
||||||
|
jsx_self: ReactJsxSelf::new(ctx),
|
||||||
|
jsx_source: ReactJsxSource::new(ctx),
|
||||||
imports: vec![],
|
imports: vec![],
|
||||||
require_jsx_runtime: false,
|
require_jsx_runtime: false,
|
||||||
jsx_runtime_importer,
|
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);
|
self.add_import(e, has_key_after_props_spread, need_jsxs);
|
||||||
|
|
||||||
if !properties.is_empty() || is_automatic {
|
if !properties.is_empty() || is_automatic {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ use oxc_span::SPAN;
|
||||||
|
|
||||||
use crate::context::Ctx;
|
use crate::context::Ctx;
|
||||||
|
|
||||||
|
const SELF: &str = "__self";
|
||||||
|
|
||||||
/// [plugin-transform-react-jsx-self](https://babeljs.io/docs/babel-plugin-transform-react-jsx-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.
|
/// This plugin is included in `preset-react` and only enabled in development mode.
|
||||||
|
|
@ -17,7 +19,6 @@ use crate::context::Ctx;
|
||||||
/// TODO:
|
/// TODO:
|
||||||
/// *. Omit adding `this` in some conditions
|
/// *. Omit adding `this` in some conditions
|
||||||
/// <https://github.com/babel/babel/blob/9cd048b5ad45eafd157c4f9968343e36170a66c1/packages/babel-plugin-transform-react-jsx-self/src/index.ts#L78>
|
/// <https://github.com/babel/babel/blob/9cd048b5ad45eafd157c4f9968343e36170a66c1/packages/babel-plugin-transform-react-jsx-self/src/index.ts#L78>
|
||||||
#[allow(unused)]
|
|
||||||
pub struct ReactJsxSelf<'a> {
|
pub struct ReactJsxSelf<'a> {
|
||||||
ctx: Ctx<'a>,
|
ctx: Ctx<'a>,
|
||||||
}
|
}
|
||||||
|
|
@ -30,13 +31,22 @@ impl<'a> ReactJsxSelf<'a> {
|
||||||
pub fn transform_jsx_opening_element(&self, elem: &mut JSXOpeningElement<'a>) {
|
pub fn transform_jsx_opening_element(&self, elem: &mut JSXOpeningElement<'a>) {
|
||||||
self.add_self_this_attribute(elem);
|
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> {
|
impl<'a> ReactJsxSelf<'a> {
|
||||||
/// `<div __self={this} />`
|
/// `<div __self={this} />`
|
||||||
/// ^^^^^^^^^^^^^
|
/// ^^^^^^^^^^^^^
|
||||||
fn add_self_this_attribute(&self, elem: &mut JSXOpeningElement<'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 value = {
|
||||||
let jsx_expr = JSXExpression::Expression(self.ctx.ast.this_expression(SPAN));
|
let jsx_expr = JSXExpression::Expression(self.ctx.ast.this_expression(SPAN));
|
||||||
let container = self.ctx.ast.jsx_expression_container(SPAN, jsx_expr);
|
let container = self.ctx.ast.jsx_expression_container(SPAN, jsx_expr);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ use oxc_syntax::NumberBase;
|
||||||
|
|
||||||
use crate::context::Ctx;
|
use crate::context::Ctx;
|
||||||
|
|
||||||
|
const SOURCE: &str = "__source";
|
||||||
|
|
||||||
/// [plugin-transform-react-jsx-source](https://babeljs.io/docs/babel-plugin-transform-react-jsx-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.
|
/// 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>) {
|
pub fn transform_jsx_opening_element(&self, elem: &mut JSXOpeningElement<'a>) {
|
||||||
self.add_source_attribute(elem);
|
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> {
|
impl<'a> ReactJsxSource<'a> {
|
||||||
/// `<sometag __source={ { fileName: 'this/file.js', lineNumber: 10, columnNumber: 1 } } />`
|
/// `<sometag __source={ { fileName: 'this/file.js', lineNumber: 10, columnNumber: 1 } } />`
|
||||||
/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
fn add_source_attribute(&self, elem: &mut JSXOpeningElement<'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 kind = PropertyKind::Init;
|
||||||
|
|
||||||
let filename = {
|
let filename = {
|
||||||
|
|
@ -64,16 +84,6 @@ impl<'a> ReactJsxSource<'a> {
|
||||||
properties.push(ObjectPropertyKind::ObjectProperty(filename));
|
properties.push(ObjectPropertyKind::ObjectProperty(filename));
|
||||||
properties.push(ObjectPropertyKind::ObjectProperty(line_number));
|
properties.push(ObjectPropertyKind::ObjectProperty(line_number));
|
||||||
properties.push(ObjectPropertyKind::ObjectProperty(column_number));
|
properties.push(ObjectPropertyKind::ObjectProperty(column_number));
|
||||||
|
self.ctx.ast.object_expression(SPAN, properties, None)
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,13 +99,11 @@ impl<'a> React<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transform_jsx_opening_element(&self, elem: &mut JSXOpeningElement<'a>) {
|
pub fn transform_jsx_opening_element(&self, elem: &mut JSXOpeningElement<'a>) {
|
||||||
if self.development {
|
if self.options.is_jsx_self_plugin_enabled() {
|
||||||
if self.options.jsx_self_plugin {
|
self.jsx_self.transform_jsx_opening_element(elem);
|
||||||
self.jsx_self.transform_jsx_opening_element(elem);
|
}
|
||||||
}
|
if self.options.is_jsx_source_plugin_enabled() {
|
||||||
if self.options.jsx_source_plugin {
|
self.jsx_source.transform_jsx_opening_element(elem);
|
||||||
self.jsx_source.transform_jsx_opening_element(elem);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
Passed: 131/392
|
Passed: 129/392
|
||||||
|
|
||||||
# All Passed:
|
# All Passed:
|
||||||
* babel-plugin-transform-react-jsx-source
|
* babel-plugin-transform-react-jsx-source
|
||||||
|
|
@ -125,11 +125,13 @@ Passed: 131/392
|
||||||
* regression/15768/input.ts
|
* regression/15768/input.ts
|
||||||
* variable-declaration/non-null-in-optional-chain/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/input.js
|
||||||
* preset-options/development-runtime-automatic/input.js
|
* preset-options/development-runtime-automatic/input.js
|
||||||
* preset-options/development-runtime-automatic-windows/input.js
|
* preset-options/development-runtime-automatic-windows/input.js
|
||||||
* preset-options/development-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/input.js
|
||||||
* preset-options/runtime-classic-pragma-no-frag/input.js
|
* preset-options/runtime-classic-pragma-no-frag/input.js
|
||||||
* regression/11294/input.mjs
|
* regression/11294/input.mjs
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue