mirror of
https://github.com/danbulant/oxc
synced 2026-05-25 12:51:57 +00:00
feat(transformer): implement react-jsx-source (#2948)
This commit is contained in:
parent
b05c26374c
commit
14754777a4
6 changed files with 88 additions and 20 deletions
|
|
@ -7,7 +7,7 @@ use crate::context::Ctx;
|
||||||
|
|
||||||
/// [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`.
|
/// This plugin is included in `preset-react` and only enabled in development mode.
|
||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
|
|
@ -19,20 +19,16 @@ use crate::context::Ctx;
|
||||||
/// <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)]
|
#[allow(unused)]
|
||||||
pub struct ReactJsxSelf<'a> {
|
pub struct ReactJsxSelf<'a> {
|
||||||
development: bool,
|
|
||||||
|
|
||||||
ctx: Ctx<'a>,
|
ctx: Ctx<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ReactJsxSelf<'a> {
|
impl<'a> ReactJsxSelf<'a> {
|
||||||
pub fn new(development: bool, ctx: &Ctx<'a>) -> Self {
|
pub fn new(ctx: &Ctx<'a>) -> Self {
|
||||||
Self { development, ctx: Rc::clone(ctx) }
|
Self { ctx: Rc::clone(ctx) }
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
self.add_self_this_attribute(elem);
|
||||||
self.add_self_this_attribute(elem);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,10 +36,7 @@ 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 = {
|
let name = JSXAttributeName::Identifier(JSXIdentifier::new(SPAN, "__self".into()));
|
||||||
let name = self.ctx.ast.new_atom("__self");
|
|
||||||
JSXAttributeName::Identifier(JSXIdentifier::new(SPAN, name))
|
|
||||||
};
|
|
||||||
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);
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,21 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use oxc_ast::ast::*;
|
||||||
|
use oxc_span::SPAN;
|
||||||
|
use oxc_syntax::NumberBase;
|
||||||
|
|
||||||
use crate::context::Ctx;
|
use crate::context::Ctx;
|
||||||
|
|
||||||
/// [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)
|
||||||
#[allow(unused)]
|
///
|
||||||
|
/// This plugin is included in `preset-react` and only enabled in development mode.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
///
|
||||||
|
/// In: `<sometag />`
|
||||||
|
/// Out: `<sometag __source={ { fileName: 'this/file.js', lineNumber: 10, columnNumber: 1 } } />`
|
||||||
|
///
|
||||||
|
/// TODO: get lineNumber and columnNumber from somewhere
|
||||||
pub struct ReactJsxSource<'a> {
|
pub struct ReactJsxSource<'a> {
|
||||||
ctx: Ctx<'a>,
|
ctx: Ctx<'a>,
|
||||||
}
|
}
|
||||||
|
|
@ -12,4 +24,56 @@ impl<'a> ReactJsxSource<'a> {
|
||||||
pub fn new(ctx: &Ctx<'a>) -> Self {
|
pub fn new(ctx: &Ctx<'a>) -> Self {
|
||||||
Self { ctx: Rc::clone(ctx) }
|
Self { ctx: Rc::clone(ctx) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn transform_jsx_opening_element(&self, elem: &mut JSXOpeningElement<'a>) {
|
||||||
|
self.add_source_attribute(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ReactJsxSource<'a> {
|
||||||
|
/// `<sometag __source={ { fileName: 'this/file.js', lineNumber: 10, columnNumber: 1 } } />`
|
||||||
|
/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
fn add_source_attribute(&self, elem: &mut JSXOpeningElement<'a>) {
|
||||||
|
let kind = PropertyKind::Init;
|
||||||
|
|
||||||
|
let filename = {
|
||||||
|
let name = IdentifierName::new(SPAN, "fileName".into());
|
||||||
|
let key = self.ctx.ast.property_key_identifier(name);
|
||||||
|
let string = StringLiteral::new(SPAN, self.ctx.ast.new_atom(self.ctx.filename()));
|
||||||
|
let value = self.ctx.ast.literal_string_expression(string);
|
||||||
|
self.ctx.ast.object_property(SPAN, kind, key, value, None, false, false, false)
|
||||||
|
};
|
||||||
|
|
||||||
|
let line_number = {
|
||||||
|
let ident = IdentifierName::new(SPAN, "lineNumber".into());
|
||||||
|
let key = self.ctx.ast.property_key_identifier(ident);
|
||||||
|
let number = self.ctx.ast.number_literal(SPAN, 1.0, "1", NumberBase::Decimal);
|
||||||
|
let value = self.ctx.ast.literal_number_expression(number);
|
||||||
|
self.ctx.ast.object_property(SPAN, kind, key, value, None, false, false, false)
|
||||||
|
};
|
||||||
|
|
||||||
|
let column_number = {
|
||||||
|
let ident = IdentifierName::new(SPAN, "columnNumber".into());
|
||||||
|
let key = self.ctx.ast.property_key_identifier(ident);
|
||||||
|
let number = self.ctx.ast.number_literal(SPAN, 1.0, "1", NumberBase::Decimal);
|
||||||
|
let value = self.ctx.ast.literal_number_expression(number);
|
||||||
|
self.ctx.ast.object_property(SPAN, kind, key, value, None, false, false, false)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut properties = self.ctx.ast.new_vec();
|
||||||
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ pub struct React<'a> {
|
||||||
jsx_self: ReactJsxSelf<'a>,
|
jsx_self: ReactJsxSelf<'a>,
|
||||||
jsx_source: ReactJsxSource<'a>,
|
jsx_source: ReactJsxSource<'a>,
|
||||||
display_name: ReactDisplayName<'a>,
|
display_name: ReactDisplayName<'a>,
|
||||||
|
development: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
@ -39,9 +40,10 @@ impl<'a> React<'a> {
|
||||||
Self {
|
Self {
|
||||||
ctx: Rc::clone(ctx),
|
ctx: Rc::clone(ctx),
|
||||||
jsx: ReactJsx::new(options, ctx),
|
jsx: ReactJsx::new(options, ctx),
|
||||||
jsx_self: ReactJsxSelf::new(development, ctx),
|
jsx_self: ReactJsxSelf::new(ctx),
|
||||||
jsx_source: ReactJsxSource::new(ctx),
|
jsx_source: ReactJsxSource::new(ctx),
|
||||||
display_name: ReactDisplayName::new(ctx),
|
display_name: ReactDisplayName::new(ctx),
|
||||||
|
development,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +80,10 @@ impl<'a> React<'a> {
|
||||||
self.display_name.transform_export_default_declaration(decl);
|
self.display_name.transform_export_default_declaration(decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transform_jsx_opening_element(&mut self, elem: &mut JSXOpeningElement<'a>) {
|
pub fn transform_jsx_opening_element(&self, elem: &mut JSXOpeningElement<'a>) {
|
||||||
self.jsx_self.transform_jsx_opening_element(elem);
|
if self.development {
|
||||||
|
self.jsx_self.transform_jsx_opening_element(elem);
|
||||||
|
self.jsx_source.transform_jsx_opening_element(elem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
Passed: 76/177
|
Passed: 76/178
|
||||||
|
|
||||||
# All Passed:
|
# All Passed:
|
||||||
|
* babel-plugin-transform-react-jsx-source
|
||||||
|
|
||||||
|
|
||||||
# babel-plugin-transform-typescript (60/158)
|
# babel-plugin-transform-typescript (60/158)
|
||||||
|
|
@ -107,7 +107,8 @@ Passed: 76/177
|
||||||
# babel-plugin-transform-react-display-name (15/16)
|
# babel-plugin-transform-react-display-name (15/16)
|
||||||
* display-name/nested/input.js
|
* display-name/nested/input.js
|
||||||
|
|
||||||
# babel-plugin-transform-react-jsx-self (1/3)
|
# babel-plugin-transform-react-jsx-self (0/3)
|
||||||
* react-source/arrow-function/input.js
|
* react-source/arrow-function/input.js
|
||||||
|
* react-source/basic-sample/input.js
|
||||||
* react-source/disable-with-super/input.js
|
* react-source/disable-with-super/input.js
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
Passed: 0/0
|
Passed: 0/2
|
||||||
|
|
||||||
# All Passed:
|
# All Passed:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# babel-plugin-transform-react-jsx-source (0/2)
|
||||||
|
* react-source/basic-sample/exec.js
|
||||||
|
* react-source/with-source/exec.js
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ const CASES: &[&str] = &[
|
||||||
// "babel-plugin-transform-react-jsx",
|
// "babel-plugin-transform-react-jsx",
|
||||||
"babel-plugin-transform-react-display-name",
|
"babel-plugin-transform-react-display-name",
|
||||||
"babel-plugin-transform-react-jsx-self",
|
"babel-plugin-transform-react-jsx-self",
|
||||||
|
"babel-plugin-transform-react-jsx-source",
|
||||||
// // Proposal
|
// // Proposal
|
||||||
// "babel-plugin-proposal-decorators",
|
// "babel-plugin-proposal-decorators",
|
||||||
];
|
];
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue