Skip to content

Commit ed36c1e

Browse files
authored
fix corner case in unused (#5867)
fixes #5866
1 parent ce8ef52 commit ed36c1e

File tree

2 files changed

+253
-2
lines changed

2 files changed

+253
-2
lines changed

lib/compress.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8129,6 +8129,7 @@ Compressor.prototype.compress = function(node) {
81298129
}
81308130

81318131
function trim_destructured(node, value, process, drop, root) {
8132+
var unwind = true;
81328133
var trimmer = new TreeTransformer(function(node) {
81338134
if (node instanceof AST_DefaultValue) {
81348135
if (!(compressor.option("default_values") && value && value.is_defined(compressor))) {
@@ -8146,21 +8147,27 @@ Compressor.prototype.compress = function(node) {
81468147
}
81478148
if (node instanceof AST_DestructuredArray) {
81488149
var save_drop = drop;
8150+
var save_unwind = unwind;
81498151
var save_value = value;
81508152
if (value instanceof AST_SymbolRef) {
81518153
drop = false;
81528154
value = value.fixed_value();
81538155
}
8154-
var native, values;
8156+
var last_side_effects, native, values;
81558157
if (value instanceof AST_Array) {
81568158
native = true;
81578159
values = value.elements;
8160+
if (save_unwind) for (last_side_effects = values.length; --last_side_effects >= 0;) {
8161+
if (values[last_side_effects].has_side_effects(compressor)) break;
8162+
}
81588163
} else {
81598164
native = value && value.is_string(compressor);
81608165
values = false;
8166+
last_side_effects = node.elements.length;
81618167
}
81628168
var elements = [], newValues = drop && [], pos = 0;
81638169
node.elements.forEach(function(element, index) {
8170+
if (save_unwind) unwind = index >= last_side_effects;
81648171
value = values && values[index];
81658172
if (value instanceof AST_Hole) {
81668173
value = null;
@@ -8203,6 +8210,7 @@ Compressor.prototype.compress = function(node) {
82038210
}
82048211
}
82058212
value = save_value;
8213+
unwind = save_unwind;
82068214
drop = save_drop;
82078215
if (values && newValues) {
82088216
fill_holes(value, newValues);
@@ -8218,6 +8226,7 @@ Compressor.prototype.compress = function(node) {
82188226
return null;
82198227
case 1:
82208228
if (!drop) break;
8229+
if (!unwind) break;
82218230
if (node === root) break;
82228231
var sym = elements[0];
82238232
if (sym.has_side_effects(compressor)) break;
@@ -8236,16 +8245,19 @@ Compressor.prototype.compress = function(node) {
82368245
}
82378246
if (node instanceof AST_DestructuredObject) {
82388247
var save_drop = drop;
8248+
var save_unwind = unwind;
82398249
var save_value = value;
82408250
if (value instanceof AST_SymbolRef) {
82418251
drop = false;
82428252
value = value.fixed_value();
82438253
}
8244-
var prop_keys, prop_map, values;
8254+
var last_side_effects, prop_keys, prop_map, values;
82458255
if (value instanceof AST_Object) {
8256+
last_side_effects = -1;
82468257
prop_keys = [];
82478258
prop_map = new Dictionary();
82488259
values = value.properties.map(function(prop, index) {
8260+
if (save_unwind && prop.has_side_effects(compressor)) last_side_effects = index;
82498261
prop = prop.clone();
82508262
if (prop instanceof AST_Spread) {
82518263
prop_map = false;
@@ -8261,6 +8273,8 @@ Compressor.prototype.compress = function(node) {
82618273
}
82628274
return prop;
82638275
});
8276+
} else {
8277+
last_side_effects = node.properties.length;
82648278
}
82658279
if (node.rest) {
82668280
value = false;
@@ -8283,6 +8297,7 @@ Compressor.prototype.compress = function(node) {
82838297
return key;
82848298
}).forEach(function(key, index) {
82858299
var prop = node.properties[index], trimmed;
8300+
if (save_unwind) unwind = index >= last_side_effects;
82868301
if (key instanceof AST_Node) {
82878302
drop = false;
82888303
value = false;
@@ -8323,6 +8338,7 @@ Compressor.prototype.compress = function(node) {
83238338
}
83248339
});
83258340
value = save_value;
8341+
unwind = save_unwind;
83268342
drop = save_drop;
83278343
if (drop_keys && prop_keys) {
83288344
value = value.clone();
@@ -8357,6 +8373,7 @@ Compressor.prototype.compress = function(node) {
83578373
return null;
83588374
case 1:
83598375
if (!drop) break;
8376+
if (!unwind) break;
83608377
if (node === root) break;
83618378
var prop = properties[0];
83628379
if (prop.key instanceof AST_Node) break;

test/compress/destructured.js

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4007,3 +4007,237 @@ issue_5854_2: {
40074007
expect_stdout: "PASS"
40084008
node_version: ">=6"
40094009
}
4010+
4011+
issue_5866_1: {
4012+
options = {
4013+
unused: true,
4014+
}
4015+
input: {
4016+
var a = {};
4017+
var { p: { q: b } } = {
4018+
p: a,
4019+
r: a.q = "PASS",
4020+
};
4021+
console.log(b);
4022+
}
4023+
expect: {
4024+
var a = {};
4025+
var { q: b } = {
4026+
p: a,
4027+
r: a.q = "PASS",
4028+
}.p;
4029+
console.log(b);
4030+
}
4031+
expect_stdout: "PASS"
4032+
node_version: ">=6"
4033+
}
4034+
4035+
issue_5866_2: {
4036+
options = {
4037+
side_effects: true,
4038+
unused: true,
4039+
}
4040+
input: {
4041+
var a = {}, b;
4042+
({ p: { q: b } } = {
4043+
p: a,
4044+
r: a.q = "PASS",
4045+
});
4046+
console.log(b);
4047+
}
4048+
expect: {
4049+
var b, a = {};
4050+
({ q: b } = {
4051+
p: a,
4052+
r: a.q = "PASS",
4053+
}.p);
4054+
console.log(b);
4055+
}
4056+
expect_stdout: "PASS"
4057+
node_version: ">=6"
4058+
}
4059+
4060+
issue_5866_3: {
4061+
options = {
4062+
unused: true,
4063+
}
4064+
input: {
4065+
var a = {};
4066+
var [ { p: b } ] = [ a, a.p = "PASS" ];
4067+
console.log(b);
4068+
}
4069+
expect: {
4070+
var a = {};
4071+
var { p: b } = [ a, a.p = "PASS" ][0];
4072+
console.log(b);
4073+
}
4074+
expect_stdout: "PASS"
4075+
node_version: ">=6"
4076+
}
4077+
4078+
issue_5866_4: {
4079+
options = {
4080+
side_effects: true,
4081+
unused: true,
4082+
}
4083+
input: {
4084+
var a = {}, b;
4085+
[ { p: b } ] = [ a, a.p = "PASS" ];
4086+
console.log(b);
4087+
}
4088+
expect: {
4089+
var b, a = {};
4090+
({ p: b } = [ a, a.p = "PASS" ][0]);
4091+
console.log(b);
4092+
}
4093+
expect_stdout: "PASS"
4094+
node_version: ">=6"
4095+
}
4096+
4097+
issue_5866_5: {
4098+
options = {
4099+
unused: true,
4100+
}
4101+
input: {
4102+
var a = [];
4103+
var [ [ b ] ] = [ a, a[0] = "PASS" ];
4104+
console.log(b);
4105+
}
4106+
expect: {
4107+
var a = [];
4108+
var [ b ] = [ a, a[0] = "PASS" ][0];
4109+
console.log(b);
4110+
}
4111+
expect_stdout: "PASS"
4112+
node_version: ">=6"
4113+
}
4114+
4115+
issue_5866_6: {
4116+
options = {
4117+
side_effects: true,
4118+
unused: true,
4119+
}
4120+
input: {
4121+
var a = [], b;
4122+
[ [ b ] ] = [ a, a[0] = "PASS" ];
4123+
console.log(b);
4124+
}
4125+
expect: {
4126+
var b, a = [];
4127+
[ b ] = [ a, a[0] = "PASS" ][0];
4128+
console.log(b);
4129+
}
4130+
expect_stdout: "PASS"
4131+
node_version: ">=6"
4132+
}
4133+
4134+
issue_5866_7: {
4135+
options = {
4136+
unused: true,
4137+
}
4138+
input: {
4139+
var a = {};
4140+
var [ { p: b }, c ] = [ a, a.p = {} ];
4141+
console.log(b === c ? "PASS" : "FAIL");
4142+
}
4143+
expect: {
4144+
var a = {};
4145+
var [ { p: b }, c ] = [ a, a.p = {} ];
4146+
console.log(b === c ? "PASS" : "FAIL");
4147+
}
4148+
expect_stdout: "PASS"
4149+
node_version: ">=6"
4150+
}
4151+
4152+
issue_5866_8: {
4153+
options = {
4154+
side_effects: true,
4155+
unused: true,
4156+
}
4157+
input: {
4158+
var a = {}, b, c;
4159+
[ { p: b }, c ] = [ a, a.p = {} ];
4160+
console.log(b === c ? "PASS" : "FAIL");
4161+
}
4162+
expect: {
4163+
var b, c, a = {};
4164+
[ { p: b }, c ] = [ a, a.p = {} ];
4165+
console.log(b === c ? "PASS" : "FAIL");
4166+
}
4167+
expect_stdout: "PASS"
4168+
node_version: ">=6"
4169+
}
4170+
4171+
issue_5866_9: {
4172+
options = {
4173+
unused: true,
4174+
}
4175+
input: {
4176+
var a = {};
4177+
var [ b, { p: c } ] = [ a.p = {}, a ];
4178+
console.log(b === c ? "PASS" : "FAIL");
4179+
}
4180+
expect: {
4181+
var a = {};
4182+
var [ b, c ] = [ a.p = {}, a.p ];
4183+
console.log(b === c ? "PASS" : "FAIL");
4184+
}
4185+
expect_stdout: "PASS"
4186+
node_version: ">=6"
4187+
}
4188+
4189+
issue_5866_10: {
4190+
options = {
4191+
side_effects: true,
4192+
unused: true,
4193+
}
4194+
input: {
4195+
var a = {}, b, c;
4196+
[ b, { p: c } ] = [ a.p = {}, a ];
4197+
console.log(b === c ? "PASS" : "FAIL");
4198+
}
4199+
expect: {
4200+
var b, c, a = {};
4201+
[ b, c ] = [ a.p = {}, a.p ];
4202+
console.log(b === c ? "PASS" : "FAIL");
4203+
}
4204+
expect_stdout: "PASS"
4205+
node_version: ">=6"
4206+
}
4207+
4208+
issue_5866_11: {
4209+
options = {
4210+
unused: true,
4211+
}
4212+
input: {
4213+
var a = {};
4214+
var { p: { q: b } } = { p: a = { q: {} } };
4215+
console.log(a.q === b ? "PASS" : "FAIL");
4216+
}
4217+
expect: {
4218+
var a = {};
4219+
var b = { p: (a = { q: {} }).q }.p;
4220+
console.log(a.q === b ? "PASS" : "FAIL");
4221+
}
4222+
expect_stdout: "PASS"
4223+
node_version: ">=6"
4224+
}
4225+
4226+
issue_5866_12: {
4227+
options = {
4228+
side_effects: true,
4229+
unused: true,
4230+
}
4231+
input: {
4232+
var a = {}, b;
4233+
({ p: { q: b } } = { p: a = { q: {} } });
4234+
console.log(a.q === b ? "PASS" : "FAIL");
4235+
}
4236+
expect: {
4237+
var b, a = {};
4238+
b = { p: (a = { q: {} }).q }.p;
4239+
console.log(a.q === b ? "PASS" : "FAIL");
4240+
}
4241+
expect_stdout: "PASS"
4242+
node_version: ">=6"
4243+
}

0 commit comments

Comments
 (0)