diff --git a/crates/oxc_syntax/src/scope.rs b/crates/oxc_syntax/src/scope.rs index d6b9e0f489604..637affb411dc6 100644 --- a/crates/oxc_syntax/src/scope.rs +++ b/crates/oxc_syntax/src/scope.rs @@ -12,7 +12,7 @@ export type ScopeId = number; "#; bitflags! { - #[derive(Debug, Clone, Copy)] + #[derive(Debug, Clone, Copy, PartialEq)] pub struct ScopeFlags: u16 { const StrictMode = 1 << 0; const Top = 1 << 1; @@ -42,6 +42,10 @@ impl ScopeFlags { self.contains(Self::StrictMode) } + pub fn is_block(&self) -> bool { + self.is_empty() || *self == Self::StrictMode + } + pub fn is_top(&self) -> bool { self.contains(Self::Top) } diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index 14bdd8e4c8cf0..54cbf7e3bf6bb 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -169,10 +169,10 @@ impl<'a> Traverse<'a> for Transformer<'a> { fn enter_jsx_opening_element( &mut self, elem: &mut JSXOpeningElement<'a>, - _ctx: &TraverseCtx<'a>, + ctx: &TraverseCtx<'a>, ) { self.x0_typescript.transform_jsx_opening_element(elem); - self.x1_react.transform_jsx_opening_element(elem); + self.x1_react.transform_jsx_opening_element(elem, ctx); self.x3_es2015.transform_jsx_opening_element(elem); } diff --git a/crates/oxc_transformer/src/react/mod.rs b/crates/oxc_transformer/src/react/mod.rs index 25cde34ed701d..fd05bc34952d5 100644 --- a/crates/oxc_transformer/src/react/mod.rs +++ b/crates/oxc_transformer/src/react/mod.rs @@ -8,7 +8,7 @@ mod utils; use std::rc::Rc; use oxc_ast::ast::*; -use oxc_traverse::TraverseCtx; +use oxc_traverse::{Ancestor, FinderRet, TraverseCtx}; use crate::context::Ctx; @@ -78,9 +78,31 @@ impl<'a> React<'a> { } } - pub fn transform_jsx_opening_element(&mut self, elem: &mut JSXOpeningElement<'a>) { + pub fn transform_jsx_opening_element( + &mut self, + elem: &mut JSXOpeningElement<'a>, + ctx: &TraverseCtx<'a>, + ) { if self.options.is_jsx_self_plugin_enabled() { - self.jsx.jsx_self.transform_jsx_opening_element(elem); + let is_constructor = ctx + .find_scope(|scope| { + if scope.is_block() || scope.is_arrow() { + return FinderRet::Continue; + } + FinderRet::Found(scope.is_constructor()) + }) + .unwrap_or(false); + if !is_constructor + // no super class + || ctx + .find_ancestor(|ancestor| match ancestor { + Ancestor::ClassBody(class) => FinderRet::Found(class.super_class().is_none()), + _ => FinderRet::Continue, + }) + .unwrap_or(true) + { + self.jsx.jsx_self.transform_jsx_opening_element(elem); + } } if self.options.is_jsx_source_plugin_enabled() { self.jsx.jsx_source.transform_jsx_opening_element(elem); diff --git a/tasks/transform_conformance/babel.snap.md b/tasks/transform_conformance/babel.snap.md index e855bc5053ee4..fead6a775b13c 100644 --- a/tasks/transform_conformance/babel.snap.md +++ b/tasks/transform_conformance/babel.snap.md @@ -1,10 +1,11 @@ commit: 4bd1b2c2 -Passed: 308/362 +Passed: 309/362 # All Passed: * babel-preset-react * babel-plugin-transform-react-display-name +* babel-plugin-transform-react-jsx-self * babel-plugin-transform-react-jsx-source @@ -65,9 +66,6 @@ Passed: 308/362 * autoImport/complicated-scope-module/input.js * react-automatic/should-throw-when-filter-is-specified/input.js -# babel-plugin-transform-react-jsx-self (2/3) -* react-source/disable-with-super/input.js - # babel-plugin-transform-react-jsx-development (8/12) * cross-platform/self-inside-arrow/input.mjs * cross-platform/source-and-self-defined/input.js