17
17
package com .google .javascript .jscomp ;
18
18
19
19
import org .junit .Before ;
20
+ import org .junit .Ignore ;
20
21
import org .junit .Test ;
21
22
import org .junit .runner .RunWith ;
22
23
import org .junit .runners .JUnit4 ;
@@ -34,6 +35,7 @@ public void setUp() throws Exception {
34
35
super .setUp ();
35
36
36
37
enableNormalize ();
38
+ enableComputeSideEffects ();
37
39
// TODO(bradfordcsmith): Stop normalizing the expected output or document why it is necessary.
38
40
enableNormalizeExpectedOutput ();
39
41
late = false ;
@@ -134,7 +136,7 @@ public void testFoldReturnsIntegration() {
134
136
@ Test
135
137
public void testFoldReturnsIntegrationWithScoped () {
136
138
late = true ;
137
- disableNormalize ();
139
+ disableComputeSideEffects ();
138
140
139
141
// if-then-else duplicate statement removal handles this case:
140
142
testSame ("function test(a) {if (a) {const a = Math.random();if(a) {return a;}} return a; }" );
@@ -444,4 +446,1109 @@ public void testDontFoldKnownMethodsWithOptionalChaining() {
444
446
test ("x = parseInt?.(`123`)" , "x = parseInt?.(\" 123\" )" );
445
447
test ("x = parseFloat?.(`1.23`)" , "x = parseFloat?.(\" 1.23\" )" );
446
448
}
449
+
450
+ @ Test
451
+ public void testLabeledBlocks () {
452
+ test (
453
+ lines (
454
+ "function b(m) {" , //
455
+ " return m;" ,
456
+ " label: {" ,
457
+ " START('debug');" ,
458
+ " label2: {" ,
459
+ " alert('Shouldnt be here' + m);" ,
460
+ " }" ,
461
+ " END('debug');" ,
462
+ " }" ,
463
+ "}" ),
464
+ lines (
465
+ "function b(m) {" , //
466
+ " return m;" ,
467
+ "}" ));
468
+ }
469
+
470
+ @ Test
471
+ public void testDoNotRemoveDeclarationOfUsedVariable () {
472
+ test (
473
+ lines (
474
+ "var f = function() {" , //
475
+ " return 1;" ,
476
+ " let b = 5;" ,
477
+ " do {" ,
478
+ " b--;" ,
479
+ " } while (b);" ,
480
+ " return 3;" ,
481
+ "};" ),
482
+ lines (
483
+ "var f = function() {" , //
484
+ " return 1;" ,
485
+ "};" ));
486
+ }
487
+
488
+ @ Test
489
+ public void testDontRemoveExport () {
490
+ test (
491
+ lines (
492
+ "function foo() {" , //
493
+ " return 1;" ,
494
+ " alert(2);" ,
495
+ "}" ,
496
+ "export { foo as foo };" ),
497
+ lines (
498
+ "function foo() {" , //
499
+ " return 1;" ,
500
+ "}" ,
501
+ "export { foo as foo };" ));
502
+ }
503
+
504
+ @ Test
505
+ public void testRemoveUnreachableCode1 () {
506
+ // switch statement with stuff after "return"
507
+ test (
508
+ lines (
509
+ "function foo(){" , //
510
+ " switch (foo) {" ,
511
+ " case 1:" ,
512
+ " x=1;" ,
513
+ " return;" ,
514
+ " break;" ,
515
+ " case 2: {" ,
516
+ " x=2;" ,
517
+ " return;" ,
518
+ " break;" ,
519
+ " }" ,
520
+ " default:" ,
521
+ " }" ,
522
+ "}" ),
523
+ lines (
524
+ "function foo() {" , //
525
+ " switch (foo) {" ,
526
+ " case 1:" ,
527
+ " x=1;" ,
528
+ " break;" ,
529
+ " case 2:" ,
530
+ " x=2;" ,
531
+ " }" ,
532
+ "}" ));
533
+ }
534
+
535
+ @ Test
536
+ public void testRemoveUnreachableCode2 () {
537
+ // if/else statements with returns
538
+ test (
539
+ lines (
540
+ "function bar(){" , //
541
+ " if (foo)" ,
542
+ " x=1;" ,
543
+ " else if(bar) {" ,
544
+ " return;" ,
545
+ " x=2;" ,
546
+ " } else {" ,
547
+ " x=3;" ,
548
+ " return;" ,
549
+ " x=4;" ,
550
+ " }" ,
551
+ " return 5;" ,
552
+ " x=5;" ,
553
+ "}" ),
554
+ lines (
555
+ "function bar() {" , //
556
+ " if (foo) {" ,
557
+ " x=1;" ,
558
+ " return 5;" ,
559
+ " }" ,
560
+ " bar || (x = 3);" ,
561
+ "}" ));
562
+
563
+ // if statements without blocks
564
+ // NOTE: This pass should never see while-loops, because normalization replaces them all with
565
+ // for-loops.
566
+ test (
567
+ lines (
568
+ "function foo() {" , //
569
+ " if (x == 3) return;" ,
570
+ " x = 4;" ,
571
+ " y++;" ,
572
+ " for (; y == 4; ) {" ,
573
+ " return;" ,
574
+ " x = 3" ,
575
+ " }" ,
576
+ "}" ),
577
+ lines (
578
+ "function foo() {" , //
579
+ " if (x != 3) {" ,
580
+ " x = 4;" ,
581
+ " y++;" ,
582
+ " for (; y == 4; ) {" ,
583
+ " break" ,
584
+ " }" ,
585
+ " }" ,
586
+ "}" ));
587
+
588
+ // for/do/while loops
589
+ test (
590
+ lines (
591
+ "function baz() {" , //
592
+ // Normalize always moves the for-loop initializer out of the loop.
593
+ " i = 0;" ,
594
+ " for (; i < n; i++) {" ,
595
+ " x = 3;" ,
596
+ " break;" ,
597
+ " x = 4" ,
598
+ " }" ,
599
+ " do {" ,
600
+ " x = 2;" ,
601
+ " break;" ,
602
+ " x = 4" ,
603
+ " } while (x == 4);" ,
604
+ " for (; i < 4; ) {" ,
605
+ " x = 3;" ,
606
+ " return;" ,
607
+ " x = 6" ,
608
+ " }" ,
609
+ "}" ),
610
+ lines (
611
+ "function baz() {" , //
612
+ " i = 0;" ,
613
+ " for (; i < n; i++) {" ,
614
+ " x = 3;" ,
615
+ " break" ,
616
+ " }" ,
617
+ " do {" ,
618
+ " x = 2;" ,
619
+ " break" ,
620
+ " } while (x == 4);" ,
621
+ " for (; i < 4; ) {" ,
622
+ " x = 3;" ,
623
+ " break;" ,
624
+ " }" ,
625
+ "}" ));
626
+
627
+ // return statements on the same level as conditionals
628
+ test (
629
+ lines (
630
+ "function foo() {" , //
631
+ " if (x == 3) {" ,
632
+ " return" ,
633
+ " }" ,
634
+ " return 5;" ,
635
+ " while (y == 4) {" ,
636
+ " x++;" ,
637
+ " return;" ,
638
+ " x = 4" ,
639
+ " }" ,
640
+ "}" ),
641
+ lines (
642
+ "function foo() {" , //
643
+ " return x == 3 ? void 0 : 5;" ,
644
+ "}" ));
645
+
646
+ // return statements on the same level as conditionals
647
+ test (
648
+ lines (
649
+ "function foo() {" , //
650
+ " return 3;" ,
651
+ " for (; y == 4;) {" ,
652
+ " x++;" ,
653
+ " return;" ,
654
+ " x = 4" ,
655
+ " }" ,
656
+ "}" ),
657
+ lines (
658
+ "function foo() {" , //
659
+ " return 3" ,
660
+ "}" ));
661
+
662
+ // try/catch statements
663
+ test (
664
+ lines (
665
+ "function foo() {" , //
666
+ " try {" ,
667
+ " x = 3;" ,
668
+ " return x + 1;" ,
669
+ " x = 5" ,
670
+ " } catch (e) {" ,
671
+ " x = 4;" ,
672
+ " return 5;" ,
673
+ " x = 5" ,
674
+ " }" ,
675
+ "}" ),
676
+ lines (
677
+ "function foo() {" , //
678
+ " try {" ,
679
+ " x = 3;" ,
680
+ " return x + 1" ,
681
+ " } catch (e) {" ,
682
+ " x = 4;" ,
683
+ " return 5" ,
684
+ " }" ,
685
+ "}" ));
686
+
687
+ // try/finally statements
688
+ test (
689
+ lines (
690
+ "function foo() {" , //
691
+ " try {" ,
692
+ " x = 3;" ,
693
+ " return x + 1;" ,
694
+ " x = 5" ,
695
+ " } finally {" ,
696
+ " x = 4;" ,
697
+ " return 5;" ,
698
+ " x = 5" ,
699
+ " }" ,
700
+ "}" ),
701
+ lines (
702
+ "function foo() {" , //
703
+ " try {" ,
704
+ " x = 3;" ,
705
+ " return x + 1" ,
706
+ " } finally {" ,
707
+ " x = 4;" ,
708
+ " return 5" ,
709
+ " }" ,
710
+ "}" ));
711
+
712
+ // try/catch/finally statements
713
+ test (
714
+ lines (
715
+ "function foo() {" , //
716
+ " try {" ,
717
+ " x = 3;" ,
718
+ " return x + 1;" ,
719
+ " x = 5" ,
720
+ " } catch (e) {" ,
721
+ " x = 3;" ,
722
+ " return;" ,
723
+ " x = 2" ,
724
+ " } finally {" ,
725
+ " x = 4;" ,
726
+ " return 5;" ,
727
+ " x = 5" ,
728
+ " }" ,
729
+ "}" ),
730
+ lines (
731
+ "function foo() {" , //
732
+ " try {" ,
733
+ " x = 3;" ,
734
+ " return x + 1" ,
735
+ " } catch (e) {" ,
736
+ " x = 3;" ,
737
+ " } finally {" ,
738
+ " x = 4;" ,
739
+ " return 5" ,
740
+ " }" ,
741
+ "}" ));
742
+
743
+ // test a combination of blocks
744
+ test (
745
+ lines (
746
+ "function foo() {" , //
747
+ " x = 3;" ,
748
+ " if (x == 4) {" ,
749
+ " x = 5;" ,
750
+ " return;" ,
751
+ " x = 6" ,
752
+ " } else {" ,
753
+ " x = 7" ,
754
+ " }" ,
755
+ " return 5;" ,
756
+ " x = 3" ,
757
+ "}" ),
758
+ lines (
759
+ "function foo() {" , //
760
+ " x = 3;" ,
761
+ " if (x == 4) {" ,
762
+ " x = 5;" ,
763
+ " } else {" ,
764
+ " x = 7" ,
765
+ " return 5" ,
766
+ " }" ,
767
+ "}" ));
768
+
769
+ // test removing multiple statements
770
+ test (
771
+ lines (
772
+ "function foo() {" , //
773
+ " return 1;" ,
774
+ " var x = 2;" ,
775
+ " var y = 10;" ,
776
+ " return 2;" ,
777
+ "}" ),
778
+ lines (
779
+ "function foo() {" , //
780
+ " var y;" ,
781
+ " var x;" ,
782
+ " return 1" ,
783
+ "}" ));
784
+
785
+ test (
786
+ lines (
787
+ "function foo() {" , //
788
+ " return 1;" ,
789
+ " x = 2;" ,
790
+ " y = 10;" ,
791
+ " return 2;" ,
792
+ "}" ),
793
+ lines (
794
+ "function foo() {" , //
795
+ " return 1" ,
796
+ "}" ));
797
+ }
798
+
799
+ @ Test
800
+ public void testRemoveUselessNameStatements () {
801
+ test ("a;" , "" );
802
+ test ("a.b;" , "" );
803
+ test ("a.b.MyClass.prototype.memberName;" , "" );
804
+ }
805
+
806
+ @ Test
807
+ public void testRemoveUselessStrings () {
808
+ test ("'a';" , "" );
809
+ }
810
+
811
+ @ Test
812
+ public void testNoRemoveUseStrict () {
813
+ test ("'use strict';" , "'use strict'" );
814
+ }
815
+
816
+ @ Test
817
+ public void testRemoveDo () {
818
+ testSame ("do { print(1); break } while(1)" );
819
+ // NOTE: This pass should never see while-loops, because normalization replaces them all with
820
+ // for-loops.
821
+ test (
822
+ "for (; 1;) { break; do { print(1); break } while(1) }" ,
823
+ "for (; ;) { break; }" );
824
+ }
825
+
826
+ @ Test
827
+ public void testRemoveUselessLiteralValueStatements () {
828
+ test ("true;" , "" );
829
+ test ("'hi';" , "" );
830
+ test ("if (x) 1;" , "" );
831
+ // NOTE: This pass should never see while-loops, because normalization replaces them all with
832
+ // for-loops.
833
+ test ("for (; x;) 1;" , "for (; x;);" );
834
+ test ("do 1; while (x);" , "for (;x;);" );
835
+ test ("for (;;) 1;" , "for (;;);" );
836
+ test (
837
+ "switch(x){case 1:true;case 2:'hi';default:true}" , //
838
+ "" );
839
+ }
840
+
841
+ @ Test
842
+ public void testConditionalDeadCode () {
843
+ test ("function f() { if (1) return 5; else return 5; x = 1}" , "function f() { return 5;}" );
844
+ }
845
+
846
+ @ Test
847
+ @ Ignore (
848
+ "TODO(b/301641291): this was originally supported by UnreachableCodeElimination, which was"
849
+ + " removed in favor of peephole optimizations. Support this test case if found useful in"
850
+ + " the real code." )
851
+ public void testSwitchCase () {
852
+ test ("function f() { switch(x) { default: return 5; foo()}}" , "function f() { return 5; }" );
853
+ testSame ("function f() { switch(x) { default: return; case 1: foo(); bar()}}" );
854
+ test (
855
+ "function f() { switch(x) { default: return; case 1: return 5;bar()}}" ,
856
+ "function f() { switch(x) { default: return; case 1: return 5;}}" );
857
+ }
858
+
859
+ @ Test
860
+ public void testTryCatchFinally1 () {
861
+ testSame ("try {foo()} catch (e) {bar()}" );
862
+ testSame ("try { try {foo()} catch (e) {bar()}} catch (x) {bar()}" );
863
+ }
864
+
865
+ @ Test
866
+ public void testTryCatchFinally2 () {
867
+ testSame ("try {var x = 1} catch (e) {e()}" );
868
+ }
869
+
870
+ @ Test
871
+ public void testTryCatchFinally3 () {
872
+ testSame ("try {var x = 1} catch (e) {e()} finally {x()}" );
873
+ }
874
+
875
+ @ Test
876
+ public void testTryCatchFinally4 () {
877
+ testSame ("try {var x = 1} catch (e) {e()} finally {}" );
878
+ }
879
+
880
+ @ Test
881
+ public void testTryCatchFinally5 () {
882
+ testSame ("try {var x = 1} finally {x()}" );
883
+ testSame ("var x = 1" );
884
+ }
885
+
886
+ @ Test
887
+ public void testTryCatchFinally6 () {
888
+ test ("function f() {return; try{var x = 1}catch(e){} }" , "function f() {var x;}" );
889
+ }
890
+
891
+ @ Test
892
+ public void testRemovalRequiresRedeclaration () {
893
+ // NOTE: This pass should never see while-loops, because normalization replaces them all with
894
+ // for-loops.
895
+ test (
896
+ lines (
897
+ "for (; 1;) {" , //
898
+ " break;" ,
899
+ " var x = 1" ,
900
+ "}" ),
901
+ lines (
902
+ "var x;" , //
903
+ "for (;;) {" ,
904
+ " break;" ,
905
+ "}" ));
906
+ test (
907
+ lines (
908
+ "for (; 1;) {" , //
909
+ " break;" ,
910
+ " var x=1;" ,
911
+ " var y=1;" ,
912
+ "}" ),
913
+ lines (
914
+ "var y;" , //
915
+ "var x;" ,
916
+ "for (;;) {" ,
917
+ " break;" ,
918
+ "}" ));
919
+ }
920
+
921
+ @ Test
922
+ public void testAssignPropertyOnCreatedObject () {
923
+ testSame ("this.foo = 3;" );
924
+ testSame ("a.foo = 3;" );
925
+ testSame ("bar().foo = 3;" );
926
+ testSame ("({}).foo = bar();" );
927
+ testSame ("(new X()).foo = 3;" );
928
+
929
+ test ("({}).foo = 3;" , "" );
930
+ test ("(function() {}).prototype.toString = function(){};" , "" );
931
+ test ("(function() {}).prototype['toString'] = function(){};" , "" );
932
+ test ("(function() {}).prototype[f] = function(){};" , "" );
933
+ }
934
+
935
+ @ Test
936
+ public void testUselessUnconditionalReturn1 () {
937
+ test ("function foo() { return }" , "function foo() { }" );
938
+ }
939
+
940
+ @ Test
941
+ public void testUselessUnconditionalReturn2 () {
942
+ test ("function foo() { return; return; x=1 }" , "function foo() { }" );
943
+ }
944
+
945
+ @ Test
946
+ public void testUselessUnconditionalReturn3 () {
947
+ test ("function foo() { return; return; var x=1}" , "function foo() {var x}" );
948
+ }
949
+
950
+ @ Test
951
+ public void testUselessUnconditionalReturn4 () {
952
+ test (
953
+ "function foo() { return; function bar() {} }" ,
954
+ "function foo() { function bar() {} }" );
955
+ }
956
+
957
+ @ Test
958
+ public void testUselessUnconditionalReturn5 () {
959
+ testSame ("function foo() { return 5 }" );
960
+ }
961
+
962
+ @ Test
963
+ public void testUselessUnconditionalReturn6 () {
964
+ test ("function f() {switch (a) { case 'a': return}}" , "function f() {}" );
965
+ }
966
+
967
+ @ Test
968
+ @ Ignore (
969
+ "TODO(b/301641291): this was originally supported by UnreachableCodeElimination, which was"
970
+ + " removed in favor of peephole optimizations. Support this test case if found useful in"
971
+ + " the real code." )
972
+ public void testUselessUnconditionalReturn7 () {
973
+ testSame ("function f() {switch (a) { default: return; case 'a': alert(1)}}" );
974
+ }
975
+
976
+ @ Test
977
+ @ Ignore (
978
+ "TODO(b/301641291): this was originally supported by UnreachableCodeElimination, which was"
979
+ + " removed in favor of peephole optimizations. Support this test case if found useful in"
980
+ + " the real code." )
981
+ public void testUselessUnconditionalReturn8 () {
982
+ testSame ("function f() {switch (a) { case 'a': return; default: alert(1)}}" );
983
+ }
984
+
985
+ @ Test
986
+ public void testUselessUnconditionalReturn9 () {
987
+ testSame ("function f() {switch (a) { case 'a': case foo(): }}" );
988
+ }
989
+
990
+ @ Test
991
+ public void testUselessUnconditionalContinue () {
992
+ test ("for(;1;) {continue}" , "for(;;) {}" );
993
+ test ("for(;0;) {continue}" , "" );
994
+ }
995
+
996
+ @ Test
997
+ public void testUselessUnconditionalContinue2 () {
998
+ test (
999
+ "X: for(;1;) { for(;1;) { if (x()) {continue X} x = 1}}" ,
1000
+ "X: for(; ;) { for(; ;) { if (x()) {continue X} x = 1}}" );
1001
+ }
1002
+
1003
+ @ Test
1004
+ @ Ignore (
1005
+ "TODO(b/301641291): this was originally supported by UnreachableCodeElimination, which was"
1006
+ + " removed in favor of peephole optimizations. Support this test case if found useful in"
1007
+ + " the real code." )
1008
+ public void testUselessUnconditionalContinue3 () {
1009
+ test (
1010
+ "for(;1;) { X: for(;1;) { if (x()) {continue X} }}" ,
1011
+ "for(; ;) { X: for(; ;) { if (x()) {}}}" );
1012
+ }
1013
+
1014
+ @ Test
1015
+ @ Ignore (
1016
+ "TODO(b/301641291): this was originally supported by UnreachableCodeElimination, which was"
1017
+ + " removed in favor of peephole optimizations. Support this test case if found useful in"
1018
+ + " the real code." )
1019
+ public void testUselessUnconditionalContinue4 () {
1020
+ test ("do { continue } while(1);" , "do { } while(1);" );
1021
+ }
1022
+
1023
+ @ Test
1024
+ @ Ignore
1025
+ public void testUselessUnconditionalBreak1 () {
1026
+ // TODO - b/335145701: `case 'a'` can not be eliminated as that would force "foo()" to be
1027
+ // always executed.
1028
+ // `case foo()` can only be eliminated if "foo()" can be determined to be side-effect
1029
+ // free.
1030
+ test (
1031
+ "switch (a) { case 'a': break; case foo(): }" ,
1032
+ "switch (a) { case 'a': case foo(): }" );
1033
+ }
1034
+
1035
+ @ Test
1036
+ public void testUselessUnconditionalBreak2 () {
1037
+ test ("switch (a) { case 'a': break }" , "" );
1038
+ test (
1039
+ "switch (a) { default: break; case 'a': }" , //
1040
+ "" );
1041
+ }
1042
+
1043
+ @ Test
1044
+ public void testUselessUnconditionalBreak3 () {
1045
+ testSame ("switch (a) { case 'a': alert(a); break; default: alert(a); }" );
1046
+ testSame ("switch (a) { default: alert(a); break; case 'a': alert(a); }" );
1047
+ }
1048
+
1049
+ @ Test
1050
+ public void testUselessUnconditionalBreak4 () {
1051
+ test ("X: {switch (a) { case 'a': break X}}" , "" );
1052
+
1053
+ test (
1054
+ "X: {switch (a) { case 'a': if (a()) {break X} a = 1; }}" , //
1055
+ "X: {switch (a) { case 'a': a() || (a = 1); }}" );
1056
+ }
1057
+
1058
+ @ Test
1059
+ public void testUselessUnconditionalBreak5 () {
1060
+ test (
1061
+ "X: {switch (a) { case 'a': if (a()) {break X}}}" , //
1062
+ "X: {switch (a) { case 'a': a() }}" );
1063
+ }
1064
+
1065
+ @ Test
1066
+ public void testUselessUnconditionalBreak6 () {
1067
+ test (
1068
+ "X: {switch (a) { case 'a': if (a()) {break X}}}" , //
1069
+ "X: {switch (a) { case 'a': a(); }}" );
1070
+ }
1071
+
1072
+ @ Test
1073
+ public void testUselessUnconditionalBreak7 () {
1074
+ // There is no reason to keep these
1075
+ testSame ("do { break } while(1);" );
1076
+ test ("for(;1;) { break }" , "for(;;) { break; }" );
1077
+ }
1078
+
1079
+ @ Test
1080
+ public void testIteratedRemoval1 () {
1081
+ test ("switch (a) { case 'a': break; case 'b': break; case 'c': break }" , "" );
1082
+ }
1083
+
1084
+ @ Test
1085
+ public void testIteratedRemoval2 () {
1086
+ test (
1087
+ "function foo() { switch (a) { case 'a':return; case 'b':return; case 'c':return }}" ,
1088
+ "function foo() { }" );
1089
+ }
1090
+
1091
+ @ Test
1092
+ public void testIteratedRemoval3 () {
1093
+ test (
1094
+ "for (;;) {\n "
1095
+ + " switch (a) {\n "
1096
+ + " case 'a': continue;\n "
1097
+ + " case 'b': continue;\n "
1098
+ + " case 'c': continue;\n "
1099
+ + " }\n "
1100
+ + " }" ,
1101
+ " for (;;) { }" );
1102
+ }
1103
+
1104
+ @ Test
1105
+ public void testIteratedRemoval4 () {
1106
+ test ("function foo() { if (x) { return; } if (x) { return; }}" , "function foo() {}" );
1107
+ }
1108
+
1109
+ @ Test
1110
+ public void testIteratedRemoval5 () {
1111
+ test (
1112
+ "var x; \n "
1113
+ + " out: { \n "
1114
+ + " try { break out; } catch (e) { break out; } \n "
1115
+ + " x = undefined; \n "
1116
+ + " }" ,
1117
+ "var x;" );
1118
+ }
1119
+
1120
+ @ Test
1121
+ public void testIssue311 () {
1122
+ test (
1123
+ lines (
1124
+ "function a(b) {" ,
1125
+ " switch (b.v) {" ,
1126
+ " case 'SWITCH':" ,
1127
+ " if (b.i >= 0) {" ,
1128
+ " return b.o;" ,
1129
+ " } else {" ,
1130
+ " return;" ,
1131
+ " }" ,
1132
+ " break;" ,
1133
+ " }" ,
1134
+ "}" ),
1135
+ lines (
1136
+ "function a(b) {" ,
1137
+ " switch (b.v) {" ,
1138
+ " case 'SWITCH':" ,
1139
+ " if (b.i >= 0) {" ,
1140
+ " return b.o;" ,
1141
+ " }" ,
1142
+ " }" ,
1143
+ "}" ));
1144
+ }
1145
+
1146
+ @ Test
1147
+ public void testIssue4177428a () {
1148
+ testSame (
1149
+ lines (
1150
+ "f = function() {" ,
1151
+ " var action;" ,
1152
+ " a: {" ,
1153
+ " var proto = null;" ,
1154
+ " try {" ,
1155
+ " proto = new Proto" ,
1156
+ " } finally {" ,
1157
+ " action = proto;" ,
1158
+ " break a" , // Keep this...
1159
+ " }" ,
1160
+ " }" ,
1161
+ " alert(action)" , // and this.
1162
+ "};" ));
1163
+ }
1164
+
1165
+ @ Test
1166
+ public void testIssue4177428b () {
1167
+ test (
1168
+ lines (
1169
+ "f = function() {" ,
1170
+ " var action;" ,
1171
+ " a: {" ,
1172
+ " var proto = null;" ,
1173
+ " try {" ,
1174
+ " try {" ,
1175
+ " proto = new Proto" ,
1176
+ " } finally {" ,
1177
+ " action = proto;" ,
1178
+ " break a" , // Keep this...
1179
+ " }" ,
1180
+ " } finally {" ,
1181
+ " }" ,
1182
+ " }" ,
1183
+ " alert(action)" , // and this.
1184
+ "};" ),
1185
+ lines (
1186
+ "f = function() {" ,
1187
+ " var action;" ,
1188
+ " a: {" ,
1189
+ " var proto = null;" ,
1190
+ " try {" ,
1191
+ " proto = new Proto" ,
1192
+ " } finally {" ,
1193
+ " action = proto;" ,
1194
+ " break a" , // Keep this...
1195
+ " }" ,
1196
+ " }" ,
1197
+ " alert(action)" , // and this.
1198
+ "};" ));
1199
+ }
1200
+
1201
+ @ Test
1202
+ public void testIssue4177428c () {
1203
+ test (
1204
+ lines (
1205
+ "f = function() {" ,
1206
+ " var action;" ,
1207
+ " a: {" ,
1208
+ " var proto = null;" ,
1209
+ " try {" ,
1210
+ " } finally {" ,
1211
+ " try {" ,
1212
+ " proto = new Proto" ,
1213
+ " } finally {" ,
1214
+ " action = proto;" ,
1215
+ " break a" , // Keep this...
1216
+ " }" ,
1217
+ " }" ,
1218
+ " }" ,
1219
+ " alert(action)" ,
1220
+ // and this.
1221
+ "};" ),
1222
+ lines (
1223
+ "f = function() {" ,
1224
+ " var action;" ,
1225
+ " a: {" ,
1226
+ " var proto = null;" ,
1227
+ " try {" ,
1228
+ " proto = new Proto" ,
1229
+ " } finally {" ,
1230
+ " action = proto;" ,
1231
+ " break a" , // Keep this...
1232
+ " }" ,
1233
+ " }" ,
1234
+ " alert(action)" , // and this.
1235
+ "};" ));
1236
+ }
1237
+
1238
+ @ Test
1239
+ public void testIssue4177428_continue () {
1240
+ test (
1241
+ lines (
1242
+ "f = function() {" , //
1243
+ " var action;" ,
1244
+ " a: do {" ,
1245
+ " var proto = null;" ,
1246
+ " try {" ,
1247
+ " proto = new Proto" ,
1248
+ " } finally {" ,
1249
+ " action = proto;" ,
1250
+ " continue a" ,
1251
+ // Keep this...
1252
+ " }" ,
1253
+ " } while(false)" ,
1254
+ " alert(action)" ,
1255
+ // and this.
1256
+ "};" ),
1257
+ lines (
1258
+ "f = function() {" , //
1259
+ " var action;" ,
1260
+ " a: do {" ,
1261
+ " var proto = null;" ,
1262
+ " try {" ,
1263
+ " proto = new Proto" ,
1264
+ " } finally {" ,
1265
+ " action = proto;" ,
1266
+ " continue a" ,
1267
+ // Keep this...
1268
+ " }" ,
1269
+ " } while(0)" ,
1270
+ " alert(action)" ,
1271
+ // and this.
1272
+ "};" ));
1273
+ }
1274
+
1275
+ @ Test
1276
+ public void testIssue4177428_multifinally () {
1277
+ test (
1278
+ lines (
1279
+ "a: {" ,
1280
+ " try {" ,
1281
+ " try {" ,
1282
+ " } finally {" ,
1283
+ " break a;" ,
1284
+ " }" ,
1285
+ " } finally {" ,
1286
+ " x = 1;" ,
1287
+ " }" ,
1288
+ "}" ),
1289
+ lines (
1290
+ "a: {" , //
1291
+ " x = 1;" ,
1292
+ "}" ));
1293
+ }
1294
+
1295
+ @ Test
1296
+ public void testIssue5215541_deadVarDeclar () {
1297
+ test (
1298
+ " throw 1; var x;" , //
1299
+ "var x; throw 1; " );
1300
+ testSame ("throw 1; function x() {}" );
1301
+ test (
1302
+ "throw 1; var x; var y; " , //
1303
+ " var y; var x; throw 1;" );
1304
+ test (
1305
+ " throw 1; var x = foo" , //
1306
+ "var x; throw 1" );
1307
+ }
1308
+
1309
+ @ Test
1310
+ public void testForInLoop () {
1311
+ testSame ("var x; for(x in y) {}" );
1312
+ }
1313
+
1314
+ @ Test
1315
+ public void testDontRemoveBreakInTryFinally () {
1316
+ testSame (
1317
+ lines (
1318
+ "function f() {" , //
1319
+ " b: {" ,
1320
+ " try {" ,
1321
+ " throw 9;" ,
1322
+ " } finally {" ,
1323
+ " break b;" ,
1324
+ " }" ,
1325
+ " }" ,
1326
+ " return 1;" ,
1327
+ "}" ));
1328
+ }
1329
+
1330
+ @ Test
1331
+ public void testDontRemoveBreakInTryFinallySwitch () {
1332
+ testSame (
1333
+ lines (
1334
+ "function f() {" , //
1335
+ " b: {" ,
1336
+ " try {" ,
1337
+ " throw 9;" ,
1338
+ " } finally {" ,
1339
+ " switch (x) {" ,
1340
+ " case 1:" ,
1341
+ " break b;" ,
1342
+ " }" ,
1343
+ " }" ,
1344
+ " }" ,
1345
+ " return 1;" ,
1346
+ "}" ));
1347
+ }
1348
+
1349
+ @ Test
1350
+ // This was originally supported by UnreachableCodeElimination, which was removed in favor
1351
+ // of peephole optimizations. Support this test case if found useful in the real code.
1352
+ public void testIssue1001 () {
1353
+ test (
1354
+ "function f(x) { x.property = 3; } f({})" , //
1355
+ "function f(x) { x.property = 3; }" );
1356
+ test (
1357
+ "function f(x) { x.property = 3; } new f({})" , //
1358
+ "function f(x) { x.property = 3; }" );
1359
+ }
1360
+
1361
+ @ Test
1362
+ public void testLetConstBlocks () {
1363
+ test (
1364
+ "function f() {return 1; let a; }" , //
1365
+ "function f() {return 1; }" );
1366
+
1367
+ test (
1368
+ "function f() { return 1; const a = 1; }" , //
1369
+ "function f() { return 1; }" );
1370
+
1371
+ test (
1372
+ "function f() { x = 1; { let g; return x; } let y;}" ,
1373
+ "function f() { x = 1; let g; return x; } " );
1374
+ }
1375
+
1376
+ @ Test
1377
+ public void testArrowFunctions () {
1378
+ test ("f(x => {return x; j = 1})" , "f(x => {return x;})" );
1379
+
1380
+ testSame ("f( () => {return 1;})" );
1381
+ }
1382
+
1383
+ @ Test
1384
+ public void testForOf () {
1385
+ test ("for(x of i){ 1; }" , "for(x of i) {}" );
1386
+
1387
+ testSame ("for(x of i){}" );
1388
+ }
1389
+
1390
+ @ Test
1391
+ public void testLetConstBlocks_inFunction_exportedFromEs6Module () {
1392
+ test (
1393
+ lines (
1394
+ "function f() {" , //
1395
+ " return 1;" ,
1396
+ " let a;" ,
1397
+ "}" ,
1398
+ "export { f as f };" ),
1399
+ lines (
1400
+ "function f() {" , //
1401
+ " return 1;" ,
1402
+ "}" ,
1403
+ "export { f as f };" ));
1404
+
1405
+ test (
1406
+ lines (
1407
+ "function f() {" , //
1408
+ " return 1;" ,
1409
+ " const a = 1;" ,
1410
+ "}" ,
1411
+ "export { f as f };" ),
1412
+ lines (
1413
+ "function f() {" , //
1414
+ " return 1;" ,
1415
+ "}" ,
1416
+ "export { f as f };" ));
1417
+
1418
+ test (
1419
+ lines (
1420
+ "function f() {" , //
1421
+ " x = 1;" ,
1422
+ " {" ,
1423
+ " let g;" ,
1424
+ " return x" ,
1425
+ " }" ,
1426
+ " let y" ,
1427
+ "}" ,
1428
+ "export { f as f };" ),
1429
+ lines (
1430
+ "function f() {" , //
1431
+ " x = 1;" ,
1432
+ " let g;" ,
1433
+ " return x;" ,
1434
+ "}" ,
1435
+ "export { f as f };" ));
1436
+ }
1437
+
1438
+ @ Test
1439
+ public void testRemoveUnreachableCode_withES6Modules () {
1440
+ // Switch statements
1441
+ test (
1442
+ lines (
1443
+ "function foo() {" ,
1444
+ " switch (foo) {" ,
1445
+ " case 1:" ,
1446
+ " x = 1;" ,
1447
+ " return;" ,
1448
+ " break;" ,
1449
+ " case 2: {" ,
1450
+ " x = 2;" ,
1451
+ " return;" ,
1452
+ " break;" ,
1453
+ " }" ,
1454
+ " default:" ,
1455
+ " }" ,
1456
+ "}" ,
1457
+ "export { foo as foo };" ),
1458
+ lines (
1459
+ "function foo() {" ,
1460
+ " switch (foo) {" ,
1461
+ " case 1:" ,
1462
+ " x = 1;" ,
1463
+ " break;" ,
1464
+ " case 2:" ,
1465
+ " x = 2;" ,
1466
+ " }" ,
1467
+ "}" ,
1468
+ "export { foo as foo };" ));
1469
+
1470
+ // if/else statements with returns
1471
+ test (
1472
+ lines (
1473
+ "function bar() {" ,
1474
+ " if (foo)" ,
1475
+ " x=1;" ,
1476
+ " else if(bar) {" ,
1477
+ " return;" ,
1478
+ " x=2;" ,
1479
+ " } else {" ,
1480
+ " x=3;" ,
1481
+ " return;" ,
1482
+ " x=4;" ,
1483
+ " }" ,
1484
+ " return 5;" ,
1485
+ " x=5;" ,
1486
+ "}" ,
1487
+ "export { bar as bar };" ),
1488
+ lines (
1489
+ "function bar() {" , //
1490
+ " if (foo) {" ,
1491
+ " x=1;" ,
1492
+ " return 5;" ,
1493
+ " }" ,
1494
+ " bar || (x = 3);" ,
1495
+ "}" ,
1496
+ "export { bar as bar };" ));
1497
+ }
1498
+
1499
+ @ Test
1500
+ public void testComputedClassPropertyNotRemoved () {
1501
+ testSame ("class Foo { ['x']() {} }" );
1502
+ }
1503
+
1504
+ @ Test
1505
+ public void testClassExtendsNotRemoved () {
1506
+ testSame (
1507
+ lines (
1508
+ "function f() {}" , //
1509
+ "class Foo extends f() {}" ));
1510
+ }
1511
+
1512
+ @ Test
1513
+ public void testRemoveUnreachableCodeInComputedPropertIife () {
1514
+ test (
1515
+ lines (
1516
+ "class Foo {" , //
1517
+ " [function() {" ,
1518
+ " 1; return 'x';" ,
1519
+ " }()]() { return 1; }" ,
1520
+ "}" ),
1521
+ lines (
1522
+ "class Foo {" , //
1523
+ " [function() {" ,
1524
+ " return 'x';" ,
1525
+ " }()]() { return 1; }" ,
1526
+ "}" ));
1527
+ }
1528
+
1529
+ @ Test
1530
+ public void testStaticBlockRemoved () {
1531
+ test ("class Foo { static {} }" , "class Foo { }" );
1532
+ }
1533
+
1534
+ @ Test
1535
+ public void testRemoveUnreachableCodeInStaticBlock1 () {
1536
+ // TODO(b/240443227): Unreachable/Useless code isn't removed in static blocks
1537
+ test (
1538
+ lines (
1539
+ "class Foo {" , //
1540
+ " static {" ,
1541
+ " switch (a) { case 'a': break }" ,
1542
+ " try {var x = 1} catch (e) {e()}" ,
1543
+ " true;" ,
1544
+ " if (x) 1;" ,
1545
+ " }" ,
1546
+ "}" ),
1547
+ lines (
1548
+ "class Foo {" , //
1549
+ " static {" ,
1550
+ " try {var x = 1} catch (e) {e()}" ,
1551
+ " }" ,
1552
+ "}" ));
1553
+ }
447
1554
}
0 commit comments