diff --git a/crates/oxc_ast/src/ast/jsx.rs b/crates/oxc_ast/src/ast/jsx.rs
index d41e78c23..96eac3f4c 100644
--- a/crates/oxc_ast/src/ast/jsx.rs
+++ b/crates/oxc_ast/src/ast/jsx.rs
@@ -83,7 +83,7 @@ pub struct JSXClosingFragment {
#[cfg_attr(feature = "serialize", serde(untagged))]
pub enum JSXElementName<'a> {
/// ``
- Identifier(JSXIdentifier<'a>),
+ Identifier(Box<'a, JSXIdentifier<'a>>),
/// ``
NamespacedName(Box<'a, JSXNamespacedName<'a>>),
/// ``
@@ -131,7 +131,7 @@ impl<'a> JSXMemberExpression<'a> {
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(untagged))]
pub enum JSXMemberExpressionObject<'a> {
- Identifier(JSXIdentifier<'a>),
+ Identifier(Box<'a, JSXIdentifier<'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", serde(untagged))]
pub enum JSXAttributeName<'a> {
- Identifier(JSXIdentifier<'a>),
+ Identifier(Box<'a, JSXIdentifier<'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", serde(untagged))]
pub enum JSXAttributeValue<'a> {
- StringLiteral(StringLiteral<'a>),
- ExpressionContainer(JSXExpressionContainer<'a>),
+ StringLiteral(Box<'a, StringLiteral<'a>>),
+ ExpressionContainer(Box<'a, JSXExpressionContainer<'a>>),
Element(Box<'a, JSXElement<'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", serde(untagged))]
pub enum JSXChild<'a> {
- Text(JSXText<'a>),
+ Text(Box<'a, JSXText<'a>>),
Element(Box<'a, JSXElement<'a>>),
Fragment(Box<'a, JSXFragment<'a>>),
- ExpressionContainer(JSXExpressionContainer<'a>),
- Spread(JSXSpreadChild<'a>),
+ ExpressionContainer(Box<'a, JSXExpressionContainer<'a>>),
+ Spread(Box<'a, JSXSpreadChild<'a>>),
}
#[derive(Debug, Hash)]
diff --git a/crates/oxc_ast/src/ast_builder.rs b/crates/oxc_ast/src/ast_builder.rs
index 4c52578eb..d59c1aa84 100644
--- a/crates/oxc_ast/src/ast_builder.rs
+++ b/crates/oxc_ast/src/ast_builder.rs
@@ -1302,12 +1302,16 @@ impl<'a> AstBuilder<'a> {
&self,
span: Span,
expression: JSXExpression<'a>,
- ) -> JSXExpressionContainer<'a> {
- JSXExpressionContainer { span, expression }
+ ) -> Box<'a, JSXExpressionContainer<'a>> {
+ self.alloc(JSXExpressionContainer { span, expression })
}
- pub fn jsx_spread_child(&self, span: Span, expression: Expression<'a>) -> JSXSpreadChild<'a> {
- JSXSpreadChild { span, expression }
+ pub fn jsx_spread_child(
+ &self,
+ span: Span,
+ expression: Expression<'a>,
+ ) -> Box<'a, JSXSpreadChild<'a>> {
+ self.alloc(JSXSpreadChild { span, expression })
}
pub fn jsx_empty_expression(&self, span: Span) -> JSXEmptyExpression {
@@ -1335,8 +1339,8 @@ impl<'a> AstBuilder<'a> {
JSXIdentifier { span, name }
}
- pub fn jsx_text(&self, span: Span, value: Atom<'a>) -> JSXText<'a> {
- JSXText { span, value }
+ pub fn jsx_text(&self, span: Span, value: Atom<'a>) -> Box<'a, JSXText<'a>> {
+ self.alloc(JSXText { span, value })
}
/* ---------- TypeScript ---------- */
diff --git a/crates/oxc_linter/src/rules/jsx_a11y/alt_text.rs b/crates/oxc_linter/src/rules/jsx_a11y/alt_text.rs
index ce33a3c26..0c8a06719 100644
--- a/crates/oxc_linter/src/rules/jsx_a11y/alt_text.rs
+++ b/crates/oxc_linter/src/rules/jsx_a11y/alt_text.rs
@@ -1,8 +1,5 @@
use oxc_ast::{
- ast::{
- JSXAttributeItem, JSXAttributeValue, JSXElement, JSXExpression, JSXExpressionContainer,
- JSXOpeningElement,
- },
+ ast::{JSXAttributeItem, JSXAttributeValue, JSXElement, JSXExpression, JSXOpeningElement},
AstKind,
};
use oxc_diagnostics::{
@@ -212,10 +209,13 @@ impl Rule for AltText {
fn is_valid_alt_prop(item: &JSXAttributeItem<'_>) -> bool {
match get_prop_value(item) {
None => false,
- Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expr),
- ..
- })) => !expr.is_null_or_undefined(),
+ Some(JSXAttributeValue::ExpressionContainer(container)) => {
+ if let JSXExpression::Expression(expr) = &container.expression {
+ !expr.is_null_or_undefined()
+ } else {
+ true
+ }
+ }
_ => true,
}
}
@@ -229,10 +229,13 @@ fn aria_label_has_value<'a>(item: &'a JSXAttributeItem<'a>) -> bool {
match get_prop_value(item) {
None => false,
Some(JSXAttributeValue::StringLiteral(s)) if s.value.is_empty() => false,
- Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expr),
- ..
- })) => !expr.is_undefined(),
+ Some(JSXAttributeValue::ExpressionContainer(container)) => {
+ if let JSXExpression::Expression(expr) = &container.expression {
+ !expr.is_undefined()
+ } else {
+ true
+ }
+ }
_ => true,
}
}
diff --git a/crates/oxc_linter/src/rules/jsx_a11y/aria_role.rs b/crates/oxc_linter/src/rules/jsx_a11y/aria_role.rs
index 0e1bba5fc..f21d2c38b 100644
--- a/crates/oxc_linter/src/rules/jsx_a11y/aria_role.rs
+++ b/crates/oxc_linter/src/rules/jsx_a11y/aria_role.rs
@@ -1,5 +1,5 @@
use oxc_ast::{
- ast::{JSXAttributeValue, JSXExpression, JSXExpressionContainer},
+ ast::{JSXAttributeValue, JSXExpression},
AstKind,
};
use oxc_diagnostics::{
@@ -134,12 +134,11 @@ impl Rule for AriaRole {
};
match get_prop_value(aria_role) {
- Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expr),
- ..
- })) => {
- if expr.is_undefined() || expr.is_null() {
- ctx.diagnostic(AriaRoleDiagnostic(attr.span, String::new()));
+ Some(JSXAttributeValue::ExpressionContainer(container)) => {
+ if let JSXExpression::Expression(expr) = &container.expression {
+ if expr.is_undefined() || expr.is_null() {
+ ctx.diagnostic(AriaRoleDiagnostic(attr.span, String::new()));
+ }
}
}
Some(JSXAttributeValue::StringLiteral(str)) => {
diff --git a/crates/oxc_linter/src/rules/jsx_a11y/html_has_lang.rs b/crates/oxc_linter/src/rules/jsx_a11y/html_has_lang.rs
index 618dd4992..20396ea7c 100644
--- a/crates/oxc_linter/src/rules/jsx_a11y/html_has_lang.rs
+++ b/crates/oxc_linter/src/rules/jsx_a11y/html_has_lang.rs
@@ -1,7 +1,5 @@
use oxc_ast::{
- ast::{
- JSXAttributeItem, JSXAttributeValue, JSXElementName, JSXExpression, JSXExpressionContainer,
- },
+ ast::{JSXAttributeItem, JSXAttributeValue, JSXElementName, JSXExpression},
AstKind,
};
use oxc_diagnostics::{
@@ -87,10 +85,13 @@ impl Rule for HtmlHasLang {
fn is_valid_lang_prop(item: &JSXAttributeItem) -> bool {
match get_prop_value(item) {
- Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expr),
- ..
- })) => !expr.is_undefined(),
+ Some(JSXAttributeValue::ExpressionContainer(container)) => {
+ if let JSXExpression::Expression(expr) = &container.expression {
+ !expr.is_undefined()
+ } else {
+ true
+ }
+ }
Some(JSXAttributeValue::StringLiteral(str)) => !str.value.as_str().is_empty(),
_ => true,
}
diff --git a/crates/oxc_linter/src/rules/jsx_a11y/iframe_has_title.rs b/crates/oxc_linter/src/rules/jsx_a11y/iframe_has_title.rs
index 2c3e9eec7..158d49c9e 100644
--- a/crates/oxc_linter/src/rules/jsx_a11y/iframe_has_title.rs
+++ b/crates/oxc_linter/src/rules/jsx_a11y/iframe_has_title.rs
@@ -1,5 +1,5 @@
use oxc_ast::{
- ast::{Expression, JSXAttributeValue, JSXElementName, JSXExpression, JSXExpressionContainer},
+ ast::{Expression, JSXAttributeValue, JSXElementName, JSXExpression},
AstKind,
};
use oxc_diagnostics::{
@@ -88,28 +88,27 @@ impl Rule for IframeHasTitle {
return;
}
}
- Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expr),
- ..
- })) => {
- if expr.is_string_literal() {
- if let Expression::StringLiteral(str) = expr {
- if !str.value.as_str().is_empty() {
- return;
+ Some(JSXAttributeValue::ExpressionContainer(container)) => {
+ if let JSXExpression::Expression(expr) = &container.expression {
+ if expr.is_string_literal() {
+ if let Expression::StringLiteral(str) = expr {
+ 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() {
- return;
+ if expr.is_identifier_reference() & !expr.is_undefined() {
+ return;
+ }
}
}
_ => {}
diff --git a/crates/oxc_linter/src/rules/jsx_a11y/img_redundant_alt.rs b/crates/oxc_linter/src/rules/jsx_a11y/img_redundant_alt.rs
index 7c52ebe5b..262b5c1d6 100644
--- a/crates/oxc_linter/src/rules/jsx_a11y/img_redundant_alt.rs
+++ b/crates/oxc_linter/src/rules/jsx_a11y/img_redundant_alt.rs
@@ -1,10 +1,7 @@
use regex::Regex;
use oxc_ast::{
- ast::{
- Expression, JSXAttributeItem, JSXAttributeName, JSXAttributeValue, JSXExpression,
- JSXExpressionContainer,
- },
+ ast::{Expression, JSXAttributeItem, JSXAttributeName, JSXAttributeValue, JSXExpression},
AstKind,
};
use oxc_diagnostics::{
@@ -149,18 +146,15 @@ impl Rule for ImgRedundantAlt {
ctx.diagnostic(ImgRedundantAltDiagnostic(alt_attribute_name_span));
}
}
- JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expression),
- ..
- }) => match expression {
- Expression::StringLiteral(lit) => {
+ JSXAttributeValue::ExpressionContainer(container) => match &container.expression {
+ JSXExpression::Expression(Expression::StringLiteral(lit)) => {
let alt_text = lit.value.as_str();
if is_redundant_alt_text(alt_text, &self.redundant_words) {
ctx.diagnostic(ImgRedundantAltDiagnostic(alt_attribute_name_span));
}
}
- Expression::TemplateLiteral(lit) => {
+ JSXExpression::Expression(Expression::TemplateLiteral(lit)) => {
for quasi in &lit.quasis {
let alt_text = quasi.value.raw.as_str();
diff --git a/crates/oxc_linter/src/rules/jsx_a11y/lang.rs b/crates/oxc_linter/src/rules/jsx_a11y/lang.rs
index d62665fd7..c36775c73 100644
--- a/crates/oxc_linter/src/rules/jsx_a11y/lang.rs
+++ b/crates/oxc_linter/src/rules/jsx_a11y/lang.rs
@@ -1,8 +1,6 @@
use language_tags::LanguageTag;
use oxc_ast::{
- ast::{
- JSXAttributeItem, JSXAttributeValue, JSXElementName, JSXExpression, JSXExpressionContainer,
- },
+ ast::{JSXAttributeItem, JSXAttributeValue, JSXElementName, JSXExpression},
AstKind,
};
use oxc_diagnostics::{
@@ -94,10 +92,13 @@ impl Rule for Lang {
fn is_valid_lang_prop(item: &JSXAttributeItem) -> bool {
match get_prop_value(item) {
- Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expr),
- ..
- })) => !expr.is_undefined(),
+ Some(JSXAttributeValue::ExpressionContainer(container)) => {
+ if let JSXExpression::Expression(expr) = &container.expression {
+ !expr.is_undefined()
+ } else {
+ true
+ }
+ }
Some(JSXAttributeValue::StringLiteral(str)) => {
let language_tag = LanguageTag::parse(str.value.as_str()).unwrap();
language_tag.is_valid()
diff --git a/crates/oxc_linter/src/rules/jsx_a11y/mouse_events_have_key_events.rs b/crates/oxc_linter/src/rules/jsx_a11y/mouse_events_have_key_events.rs
index 3ae4b4826..dc1f8cf09 100644
--- a/crates/oxc_linter/src/rules/jsx_a11y/mouse_events_have_key_events.rs
+++ b/crates/oxc_linter/src/rules/jsx_a11y/mouse_events_have_key_events.rs
@@ -1,5 +1,5 @@
use oxc_ast::{
- ast::{JSXAttributeValue, JSXExpression, JSXExpressionContainer},
+ ast::{JSXAttributeValue, JSXExpression},
AstKind,
};
use oxc_diagnostics::{
@@ -119,15 +119,14 @@ impl Rule for MouseEventsHaveKeyEvents {
}
match has_jsx_prop(jsx_opening_el, "onFocus").and_then(get_prop_value) {
- Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expr),
- ..
- })) => {
- if expr.is_undefined() {
- ctx.diagnostic(MouseEventsHaveKeyEventsDiagnostic::MissOnFocus(
- jsx_attr.span(),
- String::from(handler),
- ));
+ Some(JSXAttributeValue::ExpressionContainer(container)) => {
+ if let JSXExpression::Expression(expr) = &container.expression {
+ if expr.is_undefined() {
+ ctx.diagnostic(MouseEventsHaveKeyEventsDiagnostic::MissOnFocus(
+ jsx_attr.span(),
+ String::from(handler),
+ ));
+ }
}
}
None => {
@@ -150,15 +149,14 @@ impl Rule for MouseEventsHaveKeyEvents {
}
match has_jsx_prop(jsx_opening_el, "onBlur").and_then(get_prop_value) {
- Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expr),
- ..
- })) => {
- if expr.is_undefined() {
- ctx.diagnostic(MouseEventsHaveKeyEventsDiagnostic::MissOnBlur(
- jsx_attr.span(),
- String::from(handler),
- ));
+ Some(JSXAttributeValue::ExpressionContainer(container)) => {
+ if let JSXExpression::Expression(expr) = &container.expression {
+ if expr.is_undefined() {
+ ctx.diagnostic(MouseEventsHaveKeyEventsDiagnostic::MissOnBlur(
+ jsx_attr.span(),
+ String::from(handler),
+ ));
+ }
}
}
None => {
diff --git a/crates/oxc_linter/src/rules/jsx_a11y/no_access_key.rs b/crates/oxc_linter/src/rules/jsx_a11y/no_access_key.rs
index 5130354ec..75d99a7b7 100644
--- a/crates/oxc_linter/src/rules/jsx_a11y/no_access_key.rs
+++ b/crates/oxc_linter/src/rules/jsx_a11y/no_access_key.rs
@@ -1,5 +1,5 @@
use oxc_ast::{
- ast::{JSXAttributeItem, JSXAttributeValue, JSXExpression, JSXExpressionContainer},
+ ast::{JSXAttributeItem, JSXAttributeValue, JSXExpression},
AstKind,
};
use oxc_diagnostics::{
@@ -48,14 +48,13 @@ impl Rule for NoAccessKey {
Some(JSXAttributeValue::StringLiteral(_)) => {
ctx.diagnostic(NoAccessKeyDiagnostic(attr.span));
}
- Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expr),
- ..
- })) => {
- if expr.is_identifier_reference() & expr.is_undefined() {
- return;
+ Some(JSXAttributeValue::ExpressionContainer(container)) => {
+ if let JSXExpression::Expression(expr) = &container.expression {
+ if expr.is_identifier_reference() & expr.is_undefined() {
+ return;
+ }
+ ctx.diagnostic(NoAccessKeyDiagnostic(attr.span));
}
- ctx.diagnostic(NoAccessKeyDiagnostic(attr.span));
}
_ => {}
}
diff --git a/crates/oxc_linter/src/rules/nextjs/no_before_interactive_script_outside_document.rs b/crates/oxc_linter/src/rules/nextjs/no_before_interactive_script_outside_document.rs
index 04c8c95fb..333f5271b 100644
--- a/crates/oxc_linter/src/rules/nextjs/no_before_interactive_script_outside_document.rs
+++ b/crates/oxc_linter/src/rules/nextjs/no_before_interactive_script_outside_document.rs
@@ -1,5 +1,5 @@
use oxc_ast::{
- ast::{JSXAttributeItem, JSXAttributeName, JSXAttributeValue, JSXElementName, JSXIdentifier},
+ ast::{JSXAttributeItem, JSXAttributeName, JSXAttributeValue, JSXElementName},
AstKind,
};
use oxc_diagnostics::{
@@ -48,8 +48,9 @@ impl Rule for NoBeforeInteractiveScriptOutsideDocument {
if is_in_app_dir(file_path) {
return;
}
- let JSXElementName::Identifier(JSXIdentifier { name: tag_name, .. }) = &jsx_el.name
- else {
+ let tag_name = if let JSXElementName::Identifier(ident) = &jsx_el.name {
+ &ident.name
+ } else {
return;
};
if jsx_el.attributes.len() == 0 {
diff --git a/crates/oxc_linter/src/rules/nextjs/no_unwanted_polyfillio.rs b/crates/oxc_linter/src/rules/nextjs/no_unwanted_polyfillio.rs
index 235ac6233..fb11ffefd 100644
--- a/crates/oxc_linter/src/rules/nextjs/no_unwanted_polyfillio.rs
+++ b/crates/oxc_linter/src/rules/nextjs/no_unwanted_polyfillio.rs
@@ -1,5 +1,5 @@
use oxc_ast::{
- ast::{JSXAttributeItem, JSXAttributeName, JSXAttributeValue, JSXElementName, JSXIdentifier},
+ ast::{JSXAttributeItem, JSXAttributeName, JSXAttributeValue, JSXElementName},
AstKind,
};
use oxc_diagnostics::{
@@ -111,8 +111,9 @@ const NEXT_POLYFILLED_FEATURES: Set<&'static str> = phf_set! {
impl Rule for NoUnwantedPolyfillio {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
if let AstKind::JSXOpeningElement(jsx_el) = node.kind() {
- let JSXElementName::Identifier(JSXIdentifier { name: tag_name, .. }) = &jsx_el.name
- else {
+ let tag_name = if let JSXElementName::Identifier(ident) = &jsx_el.name {
+ &ident.name
+ } else {
return;
};
diff --git a/crates/oxc_linter/src/rules/react/button_has_type.rs b/crates/oxc_linter/src/rules/react/button_has_type.rs
index 637700eef..cf4915cd7 100644
--- a/crates/oxc_linter/src/rules/react/button_has_type.rs
+++ b/crates/oxc_linter/src/rules/react/button_has_type.rs
@@ -1,7 +1,7 @@
use oxc_ast::{
ast::{
Argument, Expression, JSXAttributeItem, JSXAttributeValue, JSXElementName, JSXExpression,
- JSXExpressionContainer, ObjectPropertyKind,
+ ObjectPropertyKind,
},
AstKind,
};
@@ -163,10 +163,13 @@ impl Rule for ButtonHasType {
impl ButtonHasType {
fn is_valid_button_type_prop(&self, item: &JSXAttributeItem) -> bool {
match get_prop_value(item) {
- Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expr),
- ..
- })) => self.is_valid_button_type_prop_expression(expr),
+ Some(JSXAttributeValue::ExpressionContainer(container)) => {
+ if let JSXExpression::Expression(expr) = &container.expression {
+ self.is_valid_button_type_prop_expression(expr)
+ } else {
+ false
+ }
+ }
Some(JSXAttributeValue::StringLiteral(str)) => {
self.is_valid_button_type_prop_string_literal(str.value.as_str())
}
diff --git a/crates/oxc_linter/src/rules/react_perf/jsx_no_jsx_as_prop.rs b/crates/oxc_linter/src/rules/react_perf/jsx_no_jsx_as_prop.rs
index d6c8a72c4..fece8ae75 100644
--- a/crates/oxc_linter/src/rules/react_perf/jsx_no_jsx_as_prop.rs
+++ b/crates/oxc_linter/src/rules/react_perf/jsx_no_jsx_as_prop.rs
@@ -1,5 +1,5 @@
use oxc_ast::{
- ast::{Expression, JSXAttributeValue, JSXElement, JSXExpression, JSXExpressionContainer},
+ ast::{Expression, JSXAttributeValue, JSXElement, JSXExpression},
AstKind,
};
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 {
match get_prop_value(item) {
None => return,
- Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expr),
- ..
- })) => {
- if let Some(span) = check_expression(expr) {
- ctx.diagnostic(JsxNoJsxAsPropDiagnostic(span));
+ Some(JSXAttributeValue::ExpressionContainer(container)) => {
+ if let JSXExpression::Expression(expr) = &container.expression {
+ if let Some(span) = check_expression(expr) {
+ ctx.diagnostic(JsxNoJsxAsPropDiagnostic(span));
+ }
}
}
_ => {}
diff --git a/crates/oxc_linter/src/rules/react_perf/jsx_no_new_array_as_prop.rs b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_array_as_prop.rs
index 39b8ec800..a3671b241 100644
--- a/crates/oxc_linter/src/rules/react_perf/jsx_no_new_array_as_prop.rs
+++ b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_array_as_prop.rs
@@ -1,5 +1,5 @@
use oxc_ast::{
- ast::{Expression, JSXAttributeValue, JSXElement, JSXExpression, JSXExpressionContainer},
+ ast::{Expression, JSXAttributeValue, JSXElement, JSXExpression},
AstKind,
};
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 {
match get_prop_value(item) {
None => return,
- Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expr),
- ..
- })) => {
- if let Some(span) = check_expression(expr) {
- ctx.diagnostic(JsxNoNewArrayAsPropDiagnostic(span));
+ Some(JSXAttributeValue::ExpressionContainer(container)) => {
+ if let JSXExpression::Expression(expr) = &container.expression {
+ if let Some(span) = check_expression(expr) {
+ ctx.diagnostic(JsxNoNewArrayAsPropDiagnostic(span));
+ }
}
}
_ => {}
diff --git a/crates/oxc_linter/src/rules/react_perf/jsx_no_new_function_as_prop.rs b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_function_as_prop.rs
index add9a7ae8..825948098 100644
--- a/crates/oxc_linter/src/rules/react_perf/jsx_no_new_function_as_prop.rs
+++ b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_function_as_prop.rs
@@ -1,8 +1,5 @@
use oxc_ast::{
- ast::{
- Expression, JSXAttributeValue, JSXElement, JSXExpression, JSXExpressionContainer,
- MemberExpression,
- },
+ ast::{Expression, JSXAttributeValue, JSXElement, JSXExpression, MemberExpression},
AstKind,
};
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 {
match get_prop_value(item) {
None => return,
- Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expr),
- ..
- })) => {
- if let Some(span) = check_expression(expr) {
- ctx.diagnostic(JsxNoNewFunctionAsPropDiagnostic(span));
+ Some(JSXAttributeValue::ExpressionContainer(container)) => {
+ if let JSXExpression::Expression(expr) = &container.expression {
+ if let Some(span) = check_expression(expr) {
+ ctx.diagnostic(JsxNoNewFunctionAsPropDiagnostic(span));
+ }
}
}
_ => {}
diff --git a/crates/oxc_linter/src/rules/react_perf/jsx_no_new_object_as_prop.rs b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_object_as_prop.rs
index 376562a05..f7985ade1 100644
--- a/crates/oxc_linter/src/rules/react_perf/jsx_no_new_object_as_prop.rs
+++ b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_object_as_prop.rs
@@ -1,5 +1,5 @@
use oxc_ast::{
- ast::{Expression, JSXAttributeValue, JSXElement, JSXExpression, JSXExpressionContainer},
+ ast::{Expression, JSXAttributeValue, JSXElement, JSXExpression},
AstKind,
};
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 {
match get_prop_value(item) {
None => return,
- Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expr),
- ..
- })) => {
- if let Some(span) = check_expression(expr) {
- ctx.diagnostic(JsxNoNewObjectAsPropDiagnostic(span));
+ Some(JSXAttributeValue::ExpressionContainer(container)) => {
+ if let JSXExpression::Expression(expr) = &container.expression {
+ if let Some(span) = check_expression(expr) {
+ ctx.diagnostic(JsxNoNewObjectAsPropDiagnostic(span));
+ }
}
}
_ => {}
diff --git a/crates/oxc_linter/src/utils/react.rs b/crates/oxc_linter/src/utils/react.rs
index f73975a1a..d92b6c468 100644
--- a/crates/oxc_linter/src/utils/react.rs
+++ b/crates/oxc_linter/src/utils/react.rs
@@ -1,8 +1,7 @@
use oxc_ast::{
ast::{
CallExpression, Expression, JSXAttributeItem, JSXAttributeName, JSXAttributeValue,
- JSXChild, JSXElement, JSXElementName, JSXExpression, JSXExpressionContainer,
- JSXOpeningElement,
+ JSXChild, JSXElement, JSXElementName, JSXExpression, JSXOpeningElement,
},
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) {
None => true,
Some(JSXAttributeValue::StringLiteral(s)) if s.value == "true" => true,
- Some(JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expr),
- ..
- })) => expr.get_boolean_value().unwrap_or(false),
+ Some(JSXAttributeValue::ExpressionContainer(container)) => {
+ if let JSXExpression::Expression(expr) = &container.expression {
+ expr.get_boolean_value().unwrap_or(false)
+ } else {
+ false
+ }
+ }
_ => false,
})
}
@@ -107,10 +109,13 @@ pub fn object_has_accessible_child(ctx: &LintContext, node: &JSXElement<'_>) ->
node.children.iter().any(|child| match child {
JSXChild::Text(text) => !text.value.is_empty(),
JSXChild::Element(el) => !is_hidden_from_screen_reader(ctx, &el.opening_element),
- JSXChild::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expr),
- ..
- }) => !expr.is_undefined() && !expr.is_null(),
+ JSXChild::ExpressionContainer(container) => {
+ if let JSXExpression::Expression(expr) = &container.expression {
+ !expr.is_undefined() && !expr.is_null()
+ } else {
+ false
+ }
+ }
_ => false,
}) || has_jsx_prop_lowercase(&node.opening_element, "dangerouslySetInnerHTML").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 {
match value {
JSXAttributeValue::StringLiteral(str) => str.value.parse().or(Err(())),
- JSXAttributeValue::ExpressionContainer(JSXExpressionContainer {
- expression: JSXExpression::Expression(expression),
- ..
- }) => match expression {
- Expression::StringLiteral(str) => str.value.parse().or(Err(())),
- Expression::TemplateLiteral(tmpl) => {
+ JSXAttributeValue::ExpressionContainer(container) => match &container.expression {
+ JSXExpression::Expression(Expression::StringLiteral(str)) => {
+ str.value.parse().or(Err(()))
+ }
+ JSXExpression::Expression(Expression::TemplateLiteral(tmpl)) => {
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(()),
diff --git a/crates/oxc_parser/src/jsx/mod.rs b/crates/oxc_parser/src/jsx/mod.rs
index 33fe6de56..f7b2ee65b 100644
--- a/crates/oxc_parser/src/jsx/mod.rs
+++ b/crates/oxc_parser/src/jsx/mod.rs
@@ -144,7 +144,7 @@ impl<'a> ParserImpl<'a> {
.map(JSXElementName::MemberExpression);
}
- Ok(JSXElementName::Identifier(identifier))
+ Ok(JSXElementName::Identifier(self.ast.alloc(identifier)))
}
/// `JSXMemberExpression` :
@@ -156,7 +156,7 @@ impl<'a> ParserImpl<'a> {
object: JSXIdentifier<'a>,
) -> Result>> {
let mut span = span;
- let mut object = JSXMemberExpressionObject::Identifier(object);
+ let mut object = JSXMemberExpressionObject::Identifier(self.ast.alloc(object));
let mut property = None;
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)
}
// {expr}
- Kind::LCurly => self
- .parse_jsx_expression_container(/* is_jsx_child */ true)
- .map(JSXChild::ExpressionContainer)
- .map(Some),
+ Kind::LCurly => {
+ self.parse_jsx_expression_container(/* is_jsx_child */ true)
+ .map(JSXChild::ExpressionContainer)
+ .map(Some)
+ }
// text
Kind::JSXText => Ok(Some(JSXChild::Text(self.parse_jsx_text()))),
_ => Err(self.unexpected()),
@@ -228,7 +229,7 @@ impl<'a> ParserImpl<'a> {
fn parse_jsx_expression_container(
&mut self,
in_jsx_child: bool,
- ) -> Result> {
+ ) -> Result>> {
let span = self.start_span();
self.bump_any(); // bump `{`
@@ -269,7 +270,7 @@ impl<'a> ParserImpl<'a> {
/// `JSXChildExpression` :
/// { ... `AssignmentExpression` }
- fn parse_jsx_spread_child(&mut self) -> Result> {
+ fn parse_jsx_spread_child(&mut self) -> Result>> {
let span = self.start_span();
self.bump_any(); // bump `{`
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> {
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 => {
let expr = self.parse_jsx_expression_container(/* is_jsx_child */ false)?;
Ok(JSXAttributeValue::ExpressionContainer(expr))
@@ -374,7 +377,7 @@ impl<'a> ParserImpl<'a> {
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 value = Atom::from(self.cur_string());
self.bump_any();
diff --git a/crates/oxc_transformer/src/react/jsx_self/mod.rs b/crates/oxc_transformer/src/react/jsx_self/mod.rs
index 1e4385c1e..925e226db 100644
--- a/crates/oxc_transformer/src/react/jsx_self/mod.rs
+++ b/crates/oxc_transformer/src/react/jsx_self/mod.rs
@@ -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 jsx_expr = JSXExpression::Expression(self.ctx.ast.this_expression(SPAN));
let container = self.ctx.ast.jsx_expression_container(SPAN, jsx_expr);
diff --git a/crates/oxc_transformer/src/react/jsx_source/mod.rs b/crates/oxc_transformer/src/react/jsx_source/mod.rs
index 038387f56..3b9c01407 100644
--- a/crates/oxc_transformer/src/react/jsx_source/mod.rs
+++ b/crates/oxc_transformer/src/react/jsx_source/mod.rs
@@ -80,7 +80,9 @@ impl<'a> ReactJsxSource<'a> {
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 expr = self.ctx.ast.jsx_expression_container(SPAN, JSXExpression::Expression(object));
let value = JSXAttributeValue::ExpressionContainer(expr);