@@ -7,11 +7,13 @@ use swc_core::{
7
7
ArrayLit , ArrayPat , ArrowExpr , AssignExpr , AssignPat , AssignTarget , AssignTargetPat , AwaitExpr ,
8
8
BinExpr , BlockStmt , BlockStmtOrExpr , CallExpr , Callee , CatchClause , Class , ClassExpr ,
9
9
ClassMember , CondExpr , DefaultDecl , DoWhileStmt , ExportDefaultDecl , Expr , ExprOrSpread ,
10
- ExprStmt , FnExpr , ForHead , ForInStmt , ForOfStmt , ForStmt , Function , GetterProp , Ident , IfStmt ,
11
- KeyValueProp , LabeledStmt , MemberExpr , MemberProp , MetaPropExpr , ModuleDecl , ModuleItem ,
12
- NewExpr , ObjectLit , ObjectPat , ObjectPatProp , OptCall , OptChainExpr , Param , Pat , Prop ,
13
- PropName , PropOrSpread , RestPat , ReturnStmt , SeqExpr , SetterProp , SimpleAssignTarget , Stmt ,
14
- SwitchCase , SwitchStmt , TaggedTpl , ThisExpr , ThrowStmt , Tpl , TryStmt , UnaryExpr , UnaryOp ,
10
+ ExprStmt , FnExpr , ForHead , ForInStmt , ForOfStmt , ForStmt , Function , GetterProp , Ident ,
11
+ IdentName , IfStmt , JSXAttr , JSXAttrOrSpread , JSXAttrValue , JSXElement , JSXElementChild ,
12
+ JSXElementName , JSXExpr , JSXExprContainer , JSXFragment , JSXMemberExpr , JSXNamespacedName ,
13
+ JSXObject , KeyValueProp , LabeledStmt , MemberExpr , MemberProp , MetaPropExpr , ModuleDecl ,
14
+ ModuleItem , NewExpr , ObjectLit , ObjectPat , ObjectPatProp , OptCall , OptChainExpr , Param , Pat ,
15
+ Prop , PropName , PropOrSpread , RestPat , ReturnStmt , SeqExpr , SetterProp , SimpleAssignTarget ,
16
+ Stmt , SwitchCase , SwitchStmt , TaggedTpl , ThisExpr , ThrowStmt , Tpl , TryStmt , UnaryExpr , UnaryOp ,
15
17
UpdateExpr , VarDeclOrExpr , WhileStmt , WithStmt , YieldExpr ,
16
18
} ,
17
19
} ;
@@ -431,12 +433,18 @@ impl JavascriptParser<'_> {
431
433
Expr :: Update ( expr) => self . walk_update_expression ( expr) ,
432
434
Expr :: Yield ( expr) => self . walk_yield_expression ( expr) ,
433
435
Expr :: SuperProp ( _) | Expr :: Lit ( _) | Expr :: PrivateName ( _) | Expr :: Invalid ( _) => ( ) ,
436
+ Expr :: JSXMember ( _) | Expr :: JSXNamespacedName ( _) | Expr :: JSXEmpty ( _) => {
437
+ self . ensure_jsx_enabled ( ) ;
438
+ }
439
+ Expr :: JSXElement ( element) => {
440
+ self . ensure_jsx_enabled ( ) ;
441
+ self . walk_jsx_element ( element) ;
442
+ }
443
+ Expr :: JSXFragment ( fragment) => {
444
+ self . ensure_jsx_enabled ( ) ;
445
+ self . walk_jsx_fragment ( fragment) ;
446
+ }
434
447
Expr :: Paren ( _)
435
- | Expr :: JSXMember ( _)
436
- | Expr :: JSXNamespacedName ( _)
437
- | Expr :: JSXEmpty ( _)
438
- | Expr :: JSXElement ( _)
439
- | Expr :: JSXFragment ( _)
440
448
| Expr :: TsTypeAssertion ( _)
441
449
| Expr :: TsConstAssertion ( _)
442
450
| Expr :: TsNonNull ( _)
@@ -516,6 +524,114 @@ impl JavascriptParser<'_> {
516
524
}
517
525
}
518
526
527
+ fn ensure_jsx_enabled ( & self ) {
528
+ if !self . javascript_options . jsx . unwrap_or_default ( ) {
529
+ unreachable ! ( ) ;
530
+ }
531
+ }
532
+
533
+ fn walk_jsx_element ( & mut self , element : & JSXElement ) {
534
+ self . walk_jsx_element_name ( & element. opening . name ) ;
535
+ if element. opening . type_args . is_some ( ) {
536
+ // JSX type arguments only exist in TSX; this walker assumes pure JSX input.
537
+ unreachable ! ( ) ;
538
+ }
539
+ for attr in & element. opening . attrs {
540
+ self . walk_jsx_attr_or_spread ( attr) ;
541
+ }
542
+ for child in & element. children {
543
+ self . walk_jsx_child ( child) ;
544
+ }
545
+ if let Some ( closing) = & element. closing {
546
+ self . walk_jsx_element_name ( & closing. name ) ;
547
+ }
548
+ }
549
+
550
+ fn walk_jsx_fragment ( & mut self , fragment : & JSXFragment ) {
551
+ for child in & fragment. children {
552
+ self . walk_jsx_child ( child) ;
553
+ }
554
+ }
555
+
556
+ fn walk_jsx_child ( & mut self , child : & JSXElementChild ) {
557
+ match child {
558
+ JSXElementChild :: JSXElement ( element) => self . walk_jsx_element ( element) ,
559
+ JSXElementChild :: JSXFragment ( fragment) => self . walk_jsx_fragment ( fragment) ,
560
+ JSXElementChild :: JSXExprContainer ( container) => self . walk_jsx_expr_container ( container) ,
561
+ JSXElementChild :: JSXSpreadChild ( spread) => self . walk_expression ( & spread. expr ) ,
562
+ JSXElementChild :: JSXText ( _) => ( ) ,
563
+ }
564
+ }
565
+
566
+ fn walk_jsx_expr_container ( & mut self , container : & JSXExprContainer ) {
567
+ match & container. expr {
568
+ JSXExpr :: Expr ( expr) => self . walk_expression ( expr) ,
569
+ JSXExpr :: JSXEmptyExpr ( _) => ( ) ,
570
+ }
571
+ }
572
+
573
+ fn walk_jsx_attr_or_spread ( & mut self , attr : & JSXAttrOrSpread ) {
574
+ match attr {
575
+ JSXAttrOrSpread :: JSXAttr ( attr) => self . walk_jsx_attr ( attr) ,
576
+ JSXAttrOrSpread :: SpreadElement ( spread) => self . walk_expression ( & spread. expr ) ,
577
+ }
578
+ }
579
+
580
+ fn walk_jsx_attr ( & mut self , attr : & JSXAttr ) {
581
+ if let Some ( value) = & attr. value {
582
+ self . walk_jsx_attr_value ( value) ;
583
+ }
584
+ }
585
+
586
+ fn walk_jsx_attr_value ( & mut self , value : & JSXAttrValue ) {
587
+ match value {
588
+ JSXAttrValue :: Lit ( _) => ( ) ,
589
+ JSXAttrValue :: JSXExprContainer ( container) => self . walk_jsx_expr_container ( container) ,
590
+ JSXAttrValue :: JSXElement ( element) => self . walk_jsx_element ( element) ,
591
+ JSXAttrValue :: JSXFragment ( fragment) => self . walk_jsx_fragment ( fragment) ,
592
+ }
593
+ }
594
+
595
+ fn walk_jsx_element_name ( & mut self , name : & JSXElementName ) {
596
+ match name {
597
+ JSXElementName :: Ident ( ident) => self . walk_identifier ( ident) ,
598
+ JSXElementName :: JSXMemberExpr ( member) => self . walk_jsx_member_expr ( member) ,
599
+ JSXElementName :: JSXNamespacedName ( namespaced) => self . walk_jsx_namespaced_name ( namespaced) ,
600
+ }
601
+ }
602
+
603
+ fn walk_jsx_member_expr ( & mut self , member : & JSXMemberExpr ) {
604
+ let member_expr = Self :: jsx_member_expr_to_member_expr ( member) ;
605
+ self . walk_member_expression ( & member_expr) ;
606
+ }
607
+
608
+ fn jsx_member_expr_to_member_expr ( member : & JSXMemberExpr ) -> MemberExpr {
609
+ MemberExpr {
610
+ span : member. span ,
611
+ obj : Box :: new ( Self :: jsx_object_to_expr ( & member. obj ) ) ,
612
+ prop : MemberProp :: Ident ( member. prop . clone ( ) ) ,
613
+ }
614
+ }
615
+
616
+ fn jsx_object_to_expr ( obj : & JSXObject ) -> Expr {
617
+ match obj {
618
+ JSXObject :: Ident ( ident) => Expr :: Ident ( ident. clone ( ) ) ,
619
+ JSXObject :: JSXMemberExpr ( member) => {
620
+ Expr :: Member ( Self :: jsx_member_expr_to_member_expr ( member) )
621
+ }
622
+ }
623
+ }
624
+
625
+ fn walk_jsx_namespaced_name ( & mut self , name : & JSXNamespacedName ) {
626
+ self . walk_ident_name ( & name. ns ) ;
627
+ self . walk_ident_name ( & name. name ) ;
628
+ }
629
+
630
+ fn walk_ident_name ( & mut self , name : & IdentName ) {
631
+ let ident: Ident = name. clone ( ) . into ( ) ;
632
+ self . walk_identifier ( & ident) ;
633
+ }
634
+
519
635
fn walk_object_expression ( & mut self , expr : & ObjectLit ) {
520
636
for prop in & expr. props {
521
637
self . walk_property_or_spread ( prop) ;
0 commit comments