@@ -561,6 +561,17 @@ impl Visit for TsStrip {
561561 }
562562
563563 ' type_params: {
564+ // ```TypeScript
565+ // let f = async <
566+ // T
567+ // >(v: T) => v;
568+ // ```
569+
570+ // ```TypeScript
571+ // let f = async (
572+ //
573+ // v ) => v;
574+ // ```
564575 if let Some ( tp) = & n. type_params {
565576 self . add_replacement ( tp. span ) ;
566577
@@ -673,7 +684,12 @@ impl Visit for TsStrip {
673684 return ;
674685 }
675686
676- self . strip_class_modifier ( n. span . lo , n. key . span_lo ( ) ) ;
687+ // TODO(AST): constructor can not be optional
688+ debug_assert ! ( !n. is_optional) ;
689+
690+ if n. accessibility . is_some ( ) {
691+ self . strip_class_modifier ( n. span . lo , n. key . span_lo ( ) ) ;
692+ }
677693
678694 n. visit_children_with ( self ) ;
679695 }
@@ -684,20 +700,49 @@ impl Visit for TsStrip {
684700 return ;
685701 }
686702
703+ let has_modifier = n. is_override || n. accessibility . is_some ( ) ;
704+
687705 // @foo public m(): void {}
688706 let start_pos = n
689707 . function
690708 . decorators
691709 . last ( )
692710 . map_or ( n. span . lo , |d| d. span . hi ) ;
693711
694- self . strip_class_modifier ( start_pos, n. key . span_lo ( ) ) ;
712+ if has_modifier {
713+ self . strip_class_modifier ( start_pos, n. key . span_lo ( ) ) ;
714+ }
695715
696716 if n. is_optional {
697717 let mark_index = self . get_next_token_index ( n. key . span_hi ( ) ) ;
698718 self . strip_optional_mark ( mark_index) ;
699719 }
700720
721+ // It's dangerous to strip TypeScript modifiers if the key is computed, a
722+ // generator, or `in`/`instanceof` keyword. However, it is safe to do so
723+ // if the key is preceded by a `static` keyword or decorators.
724+ //
725+ // `public [foo]()`
726+ // `; [foo]()`
727+ //
728+ // `public *foo()`
729+ // `; *foo()`
730+ //
731+ // `public in()`
732+ // `; in()`
733+ if has_modifier
734+ && !n. is_static
735+ && n. function . decorators . is_empty ( )
736+ && ( n. key . is_computed ( )
737+ || n. function . is_generator
738+ || n. key
739+ . as_ident ( )
740+ . filter ( |k| matches ! ( k. sym. as_ref( ) , "in" | "instanceof" ) )
741+ . is_some ( ) )
742+ {
743+ self . add_overwrite ( start_pos, b';' ) ;
744+ }
745+
701746 n. visit_children_with ( self ) ;
702747 }
703748
@@ -707,9 +752,12 @@ impl Visit for TsStrip {
707752 return ;
708753 }
709754
755+ let has_modifier = n. readonly || n. is_override || n. accessibility . is_some ( ) ;
710756 let start_pos = n. decorators . last ( ) . map_or ( n. span . lo , |d| d. span . hi ) ;
711757
712- self . strip_class_modifier ( start_pos, n. key . span_lo ( ) ) ;
758+ if has_modifier {
759+ self . strip_class_modifier ( start_pos, n. key . span_lo ( ) ) ;
760+ }
713761
714762 if n. is_optional {
715763 let mark_index = self . get_next_token_index ( n. key . span_hi ( ) ) ;
@@ -720,23 +768,53 @@ impl Visit for TsStrip {
720768 self . strip_definite_mark ( mark_index) ;
721769 }
722770
723- if n. value . is_none ( ) && n. key . as_ident ( ) . filter ( |k| k. sym == "static" ) . is_some ( ) {
724- if let Some ( type_ann) = & n. type_ann {
725- self . add_overwrite ( type_ann. span . lo , b';' ) ;
771+ // It's dangerous to strip types if the key is `get`, `set`, or `static`.
772+ if n. value . is_none ( ) {
773+ if let Some ( key) = n. key . as_ident ( ) {
774+ if matches ! ( key. sym. as_ref( ) , "get" | "set" | "static" ) {
775+ // `get: number`
776+ // `get; `
777+ if let Some ( type_ann) = & n. type_ann {
778+ self . add_overwrite ( type_ann. span . lo , b';' ) ;
779+ }
780+ }
726781 }
727782 }
728783
784+ // `private [foo]`
785+ // `; [foo]`
786+ //
787+ // `private in`
788+ // `; in`
789+ if !n. is_static
790+ && has_modifier
791+ && n. decorators . is_empty ( )
792+ && ( n. key . is_computed ( )
793+ || n. key
794+ . as_ident ( )
795+ . filter ( |k| matches ! ( k. sym. as_ref( ) , "in" | "instanceof" ) )
796+ . is_some ( ) )
797+ {
798+ self . add_overwrite ( start_pos, b';' ) ;
799+ }
800+
729801 n. visit_children_with ( self ) ;
730802 }
731803
732804 fn visit_private_method ( & mut self , n : & PrivateMethod ) {
733- let start_pos = n
734- . function
735- . decorators
736- . last ( )
737- . map_or ( n. span . lo , |d| d. span . hi ) ;
738-
739- self . strip_class_modifier ( start_pos, n. key . span . lo ) ;
805+ debug_assert ! ( !n. is_override) ;
806+ debug_assert ! ( !n. is_abstract) ;
807+
808+ // Is `private #foo()` valid?
809+ if n. accessibility . is_some ( ) {
810+ let start_pos = n
811+ . function
812+ . decorators
813+ . last ( )
814+ . map_or ( n. span . lo , |d| d. span . hi ) ;
815+
816+ self . strip_class_modifier ( start_pos, n. key . span . lo ) ;
817+ }
740818
741819 if n. is_optional {
742820 let mark_index = self . get_next_token_index ( n. key . span . hi ) ;
@@ -747,9 +825,12 @@ impl Visit for TsStrip {
747825 }
748826
749827 fn visit_private_prop ( & mut self , n : & PrivateProp ) {
750- let start_pos = n . decorators . last ( ) . map_or ( n . span . lo , |d| d . span . hi ) ;
828+ debug_assert ! ( !n . is_override ) ;
751829
752- self . strip_class_modifier ( start_pos, n. key . span . lo ) ;
830+ if n. readonly || n. accessibility . is_some ( ) {
831+ let start_pos = n. decorators . last ( ) . map_or ( n. span . lo , |d| d. span . hi ) ;
832+ self . strip_class_modifier ( start_pos, n. key . span . lo ) ;
833+ }
753834
754835 if n. is_optional {
755836 let mark_index = self . get_next_token_index ( n. key . span . hi ) ;
0 commit comments