compress chained compound assignments (#2850)
This commit is contained in:
@@ -320,6 +320,7 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
function reset_def(compressor, def) {
|
function reset_def(compressor, def) {
|
||||||
def.assignments = 0;
|
def.assignments = 0;
|
||||||
|
def.chained = false;
|
||||||
def.direct_access = false;
|
def.direct_access = false;
|
||||||
def.escaped = false;
|
def.escaped = false;
|
||||||
if (def.scope.uses_eval || def.scope.uses_with) {
|
if (def.scope.uses_eval || def.scope.uses_with) {
|
||||||
@@ -485,19 +486,27 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
def(AST_Assign, function(tw) {
|
def(AST_Assign, function(tw) {
|
||||||
var node = this;
|
var node = this;
|
||||||
if (node.operator != "=" || !(node.left instanceof AST_SymbolRef)) return;
|
if (!(node.left instanceof AST_SymbolRef)) return;
|
||||||
var d = node.left.definition();
|
var d = node.left.definition();
|
||||||
if (safe_to_assign(tw, d, node.right)) {
|
var fixed = d.fixed;
|
||||||
d.references.push(node.left);
|
if (!fixed && node.operator != "=") return;
|
||||||
d.assignments++;
|
if (!safe_to_assign(tw, d, node.right)) return;
|
||||||
d.fixed = function() {
|
d.references.push(node.left);
|
||||||
return node.right;
|
d.assignments++;
|
||||||
};
|
if (node.operator != "=") d.chained = true;
|
||||||
mark(tw, d, false);
|
d.fixed = node.operator == "=" ? function() {
|
||||||
node.right.walk(tw);
|
return node.right;
|
||||||
mark(tw, d, true);
|
} : function() {
|
||||||
return true;
|
return make_node(AST_Binary, node, {
|
||||||
}
|
operator: node.operator.slice(0, -1),
|
||||||
|
left: fixed instanceof AST_Node ? fixed : fixed(),
|
||||||
|
right: node.right
|
||||||
|
});
|
||||||
|
};
|
||||||
|
mark(tw, d, false);
|
||||||
|
node.right.walk(tw);
|
||||||
|
mark(tw, d, true);
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
def(AST_Binary, function(tw) {
|
def(AST_Binary, function(tw) {
|
||||||
if (!lazy_op(this.operator)) return;
|
if (!lazy_op(this.operator)) return;
|
||||||
@@ -672,6 +681,32 @@ merge(Compressor.prototype, {
|
|||||||
if (this.bfinally) this.bfinally.walk(tw);
|
if (this.bfinally) this.bfinally.walk(tw);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
def(AST_Unary, function(tw, descend) {
|
||||||
|
var node = this;
|
||||||
|
if (node.operator != "++" && node.operator != "--") return;
|
||||||
|
if (!(node.expression instanceof AST_SymbolRef)) return;
|
||||||
|
var d = node.expression.definition();
|
||||||
|
var fixed = d.fixed;
|
||||||
|
if (!fixed) return;
|
||||||
|
if (!safe_to_assign(tw, d, true)) return;
|
||||||
|
d.references.push(node.expression);
|
||||||
|
d.assignments++;
|
||||||
|
d.chained = true;
|
||||||
|
d.fixed = function() {
|
||||||
|
return make_node(AST_Binary, node, {
|
||||||
|
operator: node.operator.slice(0, -1),
|
||||||
|
left: make_node(AST_UnaryPrefix, node, {
|
||||||
|
operator: "+",
|
||||||
|
expression: fixed instanceof AST_Node ? fixed : fixed()
|
||||||
|
}),
|
||||||
|
right: make_node(AST_Number, node, {
|
||||||
|
value: 1
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
mark(tw, d, true);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
def(AST_VarDef, function(tw, descend) {
|
def(AST_VarDef, function(tw, descend) {
|
||||||
var node = this;
|
var node = this;
|
||||||
var d = node.name.definition();
|
var d = node.name.definition();
|
||||||
@@ -2946,7 +2981,7 @@ merge(Compressor.prototype, {
|
|||||||
if (def.value.has_side_effects(compressor)) {
|
if (def.value.has_side_effects(compressor)) {
|
||||||
def.value.walk(tw);
|
def.value.walk(tw);
|
||||||
}
|
}
|
||||||
if (def.name.fixed_value() === def.value) {
|
if (!node_def.chained && def.name.fixed_value() === def.value) {
|
||||||
fixed_ids[node_def.id] = def;
|
fixed_ids[node_def.id] = def;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3164,7 +3199,7 @@ merge(Compressor.prototype, {
|
|||||||
&& self.variables.get(sym.name) === (node_def = sym.definition())) {
|
&& self.variables.get(sym.name) === (node_def = sym.definition())) {
|
||||||
if (node instanceof AST_Assign) {
|
if (node instanceof AST_Assign) {
|
||||||
node.right.walk(tw);
|
node.right.walk(tw);
|
||||||
if (node.left.fixed_value() === node.right) {
|
if (!node_def.chained && node.left.fixed_value() === node.right) {
|
||||||
fixed_ids[node_def.id] = node;
|
fixed_ids[node_def.id] = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,13 +52,8 @@ collapse_vars_side_effects_1: {
|
|||||||
console.log.bind(console)(s.charAt(i++), s.charAt(i++), s.charAt(i++), 7);
|
console.log.bind(console)(s.charAt(i++), s.charAt(i++), s.charAt(i++), 7);
|
||||||
}
|
}
|
||||||
function f2() {
|
function f2() {
|
||||||
var log = console.log.bind(console),
|
var s = "abcdef", i = 2;
|
||||||
s = "abcdef",
|
console.log.bind(console)(s.charAt(i++), 5, s.charAt(i++), s.charAt(i++), 7);
|
||||||
i = 2,
|
|
||||||
x = s.charAt(i++),
|
|
||||||
y = s.charAt(i++),
|
|
||||||
z = s.charAt(i++);
|
|
||||||
log(x, i, y, z, 7);
|
|
||||||
}
|
}
|
||||||
function f3() {
|
function f3() {
|
||||||
var s = "abcdef",
|
var s = "abcdef",
|
||||||
@@ -72,7 +67,7 @@ collapse_vars_side_effects_1: {
|
|||||||
var i = 10,
|
var i = 10,
|
||||||
x = i += 2,
|
x = i += 2,
|
||||||
y = i += 3;
|
y = i += 3;
|
||||||
console.log.bind(console)(x, i += 4, y, i);
|
console.log.bind(console)(x, i += 4, y, 19);
|
||||||
}
|
}
|
||||||
f1(), f2(), f3(), f4();
|
f1(), f2(), f3(), f4();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,14 +76,12 @@ modified: {
|
|||||||
console.log(a + 1);
|
console.log(a + 1);
|
||||||
console.log(b + 1);
|
console.log(b + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function f1() {
|
function f1() {
|
||||||
var a = 1, b = 2;
|
var a = 1, b = 2;
|
||||||
--b;
|
--b;
|
||||||
console.log(a + 1);
|
console.log(a + 1);
|
||||||
console.log(b + 1);
|
console.log(b + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function f2() {
|
function f2() {
|
||||||
var a = 1, b = 2, c = 3;
|
var a = 1, b = 2, c = 3;
|
||||||
b = c;
|
b = c;
|
||||||
@@ -92,7 +90,6 @@ modified: {
|
|||||||
console.log(a + c);
|
console.log(a + c);
|
||||||
console.log(a + b + c);
|
console.log(a + b + c);
|
||||||
}
|
}
|
||||||
|
|
||||||
function f3() {
|
function f3() {
|
||||||
var a = 1, b = 2, c = 3;
|
var a = 1, b = 2, c = 3;
|
||||||
b *= c;
|
b *= c;
|
||||||
@@ -101,7 +98,6 @@ modified: {
|
|||||||
console.log(a + c);
|
console.log(a + c);
|
||||||
console.log(a + b + c);
|
console.log(a + b + c);
|
||||||
}
|
}
|
||||||
|
|
||||||
function f4() {
|
function f4() {
|
||||||
var a = 1, b = 2, c = 3;
|
var a = 1, b = 2, c = 3;
|
||||||
if (a) {
|
if (a) {
|
||||||
@@ -114,28 +110,26 @@ modified: {
|
|||||||
console.log(a + c);
|
console.log(a + c);
|
||||||
console.log(a + b + c);
|
console.log(a + b + c);
|
||||||
}
|
}
|
||||||
|
|
||||||
function f5(a) {
|
function f5(a) {
|
||||||
B = a;
|
B = a;
|
||||||
console.log(A ? 'yes' : 'no');
|
console.log(typeof A ? "yes" : "no");
|
||||||
console.log(B ? 'yes' : 'no');
|
console.log(typeof B ? "yes" : "no");
|
||||||
}
|
}
|
||||||
|
f0(), f1(), f2(), f3(), f4(), f5();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f0() {
|
function f0() {
|
||||||
var b = 2;
|
var b = 2;
|
||||||
b++;
|
b++;
|
||||||
console.log(2);
|
console.log(2);
|
||||||
console.log(b + 1);
|
console.log(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
function f1() {
|
function f1() {
|
||||||
var b = 2;
|
var b = 2;
|
||||||
--b;
|
--b;
|
||||||
console.log(2);
|
console.log(2);
|
||||||
console.log(b + 1);
|
console.log(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function f2() {
|
function f2() {
|
||||||
3;
|
3;
|
||||||
console.log(4);
|
console.log(4);
|
||||||
@@ -143,16 +137,14 @@ modified: {
|
|||||||
console.log(4);
|
console.log(4);
|
||||||
console.log(7);
|
console.log(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
function f3() {
|
function f3() {
|
||||||
var b = 2;
|
var b = 2;
|
||||||
b *= 3;
|
b *= 3;
|
||||||
console.log(1 + b);
|
console.log(7);
|
||||||
console.log(b + 3);
|
console.log(9);
|
||||||
console.log(4);
|
console.log(4);
|
||||||
console.log(1 + b + 3);
|
console.log(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
function f4() {
|
function f4() {
|
||||||
var b = 2, c = 3;
|
var b = 2, c = 3;
|
||||||
b = c;
|
b = c;
|
||||||
@@ -161,13 +153,33 @@ modified: {
|
|||||||
console.log(1 + c);
|
console.log(1 + c);
|
||||||
console.log(1 + b + c);
|
console.log(1 + b + c);
|
||||||
}
|
}
|
||||||
|
|
||||||
function f5(a) {
|
function f5(a) {
|
||||||
B = a;
|
B = a;
|
||||||
console.log(A ? 'yes' : 'no');
|
console.log(typeof A ? "yes" : "no");
|
||||||
console.log(B ? 'yes' : 'no');
|
console.log(typeof B ? "yes" : "no");
|
||||||
}
|
}
|
||||||
|
f0(), f1(), f2(), f3(), f4(), f5();
|
||||||
}
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"2",
|
||||||
|
"4",
|
||||||
|
"2",
|
||||||
|
"2",
|
||||||
|
"4",
|
||||||
|
"6",
|
||||||
|
"4",
|
||||||
|
"7",
|
||||||
|
"7",
|
||||||
|
"9",
|
||||||
|
"4",
|
||||||
|
"10",
|
||||||
|
"4",
|
||||||
|
"6",
|
||||||
|
"4",
|
||||||
|
"7",
|
||||||
|
"yes",
|
||||||
|
"yes",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_evaluate: {
|
unsafe_evaluate: {
|
||||||
@@ -745,7 +757,7 @@ iife: {
|
|||||||
expect: {
|
expect: {
|
||||||
!function(a, b, c) {
|
!function(a, b, c) {
|
||||||
b++;
|
b++;
|
||||||
console.log(0, 1 * b, 5);
|
console.log(0, 3, 5);
|
||||||
}(1, 2, 3);
|
}(1, 2, 3);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
@@ -766,7 +778,7 @@ iife_new: {
|
|||||||
expect: {
|
expect: {
|
||||||
var A = new function(a, b, c) {
|
var A = new function(a, b, c) {
|
||||||
b++;
|
b++;
|
||||||
console.log(0, 1 * b, 5);
|
console.log(0, 3, 5);
|
||||||
}(1, 2, 3);
|
}(1, 2, 3);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
@@ -5383,3 +5395,43 @@ issue_2836: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lvalues_def_1: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 1;
|
||||||
|
var a = b++, b = NaN;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 1;
|
||||||
|
var a = b++;
|
||||||
|
b = NaN;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "1 NaN"
|
||||||
|
}
|
||||||
|
|
||||||
|
lvalues_def_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 1;
|
||||||
|
var a = b += 1, b = NaN;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 1;
|
||||||
|
var a = b += 1;
|
||||||
|
b = NaN;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "2 NaN"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user