@@ -278,6 +278,15 @@ merge(Compressor.prototype, {
278
278
return x ;
279
279
} ;
280
280
281
+ var readOnlyPrefix = makePredicate ( "! ~ + - void typeof" ) ;
282
+ function statement_to_expression ( stat ) {
283
+ if ( stat . body instanceof AST_UnaryPrefix && readOnlyPrefix ( stat . body . operator ) ) {
284
+ return stat . body . expression ;
285
+ } else {
286
+ return stat . body ;
287
+ }
288
+ }
289
+
281
290
function tighten_body ( statements , compressor ) {
282
291
var CHANGED , max_iter = 10 ;
283
292
do {
@@ -303,10 +312,6 @@ merge(Compressor.prototype, {
303
312
}
304
313
} while ( CHANGED && max_iter -- > 0 ) ;
305
314
306
- if ( compressor . option ( "negate_iife" ) ) {
307
- negate_iifes ( statements , compressor ) ;
308
- }
309
-
310
315
return statements ;
311
316
312
317
function collapse_single_use_vars ( statements , compressor ) {
@@ -753,7 +758,7 @@ merge(Compressor.prototype, {
753
758
if ( seqLength ( seq ) >= compressor . sequences_limit ) {
754
759
push_seq ( ) ;
755
760
}
756
- seq . push ( stat . body ) ;
761
+ seq . push ( seq . length > 0 ? statement_to_expression ( stat ) : stat . body ) ;
757
762
} else {
758
763
push_seq ( ) ;
759
764
ret . push ( stat ) ;
@@ -802,7 +807,7 @@ merge(Compressor.prototype, {
802
807
stat . init = cons_seq ( stat . init ) ;
803
808
}
804
809
else if ( ! stat . init ) {
805
- stat . init = prev . body ;
810
+ stat . init = statement_to_expression ( prev ) ;
806
811
ret . pop ( ) ;
807
812
}
808
813
} catch ( ex ) {
@@ -859,50 +864,6 @@ merge(Compressor.prototype, {
859
864
} , [ ] ) ;
860
865
} ;
861
866
862
- function negate_iifes ( statements , compressor ) {
863
- function is_iife_call ( node ) {
864
- if ( node instanceof AST_Call ) {
865
- return node . expression instanceof AST_Function || is_iife_call ( node . expression ) ;
866
- }
867
- return false ;
868
- }
869
-
870
- statements . forEach ( function ( stat ) {
871
- if ( stat instanceof AST_SimpleStatement ) {
872
- stat . body = ( function transform ( thing ) {
873
- return thing . transform ( new TreeTransformer ( function ( node ) {
874
- if ( node instanceof AST_New ) {
875
- return node ;
876
- }
877
- if ( is_iife_call ( node ) ) {
878
- return make_node ( AST_UnaryPrefix , node , {
879
- operator : "!" ,
880
- expression : node
881
- } ) ;
882
- }
883
- else if ( node instanceof AST_Call ) {
884
- node . expression = transform ( node . expression ) ;
885
- }
886
- else if ( node instanceof AST_Seq ) {
887
- node . car = transform ( node . car ) ;
888
- }
889
- else if ( node instanceof AST_Conditional ) {
890
- var expr = transform ( node . condition ) ;
891
- if ( expr !== node . condition ) {
892
- // it has been negated, reverse
893
- node . condition = expr ;
894
- var tmp = node . consequent ;
895
- node . consequent = node . alternative ;
896
- node . alternative = tmp ;
897
- }
898
- }
899
- return node ;
900
- } ) ) ;
901
- } ) ( stat . body ) ;
902
- }
903
- } ) ;
904
- } ;
905
-
906
867
} ;
907
868
908
869
function extract_functions_from_statement_array ( statements ) {
@@ -1007,7 +968,15 @@ merge(Compressor.prototype, {
1007
968
return ast1 . print_to_string ( ) . length >
1008
969
ast2 . print_to_string ( ) . length
1009
970
? ast2 : ast1 ;
1010
- } ;
971
+ }
972
+
973
+ function best_of_statement ( ast1 , ast2 ) {
974
+ return best_of ( make_node ( AST_SimpleStatement , ast1 , {
975
+ body : ast1
976
+ } ) , make_node ( AST_SimpleStatement , ast2 , {
977
+ body : ast2
978
+ } ) ) . body ;
979
+ }
1011
980
1012
981
// methods to evaluate a constant expression
1013
982
( function ( def ) {
@@ -1227,7 +1196,17 @@ merge(Compressor.prototype, {
1227
1196
operator : "!" ,
1228
1197
expression : exp
1229
1198
} ) ;
1230
- } ;
1199
+ }
1200
+ function best ( orig , alt , first_in_statement ) {
1201
+ var negated = basic_negation ( orig ) ;
1202
+ if ( first_in_statement ) {
1203
+ var stat = make_node ( AST_SimpleStatement , alt , {
1204
+ body : alt
1205
+ } ) ;
1206
+ return best_of ( negated , stat ) === stat ? alt : negated ;
1207
+ }
1208
+ return best_of ( negated , alt ) ;
1209
+ }
1231
1210
def ( AST_Node , function ( ) {
1232
1211
return basic_negation ( this ) ;
1233
1212
} ) ;
@@ -1247,13 +1226,13 @@ merge(Compressor.prototype, {
1247
1226
self . cdr = self . cdr . negate ( compressor ) ;
1248
1227
return self ;
1249
1228
} ) ;
1250
- def ( AST_Conditional , function ( compressor ) {
1229
+ def ( AST_Conditional , function ( compressor , first_in_statement ) {
1251
1230
var self = this . clone ( ) ;
1252
1231
self . consequent = self . consequent . negate ( compressor ) ;
1253
1232
self . alternative = self . alternative . negate ( compressor ) ;
1254
- return best_of ( basic_negation ( this ) , self ) ;
1233
+ return best ( this , self , first_in_statement ) ;
1255
1234
} ) ;
1256
- def ( AST_Binary , function ( compressor ) {
1235
+ def ( AST_Binary , function ( compressor , first_in_statement ) {
1257
1236
var self = this . clone ( ) , op = this . operator ;
1258
1237
if ( compressor . option ( "unsafe_comps" ) ) {
1259
1238
switch ( op ) {
@@ -1270,20 +1249,20 @@ merge(Compressor.prototype, {
1270
1249
case "!==" : self . operator = "===" ; return self ;
1271
1250
case "&&" :
1272
1251
self . operator = "||" ;
1273
- self . left = self . left . negate ( compressor ) ;
1252
+ self . left = self . left . negate ( compressor , first_in_statement ) ;
1274
1253
self . right = self . right . negate ( compressor ) ;
1275
- return best_of ( basic_negation ( this ) , self ) ;
1254
+ return best ( this , self , first_in_statement ) ;
1276
1255
case "||" :
1277
1256
self . operator = "&&" ;
1278
- self . left = self . left . negate ( compressor ) ;
1257
+ self . left = self . left . negate ( compressor , first_in_statement ) ;
1279
1258
self . right = self . right . negate ( compressor ) ;
1280
- return best_of ( basic_negation ( this ) , self ) ;
1259
+ return best ( this , self , first_in_statement ) ;
1281
1260
}
1282
1261
return basic_negation ( this ) ;
1283
1262
} ) ;
1284
1263
} ) ( function ( node , func ) {
1285
- node . DEFMETHOD ( "negate" , function ( compressor ) {
1286
- return func . call ( this , compressor ) ;
1264
+ node . DEFMETHOD ( "negate" , function ( compressor , first_in_statement ) {
1265
+ return func . call ( this , compressor , first_in_statement ) ;
1287
1266
} ) ;
1288
1267
} ) ;
1289
1268
@@ -1968,8 +1947,8 @@ merge(Compressor.prototype, {
1968
1947
return make_node ( AST_SimpleStatement , self , {
1969
1948
body : make_node ( AST_Conditional , self , {
1970
1949
condition : self . condition ,
1971
- consequent : self . body . body ,
1972
- alternative : self . alternative . body
1950
+ consequent : statement_to_expression ( self . body ) ,
1951
+ alternative : statement_to_expression ( self . alternative )
1973
1952
} )
1974
1953
} ) . transform ( compressor ) ;
1975
1954
}
@@ -1985,14 +1964,14 @@ merge(Compressor.prototype, {
1985
1964
body : make_node ( AST_Binary , self , {
1986
1965
operator : "||" ,
1987
1966
left : negated ,
1988
- right : self . body . body
1967
+ right : statement_to_expression ( self . body )
1989
1968
} )
1990
1969
} ) . transform ( compressor ) ;
1991
1970
return make_node ( AST_SimpleStatement , self , {
1992
1971
body : make_node ( AST_Binary , self , {
1993
1972
operator : "&&" ,
1994
1973
left : self . condition ,
1995
- right : self . body . body
1974
+ right : statement_to_expression ( self . body )
1996
1975
} )
1997
1976
} ) . transform ( compressor ) ;
1998
1977
}
@@ -2003,7 +1982,7 @@ merge(Compressor.prototype, {
2003
1982
body : make_node ( AST_Binary , self , {
2004
1983
operator : "||" ,
2005
1984
left : self . condition ,
2006
- right : self . alternative . body
1985
+ right : statement_to_expression ( self . alternative )
2007
1986
} )
2008
1987
} ) . transform ( compressor ) ;
2009
1988
}
@@ -2386,7 +2365,19 @@ merge(Compressor.prototype, {
2386
2365
}
2387
2366
}
2388
2367
}
2389
- return self . evaluate ( compressor ) [ 0 ] ;
2368
+ if ( compressor . option ( "negate_iife" )
2369
+ && compressor . parent ( ) instanceof AST_SimpleStatement
2370
+ && is_iife_call ( self ) ) {
2371
+ return self . negate ( compressor , true ) ;
2372
+ }
2373
+ return self ;
2374
+
2375
+ function is_iife_call ( node ) {
2376
+ if ( node instanceof AST_Call && ! ( node instanceof AST_New ) ) {
2377
+ return node . expression instanceof AST_Function || is_iife_call ( node . expression ) ;
2378
+ }
2379
+ return false ;
2380
+ }
2390
2381
} ) ;
2391
2382
2392
2383
OPT ( AST_New , function ( self , compressor ) {
@@ -2473,6 +2464,10 @@ merge(Compressor.prototype, {
2473
2464
// !!foo ==> foo, if we're in boolean context
2474
2465
return e . expression ;
2475
2466
}
2467
+ if ( e instanceof AST_Binary ) {
2468
+ var statement = first_in_statement ( compressor ) ;
2469
+ self = ( statement ? best_of_statement : best_of ) ( self , e . negate ( compressor , statement ) ) ;
2470
+ }
2476
2471
break ;
2477
2472
case "typeof" :
2478
2473
// typeof always returns a non-empty string, thus it's
@@ -2486,9 +2481,6 @@ merge(Compressor.prototype, {
2486
2481
}
2487
2482
return make_node ( AST_True , self ) ;
2488
2483
}
2489
- if ( e instanceof AST_Binary && self . operator == "!" ) {
2490
- self = best_of ( self , e . negate ( compressor ) ) ;
2491
- }
2492
2484
}
2493
2485
return self . evaluate ( compressor ) [ 0 ] ;
2494
2486
} ) ;
@@ -2665,11 +2657,12 @@ merge(Compressor.prototype, {
2665
2657
if ( compressor . option ( "comparisons" ) && self . is_boolean ( ) ) {
2666
2658
if ( ! ( compressor . parent ( ) instanceof AST_Binary )
2667
2659
|| compressor . parent ( ) instanceof AST_Assign ) {
2660
+ var statement = first_in_statement ( compressor ) ;
2668
2661
var negated = make_node ( AST_UnaryPrefix , self , {
2669
2662
operator : "!" ,
2670
- expression : self . negate ( compressor )
2663
+ expression : self . negate ( compressor , statement )
2671
2664
} ) ;
2672
- self = best_of ( self , negated ) ;
2665
+ self = ( statement ? best_of_statement : best_of ) ( self , negated ) ;
2673
2666
}
2674
2667
if ( compressor . option ( "unsafe_comps" ) ) {
2675
2668
switch ( self . operator ) {
@@ -2873,8 +2866,9 @@ merge(Compressor.prototype, {
2873
2866
return maintain_this_binding ( compressor . parent ( ) , self , self . alternative ) ;
2874
2867
}
2875
2868
}
2876
- var negated = cond [ 0 ] . negate ( compressor ) ;
2877
- if ( best_of ( cond [ 0 ] , negated ) === negated ) {
2869
+ var statement = first_in_statement ( compressor ) ;
2870
+ var negated = cond [ 0 ] . negate ( compressor , statement ) ;
2871
+ if ( ( statement ? best_of_statement : best_of ) ( cond [ 0 ] , negated ) === negated ) {
2878
2872
self = make_node ( AST_Conditional , self , {
2879
2873
condition : negated ,
2880
2874
consequent : self . alternative ,
0 commit comments