@@ -1965,6 +1965,12 @@ Compressor.prototype.compress = function(node) {
1965
1965
block = compressor.parent(level++);
1966
1966
} else if (block instanceof AST_LabeledStatement) {
1967
1967
block = block.body;
1968
+ } else if (block instanceof AST_SwitchBranch) {
1969
+ var branches = compressor.parent(level);
1970
+ if (branches.body[branches.body.length - 1] === block || has_break(block.body)) {
1971
+ level++;
1972
+ block = branches;
1973
+ }
1968
1974
}
1969
1975
do {
1970
1976
stat = block;
@@ -1975,8 +1981,16 @@ Compressor.prototype.compress = function(node) {
1975
1981
&& (block instanceof AST_BlockStatement
1976
1982
|| block instanceof AST_Catch
1977
1983
|| block instanceof AST_Scope
1984
+ || block instanceof AST_SwitchBranch
1978
1985
|| block instanceof AST_Try)
1979
1986
&& is_last_statement(block.body, stat));
1987
+
1988
+ function has_break(stats) {
1989
+ for (var i = stats.length; --i >= 0;) {
1990
+ if (stats[i] instanceof AST_Break) return true;
1991
+ }
1992
+ return false;
1993
+ }
1980
1994
}
1981
1995
1982
1996
function find_loop_scope_try() {
@@ -3437,7 +3451,7 @@ Compressor.prototype.compress = function(node) {
3437
3451
var changed = false;
3438
3452
var parent = compressor.parent();
3439
3453
var self = compressor.self();
3440
- var exit, merge_exit ;
3454
+ var jump, merge_jump ;
3441
3455
var in_iife = in_lambda && parent && parent.TYPE == "Call" && parent.expression === self;
3442
3456
var chain_if_returns = in_lambda && compressor.option("conditionals") && compressor.option("sequences");
3443
3457
var multiple_if_returns = has_multiple_if_returns(statements);
@@ -3447,6 +3461,7 @@ Compressor.prototype.compress = function(node) {
3447
3461
var next = statements[j];
3448
3462
3449
3463
if (in_lambda && !next && stat instanceof AST_Return
3464
+ && !(self instanceof AST_SwitchBranch)
3450
3465
&& !(in_try && in_try.bfinally && in_async_generator(in_lambda))) {
3451
3466
var body = stat.value;
3452
3467
if (!body) {
@@ -3494,7 +3509,7 @@ Compressor.prototype.compress = function(node) {
3494
3509
stat.condition = cond;
3495
3510
statements[j] = stat.body;
3496
3511
stat.body = next;
3497
- if (next === exit) exit = null;
3512
+ if (next === jump) jump = null;
3498
3513
statements[i] = stat;
3499
3514
statements[i] = stat.transform(compressor);
3500
3515
continue;
@@ -3538,7 +3553,7 @@ Compressor.prototype.compress = function(node) {
3538
3553
changed = true;
3539
3554
stat = stat.clone();
3540
3555
stat.alternative = next;
3541
- if (next === exit) exit = null;
3556
+ if (next === jump) jump = null;
3542
3557
statements.splice(i, 1, stat.transform(compressor));
3543
3558
statements.splice(j, 1);
3544
3559
continue;
@@ -3583,12 +3598,12 @@ Compressor.prototype.compress = function(node) {
3583
3598
}
3584
3599
}
3585
3600
3586
- if (stat instanceof AST_Exit) {
3587
- exit = stat;
3601
+ if (stat instanceof AST_Break || stat instanceof AST_Exit) {
3602
+ jump = stat;
3588
3603
continue;
3589
3604
}
3590
3605
3591
- if (exit && exit === next) eliminate_returns(stat);
3606
+ if (jump && jump === next) eliminate_returns(stat);
3592
3607
}
3593
3608
return changed;
3594
3609
@@ -3610,38 +3625,41 @@ Compressor.prototype.compress = function(node) {
3610
3625
}
3611
3626
3612
3627
function match_return(ab, exact) {
3613
- if (!exit ) return false;
3614
- if (exit .TYPE != ab.TYPE) return false;
3628
+ if (!jump ) return false;
3629
+ if (jump .TYPE != ab.TYPE) return false;
3615
3630
var value = ab.value;
3616
3631
if (!value) return false;
3617
- var equals = exit .equals(ab);
3632
+ var equals = jump .equals(ab);
3618
3633
if (!equals && value instanceof AST_Sequence) {
3619
3634
value = value.tail_node();
3620
- if (exit .value && exit .value.equals(value)) equals = 2;
3635
+ if (jump .value && jump .value.equals(value)) equals = 2;
3621
3636
}
3622
- if (!equals && !exact && exit .value instanceof AST_Sequence) {
3623
- if (exit .value.tail_node().equals(value)) equals = 3;
3637
+ if (!equals && !exact && jump .value instanceof AST_Sequence) {
3638
+ if (jump .value.tail_node().equals(value)) equals = 3;
3624
3639
}
3625
3640
return equals;
3626
3641
}
3627
3642
3628
3643
function can_drop_abort(ab) {
3629
3644
if (ab instanceof AST_Exit) {
3630
- if (merge_exit = match_return(ab)) return true;
3645
+ if (merge_jump = match_return(ab)) return true;
3631
3646
if (!in_lambda) return false;
3632
3647
if (!(ab instanceof AST_Return)) return false;
3633
- if (is_undefined(ab.value)) return true;
3634
- return ab.value instanceof AST_Sequence && is_undefined(ab.value.tail_node());
3648
+ var value = ab.value;
3649
+ if (value && !is_undefined(value.tail_node())) return false;
3650
+ if (self instanceof AST_SwitchBranch) merge_jump = 4;
3651
+ return true;
3635
3652
}
3636
3653
if (!(ab instanceof AST_LoopControl)) return false;
3637
3654
var lct = compressor.loopcontrol_target(ab);
3638
3655
if (ab instanceof AST_Continue) return match_target(loop_body(lct));
3639
3656
if (lct instanceof AST_IterationStatement) return false;
3657
+ if (jump) merge_jump = jump.equals(ab);
3640
3658
return match_target(lct);
3641
3659
}
3642
3660
3643
3661
function can_merge_flow(ab) {
3644
- merge_exit = false;
3662
+ merge_jump = false;
3645
3663
if (!can_drop_abort(ab)) return false;
3646
3664
for (var j = statements.length; --j > i;) {
3647
3665
var stat = statements[j];
@@ -3663,12 +3681,12 @@ Compressor.prototype.compress = function(node) {
3663
3681
var lexical = false;
3664
3682
var start = i + 1;
3665
3683
var end;
3666
- if (merge_exit ) {
3667
- end = statements.lastIndexOf(exit );
3684
+ if (merge_jump ) {
3685
+ end = statements.lastIndexOf(jump );
3668
3686
if (end < 0) end = statements.length;
3669
3687
} else {
3670
3688
end = statements.length;
3671
- exit = null;
3689
+ jump = null;
3672
3690
}
3673
3691
var tail = statements.splice(start, end - start).filter(function(stat) {
3674
3692
if (stat instanceof AST_LambdaDefinition) {
@@ -3678,18 +3696,20 @@ Compressor.prototype.compress = function(node) {
3678
3696
if (is_lexical_definition(stat)) lexical = true;
3679
3697
return true;
3680
3698
});
3681
- if (merge_exit === 3) {
3682
- tail.push(make_node(AST_SimpleStatement, exit .value, {
3683
- body: make_sequence(exit .value, exit .value.expressions.slice(0, -1)),
3699
+ if (merge_jump === 3) {
3700
+ tail.push(make_node(AST_SimpleStatement, jump .value, {
3701
+ body: make_sequence(jump .value, jump .value.expressions.slice(0, -1)),
3684
3702
}));
3685
- exit .value = exit .value.tail_node();
3703
+ jump .value = jump .value.tail_node();
3686
3704
}
3687
3705
[].push.apply(lexical ? tail : statements, defuns);
3688
3706
return tail;
3689
3707
}
3690
3708
3691
3709
function trim_return(value, mode) {
3692
3710
if (value) switch (mode) {
3711
+ case 4:
3712
+ return value;
3693
3713
case 3:
3694
3714
if (!(value instanceof AST_Sequence)) break;
3695
3715
case 2:
@@ -3705,7 +3725,7 @@ Compressor.prototype.compress = function(node) {
3705
3725
}
3706
3726
block.pop();
3707
3727
var value = ab.value;
3708
- if (merge_exit ) value = trim_return(value, merge_exit );
3728
+ if (merge_jump ) value = trim_return(value, merge_jump );
3709
3729
if (value) block.push(make_node(AST_SimpleStatement, value, { body: value }));
3710
3730
return body;
3711
3731
}
@@ -3757,7 +3777,7 @@ Compressor.prototype.compress = function(node) {
3757
3777
} else if (stat instanceof AST_LabeledStatement) {
3758
3778
stat.body = eliminate_returns(stat.body);
3759
3779
} else if (stat instanceof AST_Try) {
3760
- if (!stat.bfinally || !exit .value || exit .value.is_constant()) {
3780
+ if (!stat.bfinally || !jump .value || jump .value.is_constant()) {
3761
3781
if (stat.bcatch) eliminate_returns(stat.bcatch);
3762
3782
var trimmed = eliminate_returns(stat.body.pop(), true);
3763
3783
if (trimmed) stat.body.push(trimmed);
0 commit comments