Skip to content

Commit

Permalink
introduce assignments (#3345)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlamsl committed Mar 18, 2019
1 parent 7aa7f21 commit 615ae37
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 9 deletions.
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -605,6 +605,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `arguments` (default: `true`) -- replace `arguments[index]` with function
parameter name whenever possible.

- `assignments` (default: `true`) -- apply optimizations to assignment expressions.

- `booleans` (default: `true`) -- various optimizations for boolean context,
for example `!!a ? b : c → a ? b : c`

Expand Down
34 changes: 27 additions & 7 deletions lib/compress.js
Expand Up @@ -49,6 +49,7 @@ function Compressor(options, false_by_default) {
TreeTransformer.call(this, this.before, this.after);
this.options = defaults(options, {
arguments : !false_by_default,
assignments : !false_by_default,
booleans : !false_by_default,
collapse_vars : !false_by_default,
comparisons : !false_by_default,
Expand Down Expand Up @@ -2415,6 +2416,10 @@ merge(Compressor.prototype, {
def(AST_Sequence, function(compressor) {
return this.tail_node().is_number(compressor);
});
def(AST_SymbolRef, function(compressor) {
var fixed = this.fixed_value();
return fixed && fixed.is_number(compressor);
});
var unary = makePredicate("+ - ~ ++ --");
def(AST_Unary, function() {
return unary[this.operator];
Expand All @@ -2426,22 +2431,26 @@ merge(Compressor.prototype, {
// methods to determine if an expression has a string result type
(function(def) {
def(AST_Node, return_false);
def(AST_String, return_true);
def(AST_UnaryPrefix, function() {
return this.operator == "typeof";
def(AST_Assign, function(compressor) {
return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor);
});
def(AST_Binary, function(compressor) {
return this.operator == "+" &&
(this.left.is_string(compressor) || this.right.is_string(compressor));
});
def(AST_Assign, function(compressor) {
return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor);
def(AST_Conditional, function(compressor) {
return this.consequent.is_string(compressor) && this.alternative.is_string(compressor);
});
def(AST_Sequence, function(compressor) {
return this.tail_node().is_string(compressor);
});
def(AST_Conditional, function(compressor) {
return this.consequent.is_string(compressor) && this.alternative.is_string(compressor);
def(AST_String, return_true);
def(AST_SymbolRef, function(compressor) {
var fixed = this.fixed_value();
return fixed && fixed.is_string(compressor);
});
def(AST_UnaryPrefix, function() {
return this.operator == "typeof";
});
})(function(node, func) {
node.DEFMETHOD("is_string", func);
Expand Down Expand Up @@ -6010,6 +6019,7 @@ merge(Compressor.prototype, {
|| parent instanceof AST_Sequence && parent.tail_node() === node);
}
self = self.lift_sequences(compressor);
if (!compressor.option("assignments")) return self;
if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary) {
// x = expr1 OP expr2
if (self.right.left instanceof AST_SymbolRef
Expand All @@ -6028,6 +6038,16 @@ merge(Compressor.prototype, {
self.right = self.right.left;
}
}
if ((self.operator == "+=" || self.operator == "-=")
&& self.left.is_number(compressor)
&& self.right instanceof AST_Number
&& self.right.getValue() === 1) {
var op = self.operator.slice(0, -1);
return make_node(AST_UnaryPrefix, self, {
operator: op + op,
expression: self.left
});
}
return self;

function in_try(level, node) {
Expand Down
1 change: 1 addition & 0 deletions test/compress/asm.js
@@ -1,5 +1,6 @@
asm_mixed: {
options = {
assignments: true,
booleans: true,
comparisons: true,
conditionals: true,
Expand Down
53 changes: 53 additions & 0 deletions test/compress/assignment.js
@@ -1,5 +1,6 @@
op_equals_left_local_var: {
options = {
assignments: true,
evaluate: true,
}
input: {
Expand Down Expand Up @@ -60,6 +61,7 @@ op_equals_left_local_var: {

op_equals_right_local_var: {
options = {
assignments: true,
evaluate: true,
}
input: {
Expand Down Expand Up @@ -123,6 +125,7 @@ op_equals_right_local_var: {
}
op_equals_left_global_var: {
options = {
assignments: true,
evaluate: true,
}
input: {
Expand Down Expand Up @@ -179,6 +182,7 @@ op_equals_left_global_var: {

op_equals_right_global_var: {
options = {
assignments: true,
evaluate: true,
}
input: {
Expand Down Expand Up @@ -236,3 +240,52 @@ op_equals_right_global_var: {
x = g() & x;
}
}

increment_decrement_1: {
options = {
assignments: true,
reduce_vars: true,
}
input: {
console.log(function(a) {
a += 1;
a -= 1;
return a;
}(42));
}
expect: {
console.log(function(a){
++a;
--a;
return a;
}(42));
}
expect_stdout: "42"
}

increment_decrement_2: {
options = {
assignments: true,
passes: 2,
reduce_vars: true,
}
input: {
console.log(function(a) {
a = a + 1;
a = a - 1;
a += 1;
a -= 1;
return a;
}(42));
}
expect: {
console.log(function(a){
++a;
--a;
++a;
--a;
return a;
}(42));
}
expect_stdout: "42"
}
2 changes: 1 addition & 1 deletion test/compress/collapse_vars.js
Expand Up @@ -944,7 +944,7 @@ collapse_vars_misc1: {
function f5(x) { var z = foo(); return (5 - window.x) / z }
function f6() { return window.a * window.z && zap() }
function f7() { var b = window.a * window.z; return b + b }
function f8() { var b = window.a * window.z; return b + (b + 5) }
function f8() { var b = window.a * window.z; return b + (5 + b) }
function f9() { var b = window.a * window.z; return bar() || b }
function f10(x) { var a = 5; return a += 3; }
function f11(x) { var a = 5; return a += 2; }
Expand Down
1 change: 1 addition & 0 deletions test/compress/conditionals.js
Expand Up @@ -1367,6 +1367,7 @@ cond_seq_assign_2: {

cond_seq_assign_3: {
options = {
assignments: true,
conditionals: true,
}
input: {
Expand Down
35 changes: 34 additions & 1 deletion test/compress/evaluate.js
Expand Up @@ -1540,7 +1540,7 @@ issue_2926_2: {
expect_stdout: "function"
}

issue_2968: {
issue_2968_1: {
options = {
collapse_vars: true,
evaluate: true,
Expand Down Expand Up @@ -1571,6 +1571,39 @@ issue_2968: {
expect_stdout: "PASS"
}

issue_2968_2: {
options = {
assignments: true,
collapse_vars: true,
evaluate: true,
inline: true,
passes: 2,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
var c = "FAIL";
(function() {
(function(a, b) {
a <<= 0;
a && (a[(c = "PASS", 0 >>> (b += 1))] = 0);
})(42, -42);
})();
console.log(c);
}
expect: {
var c = "FAIL";
(function() {
a = 42,
((a <<= 0) && (a[(c = "PASS", 0)] = 0));
var a;
})();
console.log(c);
}
expect_stdout: "PASS"
}

truthy_conditionals: {
options = {
conditionals: true,
Expand Down
5 changes: 5 additions & 0 deletions test/compress/functions.js
Expand Up @@ -358,6 +358,7 @@ inner_ref: {

issue_2107: {
options = {
assignments: true,
collapse_vars: true,
inline: true,
passes: 3,
Expand Down Expand Up @@ -387,6 +388,7 @@ issue_2107: {

issue_2114_1: {
options = {
assignments: true,
collapse_vars: true,
if_return: true,
inline: true,
Expand Down Expand Up @@ -419,6 +421,7 @@ issue_2114_1: {

issue_2114_2: {
options = {
assignments: true,
collapse_vars: true,
if_return: true,
inline: true,
Expand Down Expand Up @@ -1223,6 +1226,7 @@ issue_2630_1: {

issue_2630_2: {
options = {
assignments: true,
collapse_vars: true,
inline: true,
passes: 2,
Expand Down Expand Up @@ -1320,6 +1324,7 @@ issue_2630_4: {

issue_2630_5: {
options = {
assignments: true,
collapse_vars: true,
inline: true,
reduce_vars: true,
Expand Down

0 comments on commit 615ae37

Please sign in to comment.