Skip to content

Commit 2a70a6b

Browse files
authored
fix(es/typescript): Handle exported JSX binding name in TypeScript namespace (#8596)
**Related issue:** - Closes #8594
1 parent 190c4e2 commit 2a70a6b

File tree

6 files changed

+69
-3
lines changed

6 files changed

+69
-3
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"jsc": {
3+
"parser": {
4+
"syntax": "typescript",
5+
"tsx": true
6+
},
7+
"target": "es2015",
8+
"loose": false,
9+
"minify": {
10+
"compress": false,
11+
"mangle": false
12+
}
13+
},
14+
"module": {
15+
"type": "es6"
16+
},
17+
"minify": false,
18+
"isModule": true
19+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import * as React from 'react';
2+
3+
export namespace FooNs {
4+
export const Shared = () => 'I\'m shared component';
5+
export const Main = () => <Shared/>;
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import * as React from 'react';
2+
export var FooNs;
3+
(function(FooNs) {
4+
FooNs.Shared = ()=>'I\'m shared component';
5+
FooNs.Main = ()=>React.createElement(FooNs.Shared, null);
6+
})(FooNs || (FooNs = {}));

crates/swc_ecma_transforms_module/src/module_ref_rewriter.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ impl QueryRef for ImportQuery {
7171
None
7272
}
7373

74+
fn query_jsx(&self, _: &Ident) -> Option<JSXElementName> {
75+
// We do not need to handle JSX since there is no jsx preserve option in swc
76+
None
77+
}
78+
7479
fn should_fix_this(&self, ident: &Ident) -> bool {
7580
if self.helper_ctxt.iter().any(|ctxt| ctxt == &ident.span.ctxt) {
7681
return false;

crates/swc_ecma_transforms_typescript/src/transform.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,6 +1231,16 @@ impl QueryRef for ExportQuery {
12311231
self.query_ref(ident)
12321232
}
12331233

1234+
fn query_jsx(&self, ident: &Ident) -> Option<JSXElementName> {
1235+
self.export_id_list.contains(&ident.to_id()).then(|| {
1236+
JSXMemberExpr {
1237+
obj: JSXObject::Ident(self.namesapce_id.clone().into()),
1238+
prop: ident.clone(),
1239+
}
1240+
.into()
1241+
})
1242+
}
1243+
12341244
fn should_fix_this(&self, _: &Ident) -> bool {
12351245
// tsc does not care about `this` in namespace.
12361246
false

crates/swc_ecma_utils/src/lib.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3021,11 +3021,21 @@ impl VisitMut for IdentRenamer<'_> {
30213021
}
30223022

30233023
pub trait QueryRef {
3024-
fn query_ref(&self, ident: &Ident) -> Option<Expr>;
3025-
fn query_lhs(&self, ident: &Ident) -> Option<Expr>;
3024+
fn query_ref(&self, _ident: &Ident) -> Option<Expr> {
3025+
None
3026+
}
3027+
fn query_lhs(&self, _ident: &Ident) -> Option<Expr> {
3028+
None
3029+
}
3030+
/// ref used in JSX
3031+
fn query_jsx(&self, _ident: &Ident) -> Option<JSXElementName> {
3032+
None
3033+
}
30263034
/// when `foo()` is replaced with `bar.baz()`,
30273035
/// should `bar.baz` be indirect call?
3028-
fn should_fix_this(&self, ident: &Ident) -> bool;
3036+
fn should_fix_this(&self, _ident: &Ident) -> bool {
3037+
false
3038+
}
30293039
}
30303040

30313041
/// Replace `foo` with `bar` or `bar.baz`
@@ -3129,6 +3139,16 @@ where
31293139
*n = n.take().into_indirect()
31303140
}
31313141
}
3142+
3143+
fn visit_mut_jsx_element_name(&mut self, n: &mut JSXElementName) {
3144+
n.visit_mut_children_with(self);
3145+
3146+
if let JSXElementName::Ident(ident) = n {
3147+
if let Some(expr) = self.query.query_jsx(ident) {
3148+
*n = expr;
3149+
}
3150+
}
3151+
}
31323152
}
31333153

31343154
#[cfg(test)]

0 commit comments

Comments
 (0)