Skip to content

Commit cf72fe5

Browse files
authored
fix delete corner cases (#1799)
- assignment - boolean - conditional - sequence
1 parent a1532eb commit cf72fe5

File tree

5 files changed

+369
-24
lines changed

5 files changed

+369
-24
lines changed

lib/compress.js

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -481,15 +481,15 @@ merge(Compressor.prototype, {
481481
// func(something) because that changes the meaning of
482482
// the func (becomes lexical instead of global).
483483
function maintain_this_binding(parent, orig, val) {
484-
if (parent instanceof AST_Call && parent.expression === orig) {
485-
if (val instanceof AST_PropAccess || val instanceof AST_SymbolRef && val.name === "eval") {
486-
return make_node(AST_Seq, orig, {
487-
car: make_node(AST_Number, orig, {
488-
value: 0
489-
}),
490-
cdr: val
491-
});
492-
}
484+
if (parent instanceof AST_UnaryPrefix && parent.operator == "delete"
485+
|| parent instanceof AST_Call && parent.expression === orig
486+
&& (val instanceof AST_PropAccess || val instanceof AST_SymbolRef && val.name == "eval")) {
487+
return make_node(AST_Seq, orig, {
488+
car: make_node(AST_Number, orig, {
489+
value: 0
490+
}),
491+
cdr: val
492+
});
493493
}
494494
return val;
495495
}
@@ -3103,11 +3103,27 @@ merge(Compressor.prototype, {
31033103
});
31043104

31053105
OPT(AST_UnaryPrefix, function(self, compressor){
3106+
var e = self.expression;
3107+
if (self.operator == "delete"
3108+
&& !(e instanceof AST_SymbolRef
3109+
|| e instanceof AST_PropAccess
3110+
|| e instanceof AST_NaN
3111+
|| e instanceof AST_Infinity
3112+
|| e instanceof AST_Undefined)) {
3113+
if (e instanceof AST_Seq) {
3114+
e = e.to_array();
3115+
e.push(make_node(AST_True, self));
3116+
return AST_Seq.from_array(e).optimize(compressor);
3117+
}
3118+
return make_node(AST_Seq, self, {
3119+
car: e,
3120+
cdr: make_node(AST_True, self)
3121+
}).optimize(compressor);
3122+
}
31063123
var seq = self.lift_sequences(compressor);
31073124
if (seq !== self) {
31083125
return seq;
31093126
}
3110-
var e = self.expression;
31113127
if (compressor.option("side_effects") && self.operator == "void") {
31123128
e = e.drop_side_effect_free(compressor);
31133129
if (e) {
@@ -3606,6 +3622,14 @@ merge(Compressor.prototype, {
36063622
return self;
36073623
});
36083624

3625+
function in_delete(parent) {
3626+
return parent instanceof AST_UnaryPrefix && parent.operator == "delete";
3627+
}
3628+
3629+
function is_atomic(parent, self) {
3630+
return parent.expression instanceof AST_SymbolRef || parent.expression.TYPE === self.TYPE;
3631+
}
3632+
36093633
OPT(AST_Undefined, function(self, compressor){
36103634
if (compressor.option("unsafe")) {
36113635
var undef = find_variable(compressor, "undefined");
@@ -3620,10 +3644,7 @@ merge(Compressor.prototype, {
36203644
}
36213645
}
36223646
var parent = compressor.parent();
3623-
if (parent instanceof AST_UnaryPrefix
3624-
&& parent.operator == "delete"
3625-
&& (parent.expression instanceof AST_SymbolRef
3626-
|| parent.expression.TYPE === self.TYPE)) return self;
3647+
if (in_delete(parent) && is_atomic(parent, self)) return self;
36273648
return make_node(AST_UnaryPrefix, self, {
36283649
operator: "void",
36293650
expression: make_node(AST_Number, self, {
@@ -3634,12 +3655,10 @@ merge(Compressor.prototype, {
36343655

36353656
OPT(AST_Infinity, function(self, compressor){
36363657
var parent = compressor.parent();
3637-
if (parent instanceof AST_UnaryPrefix
3638-
&& parent.operator == "delete"
3639-
&& (parent.expression instanceof AST_SymbolRef
3640-
|| parent.expression.TYPE === self.TYPE))
3641-
return self;
3658+
var del = in_delete(parent);
3659+
if (del && is_atomic(parent, self)) return self;
36423660
if (compressor.option("keep_infinity")
3661+
&& !(del && !is_atomic(parent, self))
36433662
&& !find_variable(compressor, "Infinity"))
36443663
return self;
36453664
return make_node(AST_Binary, self, {
@@ -3655,10 +3674,7 @@ merge(Compressor.prototype, {
36553674

36563675
OPT(AST_NaN, function(self, compressor){
36573676
var parent = compressor.parent();
3658-
if (parent instanceof AST_UnaryPrefix
3659-
&& parent.operator == "delete"
3660-
&& !(parent.expression instanceof AST_SymbolRef
3661-
|| parent.expression.TYPE === self.TYPE)
3677+
if (in_delete(parent) && !is_atomic(parent, self)
36623678
|| find_variable(compressor, "NaN")) {
36633679
return make_node(AST_Binary, self, {
36643680
operator: "/",

test/compress/conditionals.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,3 +962,56 @@ condition_symbol_matches_consequent: {
962962
}
963963
expect_stdout: "3 7 true 4"
964964
}
965+
966+
delete_conditional_1: {
967+
options = {
968+
booleans: true,
969+
conditionals: true,
970+
evaluate: true,
971+
side_effects: true,
972+
}
973+
input: {
974+
console.log(delete (1 ? undefined : x));
975+
console.log(delete (1 ? void 0 : x));
976+
console.log(delete (1 ? Infinity : x));
977+
console.log(delete (1 ? 1 / 0 : x));
978+
console.log(delete (1 ? NaN : x));
979+
console.log(delete (1 ? 0 / 0 : x));
980+
}
981+
expect: {
982+
console.log((void 0, !0));
983+
console.log((void 0, !0));
984+
console.log((1 / 0, !0));
985+
console.log((1 / 0, !0));
986+
console.log((NaN, !0));
987+
console.log((NaN, !0));
988+
}
989+
expect_stdout: true
990+
}
991+
992+
delete_conditional_2: {
993+
options = {
994+
booleans: true,
995+
conditionals: true,
996+
evaluate: true,
997+
keep_infinity: true,
998+
side_effects: true,
999+
}
1000+
input: {
1001+
console.log(delete (0 ? x : undefined));
1002+
console.log(delete (0 ? x : void 0));
1003+
console.log(delete (0 ? x : Infinity));
1004+
console.log(delete (0 ? x : 1 / 0));
1005+
console.log(delete (0 ? x : NaN));
1006+
console.log(delete (0 ? x : 0 / 0));
1007+
}
1008+
expect: {
1009+
console.log((void 0, !0));
1010+
console.log((void 0, !0));
1011+
console.log((Infinity, !0));
1012+
console.log((1 / 0, !0));
1013+
console.log((NaN, !0));
1014+
console.log((NaN, !0));
1015+
}
1016+
expect_stdout: true
1017+
}

test/compress/drop-unused.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,3 +974,58 @@ issue_1715_4: {
974974
}
975975
expect_stdout: "1"
976976
}
977+
978+
delete_assign_1: {
979+
options = {
980+
booleans: true,
981+
side_effects: true,
982+
toplevel: true,
983+
unused: true,
984+
}
985+
input: {
986+
var a;
987+
console.log(delete (a = undefined));
988+
console.log(delete (a = void 0));
989+
console.log(delete (a = Infinity));
990+
console.log(delete (a = 1 / 0));
991+
console.log(delete (a = NaN));
992+
console.log(delete (a = 0 / 0));
993+
}
994+
expect: {
995+
console.log((void 0, !0));
996+
console.log((void 0, !0));
997+
console.log((1 / 0, !0));
998+
console.log((1 / 0, !0));
999+
console.log((NaN, !0));
1000+
console.log((0 / 0, !0));
1001+
}
1002+
expect_stdout: true
1003+
}
1004+
1005+
delete_assign_2: {
1006+
options = {
1007+
booleans: true,
1008+
keep_infinity: true,
1009+
side_effects: true,
1010+
toplevel: true,
1011+
unused: true,
1012+
}
1013+
input: {
1014+
var a;
1015+
console.log(delete (a = undefined));
1016+
console.log(delete (a = void 0));
1017+
console.log(delete (a = Infinity));
1018+
console.log(delete (a = 1 / 0));
1019+
console.log(delete (a = NaN));
1020+
console.log(delete (a = 0 / 0));
1021+
}
1022+
expect: {
1023+
console.log((void 0, !0));
1024+
console.log((void 0, !0));
1025+
console.log((Infinity, !0));
1026+
console.log((1 / 0, !0));
1027+
console.log((NaN, !0));
1028+
console.log((0 / 0, !0));
1029+
}
1030+
expect_stdout: true
1031+
}

test/compress/evaluate.js

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,8 +858,9 @@ issue_1760_2: {
858858
expect_stdout: "Infinity"
859859
}
860860

861-
delete_expr: {
861+
delete_expr_1: {
862862
options = {
863+
booleans: true,
863864
evaluate: true,
864865
}
865866
input: {
@@ -871,12 +872,88 @@ delete_expr: {
871872
console.log(delete (0 / 0));
872873
}
873874
expect: {
875+
console.log(delete undefined);
876+
console.log((void 0, !0));
877+
console.log(delete Infinity);
878+
console.log((1 / 0, !0));
879+
console.log(delete NaN);
880+
console.log((0 / 0, !0));
881+
}
882+
expect_stdout: true
883+
}
884+
885+
delete_expr_2: {
886+
options = {
887+
booleans: true,
888+
evaluate: true,
889+
keep_infinity: true,
890+
}
891+
input: {
874892
console.log(delete undefined);
875893
console.log(delete void 0);
876894
console.log(delete Infinity);
877895
console.log(delete (1 / 0));
878896
console.log(delete NaN);
879897
console.log(delete (0 / 0));
880898
}
899+
expect: {
900+
console.log(delete undefined);
901+
console.log((void 0, !0));
902+
console.log(delete Infinity);
903+
console.log((1 / 0, !0));
904+
console.log(delete NaN);
905+
console.log((0 / 0, !0));
906+
}
907+
expect_stdout: true
908+
}
909+
910+
delete_binary_1: {
911+
options = {
912+
booleans: true,
913+
evaluate: true,
914+
side_effects: true,
915+
}
916+
input: {
917+
console.log(delete (true && undefined));
918+
console.log(delete (true && void 0));
919+
console.log(delete (true && Infinity));
920+
console.log(delete (true && (1 / 0)));
921+
console.log(delete (true && NaN));
922+
console.log(delete (true && (0 / 0)));
923+
}
924+
expect: {
925+
console.log((void 0, !0));
926+
console.log((void 0, !0));
927+
console.log((1 / 0, !0));
928+
console.log((1 / 0, !0));
929+
console.log((NaN, !0));
930+
console.log((NaN, !0));
931+
}
932+
expect_stdout: true
933+
}
934+
935+
delete_binary_2: {
936+
options = {
937+
booleans: true,
938+
evaluate: true,
939+
keep_infinity: true,
940+
side_effects: true,
941+
}
942+
input: {
943+
console.log(delete (false || undefined));
944+
console.log(delete (false || void 0));
945+
console.log(delete (false || Infinity));
946+
console.log(delete (false || (1 / 0)));
947+
console.log(delete (false || NaN));
948+
console.log(delete (false || (0 / 0)));
949+
}
950+
expect: {
951+
console.log((void 0, !0));
952+
console.log((void 0, !0));
953+
console.log((Infinity, !0));
954+
console.log((1 / 0, !0));
955+
console.log((NaN, !0));
956+
console.log((NaN, !0));
957+
}
881958
expect_stdout: true
882959
}

0 commit comments

Comments
 (0)