mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
perf(ast): box enum variants (#3058)
Box all enum variants for JSX types (`JSXAttributeName`, `JSXAttributeValue`, `JSXChild`, `JSXElementName`, `JSXMemberExpressionObject`). Part of #3047. I'm not sure how to interpret the benchmark results. As I said on #3047: > I imagine it may cost a little in performance in the parser due to extra calls to `alloc`, but in return traversing the AST should be cheaper, as the data is more compact, so less cache misses. Sure enough, there is a small impact (1%) on the 2 parser benchmarks for JSX files. However, the other benchmarks have too much noise in them to see whether this is repaid in a speed up on transformer etc, especially as the transformer benchmarks also include parsing. What do you think @Boshen?
This commit is contained in:
parent
68d082644c
commit
48e20880d4
21 changed files with 182 additions and 176 deletions
|
|
@ -83,7 +83,7 @@ pub struct JSXClosingFragment {
|
||||||
#[cfg_attr(feature = "serialize", serde(untagged))]
|
#[cfg_attr(feature = "serialize", serde(untagged))]
|
||||||
pub enum JSXElementName<'a> {
|
pub enum JSXElementName<'a> {
|
||||||
/// `<Apple />`
|
/// `<Apple />`
|
||||||
Identifier(JSXIdentifier<'a>),
|
Identifier(Box<'a, JSXIdentifier<'a>>),
|
||||||
/// `<Apple:Orange />`
|
/// `<Apple:Orange />`
|
||||||
NamespacedName(Box<'a, JSXNamespacedName<'a>>),
|
NamespacedName(Box<'a, JSXNamespacedName<'a>>),
|
||||||
/// `<Apple.Orange />`
|
/// `<Apple.Orange />`
|
||||||
|
|
@ -131,7 +131,7 @@ impl<'a> JSXMemberExpression<'a> {
|
||||||
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
|
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
|
||||||
#[cfg_attr(feature = "serialize", serde(untagged))]
|
#[cfg_attr(feature = "serialize", serde(untagged))]
|
||||||
pub enum JSXMemberExpressionObject<'a> {
|
pub enum JSXMemberExpressionObject<'a> {
|
||||||
Identifier(JSXIdentifier<'a>),
|
Identifier(Box<'a, JSXIdentifier<'a>>),
|
||||||
MemberExpression(Box<'a, JSXMemberExpression<'a>>),
|
MemberExpression(Box<'a, JSXMemberExpression<'a>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -203,7 +203,7 @@ pub struct JSXSpreadAttribute<'a> {
|
||||||
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
|
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
|
||||||
#[cfg_attr(feature = "serialize", serde(untagged))]
|
#[cfg_attr(feature = "serialize", serde(untagged))]
|
||||||
pub enum JSXAttributeName<'a> {
|
pub enum JSXAttributeName<'a> {
|
||||||
Identifier(JSXIdentifier<'a>),
|
Identifier(Box<'a, JSXIdentifier<'a>>),
|
||||||
NamespacedName(Box<'a, JSXNamespacedName<'a>>),
|
NamespacedName(Box<'a, JSXNamespacedName<'a>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,8 +212,8 @@ pub enum JSXAttributeName<'a> {
|
||||||
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
|
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
|
||||||
#[cfg_attr(feature = "serialize", serde(untagged))]
|
#[cfg_attr(feature = "serialize", serde(untagged))]
|
||||||
pub enum JSXAttributeValue<'a> {
|
pub enum JSXAttributeValue<'a> {
|
||||||
StringLiteral(StringLiteral<'a>),
|
StringLiteral(Box<'a, StringLiteral<'a>>),
|
||||||
ExpressionContainer(JSXExpressionContainer<'a>),
|
ExpressionContainer(Box<'a, JSXExpressionContainer<'a>>),
|
||||||
Element(Box<'a, JSXElement<'a>>),
|
Element(Box<'a, JSXElement<'a>>),
|
||||||
Fragment(Box<'a, JSXFragment<'a>>),
|
Fragment(Box<'a, JSXFragment<'a>>),
|
||||||
}
|
}
|
||||||
|
|
@ -240,11 +240,11 @@ impl<'a> JSXIdentifier<'a> {
|
||||||
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
|
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
|
||||||
#[cfg_attr(feature = "serialize", serde(untagged))]
|
#[cfg_attr(feature = "serialize", serde(untagged))]
|
||||||
pub enum JSXChild<'a> {
|
pub enum JSXChild<'a> {
|
||||||
Text(JSXText<'a>),
|
Text(Box<'a, JSXText<'a>>),
|
||||||
Element(Box<'a, JSXElement<'a>>),
|
Element(Box<'a, JSXElement<'a>>),
|
||||||
Fragment(Box<'a, JSXFragment<'a>>),
|
Fragment(Box<'a, JSXFragment<'a>>),
|
||||||
ExpressionContainer(JSXExpressionContainer<'a>),
|
ExpressionContainer(Box<'a, JSXExpressionContainer<'a>>),
|
||||||
Spread(JSXSpreadChild<'a>),
|
Spread(Box<'a, JSXSpreadChild<'a>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Hash)]
|
#[derive(Debug, Hash)]
|
||||||
|
|
|
||||||
|
|
@ -1302,12 +1302,16 @@ impl<'a> AstBuilder<'a> {
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
expression: JSXExpression<'a>,
|
expression: JSXExpression<'a>,
|
||||||
) -> JSXExpressionContainer<'a> {
|
) -> Box<'a, JSXExpressionContainer<'a>> {
|
||||||
JSXExpressionContainer { span, expression }
|
self.alloc(JSXExpressionContainer { span, expression })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn jsx_spread_child(&self, span: Span, expression: Expression<'a>) -> JSXSpreadChild<'a> {
|
pub fn jsx_spread_child(
|
||||||
JSXSpreadChild { span, expression }
|
&self,
|
||||||
|
span: Span,
|
||||||
|
expression: Expression<'a>,
|
||||||
|
) -> Box<'a, JSXSpreadChild<'a>> {
|
||||||
|
self.alloc(JSXSpreadChild { span, expression })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn jsx_empty_expression(&self, span: Span) -> JSXEmptyExpression {
|
pub fn jsx_empty_expression(&self, span: Span) -> JSXEmptyExpression {
|
||||||
|
|
@ -1335,8 +1339,8 @@ impl<'a> AstBuilder<'a> {
|
||||||
JSXIdentifier { span, name }
|
JSXIdentifier { span, name }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn jsx_text(&self, span: Span, value: Atom<'a>) -> JSXText<'a> {
|
pub fn jsx_text(&self, span: Span, value: Atom<'a>) -> Box<'a, JSXText<'a>> {
|
||||||
JSXText { span, value }
|
self.alloc(JSXText { span, value })
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- TypeScript ---------- */
|
/* ---------- TypeScript ---------- */
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{
|
ast::{JSXAttributeItem, JSXAttributeValue, JSXElement, JSXExpression, JSXOpeningElement},
|
||||||
JSXAttributeItem, JSXAttributeValue, JSXElement, JSXExpression, JSXExpressionContainer,
|
|
||||||
JSXOpeningElement,
|
|
||||||
},
|
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::{
|
use oxc_diagnostics::{
|
||||||
|
|
@ -212,10 +209,13 @@ impl Rule for AltText {
|
||||||
fn is_valid_alt_prop(item: &JSXAttributeItem<'_>) -> bool {
|
fn is_valid_alt_prop(item: &JSXAttributeItem<'_>) -> bool {
|
||||||
match get_prop_value(item) {
|
match get_prop_value(item) {
|
||||||
None => false,
|
None => false,
|
||||||
Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
Some(JSXAttributeValue::ExpressionContainer(container)) => {
|
||||||
expression: JSXExpression::Expression(expr),
|
if let JSXExpression::Expression(expr) = &container.expression {
|
||||||
..
|
!expr.is_null_or_undefined()
|
||||||
})) => !expr.is_null_or_undefined(),
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -229,10 +229,13 @@ fn aria_label_has_value<'a>(item: &'a JSXAttributeItem<'a>) -> bool {
|
||||||
match get_prop_value(item) {
|
match get_prop_value(item) {
|
||||||
None => false,
|
None => false,
|
||||||
Some(JSXAttributeValue::StringLiteral(s)) if s.value.is_empty() => false,
|
Some(JSXAttributeValue::StringLiteral(s)) if s.value.is_empty() => false,
|
||||||
Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
Some(JSXAttributeValue::ExpressionContainer(container)) => {
|
||||||
expression: JSXExpression::Expression(expr),
|
if let JSXExpression::Expression(expr) = &container.expression {
|
||||||
..
|
!expr.is_undefined()
|
||||||
})) => !expr.is_undefined(),
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{JSXAttributeValue, JSXExpression, JSXExpressionContainer},
|
ast::{JSXAttributeValue, JSXExpression},
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::{
|
use oxc_diagnostics::{
|
||||||
|
|
@ -134,12 +134,11 @@ impl Rule for AriaRole {
|
||||||
};
|
};
|
||||||
|
|
||||||
match get_prop_value(aria_role) {
|
match get_prop_value(aria_role) {
|
||||||
Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
Some(JSXAttributeValue::ExpressionContainer(container)) => {
|
||||||
expression: JSXExpression::Expression(expr),
|
if let JSXExpression::Expression(expr) = &container.expression {
|
||||||
..
|
if expr.is_undefined() || expr.is_null() {
|
||||||
})) => {
|
ctx.diagnostic(AriaRoleDiagnostic(attr.span, String::new()));
|
||||||
if expr.is_undefined() || expr.is_null() {
|
}
|
||||||
ctx.diagnostic(AriaRoleDiagnostic(attr.span, String::new()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(JSXAttributeValue::StringLiteral(str)) => {
|
Some(JSXAttributeValue::StringLiteral(str)) => {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{
|
ast::{JSXAttributeItem, JSXAttributeValue, JSXElementName, JSXExpression},
|
||||||
JSXAttributeItem, JSXAttributeValue, JSXElementName, JSXExpression, JSXExpressionContainer,
|
|
||||||
},
|
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::{
|
use oxc_diagnostics::{
|
||||||
|
|
@ -87,10 +85,13 @@ impl Rule for HtmlHasLang {
|
||||||
|
|
||||||
fn is_valid_lang_prop(item: &JSXAttributeItem) -> bool {
|
fn is_valid_lang_prop(item: &JSXAttributeItem) -> bool {
|
||||||
match get_prop_value(item) {
|
match get_prop_value(item) {
|
||||||
Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
Some(JSXAttributeValue::ExpressionContainer(container)) => {
|
||||||
expression: JSXExpression::Expression(expr),
|
if let JSXExpression::Expression(expr) = &container.expression {
|
||||||
..
|
!expr.is_undefined()
|
||||||
})) => !expr.is_undefined(),
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
Some(JSXAttributeValue::StringLiteral(str)) => !str.value.as_str().is_empty(),
|
Some(JSXAttributeValue::StringLiteral(str)) => !str.value.as_str().is_empty(),
|
||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{Expression, JSXAttributeValue, JSXElementName, JSXExpression, JSXExpressionContainer},
|
ast::{Expression, JSXAttributeValue, JSXElementName, JSXExpression},
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::{
|
use oxc_diagnostics::{
|
||||||
|
|
@ -88,28 +88,27 @@ impl Rule for IframeHasTitle {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
Some(JSXAttributeValue::ExpressionContainer(container)) => {
|
||||||
expression: JSXExpression::Expression(expr),
|
if let JSXExpression::Expression(expr) = &container.expression {
|
||||||
..
|
if expr.is_string_literal() {
|
||||||
})) => {
|
if let Expression::StringLiteral(str) = expr {
|
||||||
if expr.is_string_literal() {
|
if !str.value.as_str().is_empty() {
|
||||||
if let Expression::StringLiteral(str) = expr {
|
return;
|
||||||
if !str.value.as_str().is_empty() {
|
}
|
||||||
return;
|
}
|
||||||
|
if let Expression::TemplateLiteral(tmpl) = expr {
|
||||||
|
if !tmpl.quasis.is_empty()
|
||||||
|
& !tmpl.expressions.is_empty()
|
||||||
|
& tmpl.quasis.iter().any(|q| !q.value.raw.as_str().is_empty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Expression::TemplateLiteral(tmpl) = expr {
|
|
||||||
if !tmpl.quasis.is_empty()
|
|
||||||
& !tmpl.expressions.is_empty()
|
|
||||||
& tmpl.quasis.iter().any(|q| !q.value.raw.as_str().is_empty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if expr.is_identifier_reference() & !expr.is_undefined() {
|
if expr.is_identifier_reference() & !expr.is_undefined() {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{
|
ast::{Expression, JSXAttributeItem, JSXAttributeName, JSXAttributeValue, JSXExpression},
|
||||||
Expression, JSXAttributeItem, JSXAttributeName, JSXAttributeValue, JSXExpression,
|
|
||||||
JSXExpressionContainer,
|
|
||||||
},
|
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::{
|
use oxc_diagnostics::{
|
||||||
|
|
@ -149,18 +146,15 @@ impl Rule for ImgRedundantAlt {
|
||||||
ctx.diagnostic(ImgRedundantAltDiagnostic(alt_attribute_name_span));
|
ctx.diagnostic(ImgRedundantAltDiagnostic(alt_attribute_name_span));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
JSXAttributeValue::ExpressionContainer(container) => match &container.expression {
|
||||||
expression: JSXExpression::Expression(expression),
|
JSXExpression::Expression(Expression::StringLiteral(lit)) => {
|
||||||
..
|
|
||||||
}) => match expression {
|
|
||||||
Expression::StringLiteral(lit) => {
|
|
||||||
let alt_text = lit.value.as_str();
|
let alt_text = lit.value.as_str();
|
||||||
|
|
||||||
if is_redundant_alt_text(alt_text, &self.redundant_words) {
|
if is_redundant_alt_text(alt_text, &self.redundant_words) {
|
||||||
ctx.diagnostic(ImgRedundantAltDiagnostic(alt_attribute_name_span));
|
ctx.diagnostic(ImgRedundantAltDiagnostic(alt_attribute_name_span));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::TemplateLiteral(lit) => {
|
JSXExpression::Expression(Expression::TemplateLiteral(lit)) => {
|
||||||
for quasi in &lit.quasis {
|
for quasi in &lit.quasis {
|
||||||
let alt_text = quasi.value.raw.as_str();
|
let alt_text = quasi.value.raw.as_str();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
use language_tags::LanguageTag;
|
use language_tags::LanguageTag;
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{
|
ast::{JSXAttributeItem, JSXAttributeValue, JSXElementName, JSXExpression},
|
||||||
JSXAttributeItem, JSXAttributeValue, JSXElementName, JSXExpression, JSXExpressionContainer,
|
|
||||||
},
|
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::{
|
use oxc_diagnostics::{
|
||||||
|
|
@ -94,10 +92,13 @@ impl Rule for Lang {
|
||||||
|
|
||||||
fn is_valid_lang_prop(item: &JSXAttributeItem) -> bool {
|
fn is_valid_lang_prop(item: &JSXAttributeItem) -> bool {
|
||||||
match get_prop_value(item) {
|
match get_prop_value(item) {
|
||||||
Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
Some(JSXAttributeValue::ExpressionContainer(container)) => {
|
||||||
expression: JSXExpression::Expression(expr),
|
if let JSXExpression::Expression(expr) = &container.expression {
|
||||||
..
|
!expr.is_undefined()
|
||||||
})) => !expr.is_undefined(),
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
Some(JSXAttributeValue::StringLiteral(str)) => {
|
Some(JSXAttributeValue::StringLiteral(str)) => {
|
||||||
let language_tag = LanguageTag::parse(str.value.as_str()).unwrap();
|
let language_tag = LanguageTag::parse(str.value.as_str()).unwrap();
|
||||||
language_tag.is_valid()
|
language_tag.is_valid()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{JSXAttributeValue, JSXExpression, JSXExpressionContainer},
|
ast::{JSXAttributeValue, JSXExpression},
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::{
|
use oxc_diagnostics::{
|
||||||
|
|
@ -119,15 +119,14 @@ impl Rule for MouseEventsHaveKeyEvents {
|
||||||
}
|
}
|
||||||
|
|
||||||
match has_jsx_prop(jsx_opening_el, "onFocus").and_then(get_prop_value) {
|
match has_jsx_prop(jsx_opening_el, "onFocus").and_then(get_prop_value) {
|
||||||
Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
Some(JSXAttributeValue::ExpressionContainer(container)) => {
|
||||||
expression: JSXExpression::Expression(expr),
|
if let JSXExpression::Expression(expr) = &container.expression {
|
||||||
..
|
if expr.is_undefined() {
|
||||||
})) => {
|
ctx.diagnostic(MouseEventsHaveKeyEventsDiagnostic::MissOnFocus(
|
||||||
if expr.is_undefined() {
|
jsx_attr.span(),
|
||||||
ctx.diagnostic(MouseEventsHaveKeyEventsDiagnostic::MissOnFocus(
|
String::from(handler),
|
||||||
jsx_attr.span(),
|
));
|
||||||
String::from(handler),
|
}
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
|
@ -150,15 +149,14 @@ impl Rule for MouseEventsHaveKeyEvents {
|
||||||
}
|
}
|
||||||
|
|
||||||
match has_jsx_prop(jsx_opening_el, "onBlur").and_then(get_prop_value) {
|
match has_jsx_prop(jsx_opening_el, "onBlur").and_then(get_prop_value) {
|
||||||
Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
Some(JSXAttributeValue::ExpressionContainer(container)) => {
|
||||||
expression: JSXExpression::Expression(expr),
|
if let JSXExpression::Expression(expr) = &container.expression {
|
||||||
..
|
if expr.is_undefined() {
|
||||||
})) => {
|
ctx.diagnostic(MouseEventsHaveKeyEventsDiagnostic::MissOnBlur(
|
||||||
if expr.is_undefined() {
|
jsx_attr.span(),
|
||||||
ctx.diagnostic(MouseEventsHaveKeyEventsDiagnostic::MissOnBlur(
|
String::from(handler),
|
||||||
jsx_attr.span(),
|
));
|
||||||
String::from(handler),
|
}
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{JSXAttributeItem, JSXAttributeValue, JSXExpression, JSXExpressionContainer},
|
ast::{JSXAttributeItem, JSXAttributeValue, JSXExpression},
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::{
|
use oxc_diagnostics::{
|
||||||
|
|
@ -48,14 +48,13 @@ impl Rule for NoAccessKey {
|
||||||
Some(JSXAttributeValue::StringLiteral(_)) => {
|
Some(JSXAttributeValue::StringLiteral(_)) => {
|
||||||
ctx.diagnostic(NoAccessKeyDiagnostic(attr.span));
|
ctx.diagnostic(NoAccessKeyDiagnostic(attr.span));
|
||||||
}
|
}
|
||||||
Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
Some(JSXAttributeValue::ExpressionContainer(container)) => {
|
||||||
expression: JSXExpression::Expression(expr),
|
if let JSXExpression::Expression(expr) = &container.expression {
|
||||||
..
|
if expr.is_identifier_reference() & expr.is_undefined() {
|
||||||
})) => {
|
return;
|
||||||
if expr.is_identifier_reference() & expr.is_undefined() {
|
}
|
||||||
return;
|
ctx.diagnostic(NoAccessKeyDiagnostic(attr.span));
|
||||||
}
|
}
|
||||||
ctx.diagnostic(NoAccessKeyDiagnostic(attr.span));
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{JSXAttributeItem, JSXAttributeName, JSXAttributeValue, JSXElementName, JSXIdentifier},
|
ast::{JSXAttributeItem, JSXAttributeName, JSXAttributeValue, JSXElementName},
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::{
|
use oxc_diagnostics::{
|
||||||
|
|
@ -48,8 +48,9 @@ impl Rule for NoBeforeInteractiveScriptOutsideDocument {
|
||||||
if is_in_app_dir(file_path) {
|
if is_in_app_dir(file_path) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let JSXElementName::Identifier(JSXIdentifier { name: tag_name, .. }) = &jsx_el.name
|
let tag_name = if let JSXElementName::Identifier(ident) = &jsx_el.name {
|
||||||
else {
|
&ident.name
|
||||||
|
} else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if jsx_el.attributes.len() == 0 {
|
if jsx_el.attributes.len() == 0 {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{JSXAttributeItem, JSXAttributeName, JSXAttributeValue, JSXElementName, JSXIdentifier},
|
ast::{JSXAttributeItem, JSXAttributeName, JSXAttributeValue, JSXElementName},
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::{
|
use oxc_diagnostics::{
|
||||||
|
|
@ -111,8 +111,9 @@ const NEXT_POLYFILLED_FEATURES: Set<&'static str> = phf_set! {
|
||||||
impl Rule for NoUnwantedPolyfillio {
|
impl Rule for NoUnwantedPolyfillio {
|
||||||
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
||||||
if let AstKind::JSXOpeningElement(jsx_el) = node.kind() {
|
if let AstKind::JSXOpeningElement(jsx_el) = node.kind() {
|
||||||
let JSXElementName::Identifier(JSXIdentifier { name: tag_name, .. }) = &jsx_el.name
|
let tag_name = if let JSXElementName::Identifier(ident) = &jsx_el.name {
|
||||||
else {
|
&ident.name
|
||||||
|
} else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{
|
ast::{
|
||||||
Argument, Expression, JSXAttributeItem, JSXAttributeValue, JSXElementName, JSXExpression,
|
Argument, Expression, JSXAttributeItem, JSXAttributeValue, JSXElementName, JSXExpression,
|
||||||
JSXExpressionContainer, ObjectPropertyKind,
|
ObjectPropertyKind,
|
||||||
},
|
},
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
|
|
@ -163,10 +163,13 @@ impl Rule for ButtonHasType {
|
||||||
impl ButtonHasType {
|
impl ButtonHasType {
|
||||||
fn is_valid_button_type_prop(&self, item: &JSXAttributeItem) -> bool {
|
fn is_valid_button_type_prop(&self, item: &JSXAttributeItem) -> bool {
|
||||||
match get_prop_value(item) {
|
match get_prop_value(item) {
|
||||||
Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
Some(JSXAttributeValue::ExpressionContainer(container)) => {
|
||||||
expression: JSXExpression::Expression(expr),
|
if let JSXExpression::Expression(expr) = &container.expression {
|
||||||
..
|
self.is_valid_button_type_prop_expression(expr)
|
||||||
})) => self.is_valid_button_type_prop_expression(expr),
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
Some(JSXAttributeValue::StringLiteral(str)) => {
|
Some(JSXAttributeValue::StringLiteral(str)) => {
|
||||||
self.is_valid_button_type_prop_string_literal(str.value.as_str())
|
self.is_valid_button_type_prop_string_literal(str.value.as_str())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{Expression, JSXAttributeValue, JSXElement, JSXExpression, JSXExpressionContainer},
|
ast::{Expression, JSXAttributeValue, JSXElement, JSXExpression},
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::{
|
use oxc_diagnostics::{
|
||||||
|
|
@ -52,12 +52,11 @@ fn check_jsx_element<'a>(jsx_elem: &JSXElement<'a>, ctx: &LintContext<'a>) {
|
||||||
for item in &jsx_elem.opening_element.attributes {
|
for item in &jsx_elem.opening_element.attributes {
|
||||||
match get_prop_value(item) {
|
match get_prop_value(item) {
|
||||||
None => return,
|
None => return,
|
||||||
Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
Some(JSXAttributeValue::ExpressionContainer(container)) => {
|
||||||
expression: JSXExpression::Expression(expr),
|
if let JSXExpression::Expression(expr) = &container.expression {
|
||||||
..
|
if let Some(span) = check_expression(expr) {
|
||||||
})) => {
|
ctx.diagnostic(JsxNoJsxAsPropDiagnostic(span));
|
||||||
if let Some(span) = check_expression(expr) {
|
}
|
||||||
ctx.diagnostic(JsxNoJsxAsPropDiagnostic(span));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{Expression, JSXAttributeValue, JSXElement, JSXExpression, JSXExpressionContainer},
|
ast::{Expression, JSXAttributeValue, JSXElement, JSXExpression},
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::{
|
use oxc_diagnostics::{
|
||||||
|
|
@ -58,12 +58,11 @@ fn check_jsx_element<'a>(jsx_elem: &JSXElement<'a>, ctx: &LintContext<'a>) {
|
||||||
for item in &jsx_elem.opening_element.attributes {
|
for item in &jsx_elem.opening_element.attributes {
|
||||||
match get_prop_value(item) {
|
match get_prop_value(item) {
|
||||||
None => return,
|
None => return,
|
||||||
Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
Some(JSXAttributeValue::ExpressionContainer(container)) => {
|
||||||
expression: JSXExpression::Expression(expr),
|
if let JSXExpression::Expression(expr) = &container.expression {
|
||||||
..
|
if let Some(span) = check_expression(expr) {
|
||||||
})) => {
|
ctx.diagnostic(JsxNoNewArrayAsPropDiagnostic(span));
|
||||||
if let Some(span) = check_expression(expr) {
|
}
|
||||||
ctx.diagnostic(JsxNoNewArrayAsPropDiagnostic(span));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{
|
ast::{Expression, JSXAttributeValue, JSXElement, JSXExpression, MemberExpression},
|
||||||
Expression, JSXAttributeValue, JSXElement, JSXExpression, JSXExpressionContainer,
|
|
||||||
MemberExpression,
|
|
||||||
},
|
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::{
|
use oxc_diagnostics::{
|
||||||
|
|
@ -56,12 +53,11 @@ fn check_jsx_element<'a>(jsx_elem: &JSXElement<'a>, ctx: &LintContext<'a>) {
|
||||||
for item in &jsx_elem.opening_element.attributes {
|
for item in &jsx_elem.opening_element.attributes {
|
||||||
match get_prop_value(item) {
|
match get_prop_value(item) {
|
||||||
None => return,
|
None => return,
|
||||||
Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
Some(JSXAttributeValue::ExpressionContainer(container)) => {
|
||||||
expression: JSXExpression::Expression(expr),
|
if let JSXExpression::Expression(expr) = &container.expression {
|
||||||
..
|
if let Some(span) = check_expression(expr) {
|
||||||
})) => {
|
ctx.diagnostic(JsxNoNewFunctionAsPropDiagnostic(span));
|
||||||
if let Some(span) = check_expression(expr) {
|
}
|
||||||
ctx.diagnostic(JsxNoNewFunctionAsPropDiagnostic(span));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{Expression, JSXAttributeValue, JSXElement, JSXExpression, JSXExpressionContainer},
|
ast::{Expression, JSXAttributeValue, JSXElement, JSXExpression},
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::{
|
use oxc_diagnostics::{
|
||||||
|
|
@ -57,12 +57,11 @@ fn check_jsx_element<'a>(jsx_elem: &JSXElement<'a>, ctx: &LintContext<'a>) {
|
||||||
for item in &jsx_elem.opening_element.attributes {
|
for item in &jsx_elem.opening_element.attributes {
|
||||||
match get_prop_value(item) {
|
match get_prop_value(item) {
|
||||||
None => return,
|
None => return,
|
||||||
Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
Some(JSXAttributeValue::ExpressionContainer(container)) => {
|
||||||
expression: JSXExpression::Expression(expr),
|
if let JSXExpression::Expression(expr) = &container.expression {
|
||||||
..
|
if let Some(span) = check_expression(expr) {
|
||||||
})) => {
|
ctx.diagnostic(JsxNoNewObjectAsPropDiagnostic(span));
|
||||||
if let Some(span) = check_expression(expr) {
|
}
|
||||||
ctx.diagnostic(JsxNoNewObjectAsPropDiagnostic(span));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{
|
ast::{
|
||||||
CallExpression, Expression, JSXAttributeItem, JSXAttributeName, JSXAttributeValue,
|
CallExpression, Expression, JSXAttributeItem, JSXAttributeName, JSXAttributeValue,
|
||||||
JSXChild, JSXElement, JSXElementName, JSXExpression, JSXExpressionContainer,
|
JSXChild, JSXElement, JSXElementName, JSXExpression, JSXOpeningElement,
|
||||||
JSXOpeningElement,
|
|
||||||
},
|
},
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
|
|
@ -94,10 +93,13 @@ pub fn is_hidden_from_screen_reader(ctx: &LintContext, node: &JSXOpeningElement)
|
||||||
has_jsx_prop_lowercase(node, "aria-hidden").map_or(false, |v| match get_prop_value(v) {
|
has_jsx_prop_lowercase(node, "aria-hidden").map_or(false, |v| match get_prop_value(v) {
|
||||||
None => true,
|
None => true,
|
||||||
Some(JSXAttributeValue::StringLiteral(s)) if s.value == "true" => true,
|
Some(JSXAttributeValue::StringLiteral(s)) if s.value == "true" => true,
|
||||||
Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
Some(JSXAttributeValue::ExpressionContainer(container)) => {
|
||||||
expression: JSXExpression::Expression(expr),
|
if let JSXExpression::Expression(expr) = &container.expression {
|
||||||
..
|
expr.get_boolean_value().unwrap_or(false)
|
||||||
})) => expr.get_boolean_value().unwrap_or(false),
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -107,10 +109,13 @@ pub fn object_has_accessible_child(ctx: &LintContext, node: &JSXElement<'_>) ->
|
||||||
node.children.iter().any(|child| match child {
|
node.children.iter().any(|child| match child {
|
||||||
JSXChild::Text(text) => !text.value.is_empty(),
|
JSXChild::Text(text) => !text.value.is_empty(),
|
||||||
JSXChild::Element(el) => !is_hidden_from_screen_reader(ctx, &el.opening_element),
|
JSXChild::Element(el) => !is_hidden_from_screen_reader(ctx, &el.opening_element),
|
||||||
JSXChild::ExpressionContainer(JSXExpressionContainer {
|
JSXChild::ExpressionContainer(container) => {
|
||||||
expression: JSXExpression::Expression(expr),
|
if let JSXExpression::Expression(expr) = &container.expression {
|
||||||
..
|
!expr.is_undefined() && !expr.is_null()
|
||||||
}) => !expr.is_undefined() && !expr.is_null(),
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}) || has_jsx_prop_lowercase(&node.opening_element, "dangerouslySetInnerHTML").is_some()
|
}) || has_jsx_prop_lowercase(&node.opening_element, "dangerouslySetInnerHTML").is_some()
|
||||||
|| has_jsx_prop_lowercase(&node.opening_element, "children").is_some()
|
|| has_jsx_prop_lowercase(&node.opening_element, "children").is_some()
|
||||||
|
|
@ -252,15 +257,14 @@ pub fn get_element_type(context: &LintContext, element: &JSXOpeningElement) -> O
|
||||||
pub fn parse_jsx_value(value: &JSXAttributeValue) -> Result<f64, ()> {
|
pub fn parse_jsx_value(value: &JSXAttributeValue) -> Result<f64, ()> {
|
||||||
match value {
|
match value {
|
||||||
JSXAttributeValue::StringLiteral(str) => str.value.parse().or(Err(())),
|
JSXAttributeValue::StringLiteral(str) => str.value.parse().or(Err(())),
|
||||||
JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
|
JSXAttributeValue::ExpressionContainer(container) => match &container.expression {
|
||||||
expression: JSXExpression::Expression(expression),
|
JSXExpression::Expression(Expression::StringLiteral(str)) => {
|
||||||
..
|
str.value.parse().or(Err(()))
|
||||||
}) => match expression {
|
}
|
||||||
Expression::StringLiteral(str) => str.value.parse().or(Err(())),
|
JSXExpression::Expression(Expression::TemplateLiteral(tmpl)) => {
|
||||||
Expression::TemplateLiteral(tmpl) => {
|
|
||||||
tmpl.quasis.first().unwrap().value.raw.parse().or(Err(()))
|
tmpl.quasis.first().unwrap().value.raw.parse().or(Err(()))
|
||||||
}
|
}
|
||||||
Expression::NumericLiteral(num) => Ok(num.value),
|
JSXExpression::Expression(Expression::NumericLiteral(num)) => Ok(num.value),
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
},
|
},
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
.map(JSXElementName::MemberExpression);
|
.map(JSXElementName::MemberExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(JSXElementName::Identifier(identifier))
|
Ok(JSXElementName::Identifier(self.ast.alloc(identifier)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `JSXMemberExpression` :
|
/// `JSXMemberExpression` :
|
||||||
|
|
@ -156,7 +156,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
object: JSXIdentifier<'a>,
|
object: JSXIdentifier<'a>,
|
||||||
) -> Result<Box<'a, JSXMemberExpression<'a>>> {
|
) -> Result<Box<'a, JSXMemberExpression<'a>>> {
|
||||||
let mut span = span;
|
let mut span = span;
|
||||||
let mut object = JSXMemberExpressionObject::Identifier(object);
|
let mut object = JSXMemberExpressionObject::Identifier(self.ast.alloc(object));
|
||||||
let mut property = None;
|
let mut property = None;
|
||||||
|
|
||||||
while self.eat(Kind::Dot) && !self.at(Kind::Eof) {
|
while self.eat(Kind::Dot) && !self.at(Kind::Eof) {
|
||||||
|
|
@ -214,10 +214,11 @@ impl<'a> ParserImpl<'a> {
|
||||||
self.parse_jsx_spread_child().map(JSXChild::Spread).map(Some)
|
self.parse_jsx_spread_child().map(JSXChild::Spread).map(Some)
|
||||||
}
|
}
|
||||||
// {expr}
|
// {expr}
|
||||||
Kind::LCurly => self
|
Kind::LCurly => {
|
||||||
.parse_jsx_expression_container(/* is_jsx_child */ true)
|
self.parse_jsx_expression_container(/* is_jsx_child */ true)
|
||||||
.map(JSXChild::ExpressionContainer)
|
.map(JSXChild::ExpressionContainer)
|
||||||
.map(Some),
|
.map(Some)
|
||||||
|
}
|
||||||
// text
|
// text
|
||||||
Kind::JSXText => Ok(Some(JSXChild::Text(self.parse_jsx_text()))),
|
Kind::JSXText => Ok(Some(JSXChild::Text(self.parse_jsx_text()))),
|
||||||
_ => Err(self.unexpected()),
|
_ => Err(self.unexpected()),
|
||||||
|
|
@ -228,7 +229,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
fn parse_jsx_expression_container(
|
fn parse_jsx_expression_container(
|
||||||
&mut self,
|
&mut self,
|
||||||
in_jsx_child: bool,
|
in_jsx_child: bool,
|
||||||
) -> Result<JSXExpressionContainer<'a>> {
|
) -> Result<Box<'a, JSXExpressionContainer<'a>>> {
|
||||||
let span = self.start_span();
|
let span = self.start_span();
|
||||||
self.bump_any(); // bump `{`
|
self.bump_any(); // bump `{`
|
||||||
|
|
||||||
|
|
@ -269,7 +270,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
|
|
||||||
/// `JSXChildExpression` :
|
/// `JSXChildExpression` :
|
||||||
/// { ... `AssignmentExpression` }
|
/// { ... `AssignmentExpression` }
|
||||||
fn parse_jsx_spread_child(&mut self) -> Result<JSXSpreadChild<'a>> {
|
fn parse_jsx_spread_child(&mut self) -> Result<Box<'a, JSXSpreadChild<'a>>> {
|
||||||
let span = self.start_span();
|
let span = self.start_span();
|
||||||
self.bump_any(); // bump `{`
|
self.bump_any(); // bump `{`
|
||||||
self.expect(Kind::Dot3)?;
|
self.expect(Kind::Dot3)?;
|
||||||
|
|
@ -336,12 +337,14 @@ impl<'a> ParserImpl<'a> {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(JSXAttributeName::Identifier(identifier))
|
Ok(JSXAttributeName::Identifier(self.ast.alloc(identifier)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_jsx_attribute_value(&mut self) -> Result<JSXAttributeValue<'a>> {
|
fn parse_jsx_attribute_value(&mut self) -> Result<JSXAttributeValue<'a>> {
|
||||||
match self.cur_kind() {
|
match self.cur_kind() {
|
||||||
Kind::Str => self.parse_literal_string().map(JSXAttributeValue::StringLiteral),
|
Kind::Str => self
|
||||||
|
.parse_literal_string()
|
||||||
|
.map(|str_lit| JSXAttributeValue::StringLiteral(self.ast.alloc(str_lit))),
|
||||||
Kind::LCurly => {
|
Kind::LCurly => {
|
||||||
let expr = self.parse_jsx_expression_container(/* is_jsx_child */ false)?;
|
let expr = self.parse_jsx_expression_container(/* is_jsx_child */ false)?;
|
||||||
Ok(JSXAttributeValue::ExpressionContainer(expr))
|
Ok(JSXAttributeValue::ExpressionContainer(expr))
|
||||||
|
|
@ -374,7 +377,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
Ok(self.ast.jsx_identifier(span, name.into()))
|
Ok(self.ast.jsx_identifier(span, name.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_jsx_text(&mut self) -> JSXText<'a> {
|
fn parse_jsx_text(&mut self) -> Box<'a, JSXText<'a>> {
|
||||||
let span = self.start_span();
|
let span = self.start_span();
|
||||||
let value = Atom::from(self.cur_string());
|
let value = Atom::from(self.cur_string());
|
||||||
self.bump_any();
|
self.bump_any();
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,8 @@ impl<'a> ReactJsxSelf<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = JSXAttributeName::Identifier(JSXIdentifier::new(SPAN, SELF.into()));
|
let name =
|
||||||
|
JSXAttributeName::Identifier(self.ctx.ast.alloc(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);
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,9 @@ impl<'a> ReactJsxSource<'a> {
|
||||||
|
|
||||||
self.should_add_jsx_file_name_variable = true;
|
self.should_add_jsx_file_name_variable = true;
|
||||||
|
|
||||||
let key = JSXAttributeName::Identifier(self.ctx.ast.jsx_identifier(SPAN, SOURCE.into()));
|
let key = JSXAttributeName::Identifier(
|
||||||
|
self.ctx.ast.alloc(self.ctx.ast.jsx_identifier(SPAN, SOURCE.into())),
|
||||||
|
);
|
||||||
let object = self.get_source_object();
|
let object = self.get_source_object();
|
||||||
let expr = self.ctx.ast.jsx_expression_container(SPAN, JSXExpression::Expression(object));
|
let expr = self.ctx.ast.jsx_expression_container(SPAN, JSXExpression::Expression(object));
|
||||||
let value = JSXAttributeValue::ExpressionContainer(expr);
|
let value = JSXAttributeValue::ExpressionContainer(expr);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue