[Pkg-javascript-commits] [uglifyjs] 109/228: fix `AST_Node.optimize()` (#1602)
Jonas Smedegaard
dr at jones.dk
Sat Apr 15 14:25:21 UTC 2017
This is an automated email from the git hooks/post-receive script.
js pushed a commit to branch master
in repository uglifyjs.
commit 8223b2e0db4cc41d467d9b94b05511a36c320184
Author: Alex Lam S.L <alexlamsl at gmail.com>
Date: Wed Mar 15 18:44:13 2017 +0800
fix `AST_Node.optimize()` (#1602)
Liberal use of `Compressor.transform()` and `AST_Node.optimize()` presents an issue for look-up operations like `TreeWalker.in_boolean_context()` and `TreeWalker.parent()`.
This is an incremental fix such that `AST_Node.optimize()` would now contain the correct stack information when called correctly.
---
lib/compress.js | 69 +++++++++++-------------
lib/utils.js | 4 +-
test/compress/transform.js | 129 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 164 insertions(+), 38 deletions(-)
diff --git a/lib/compress.js b/lib/compress.js
index ab4c3c2..59a9668 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -152,13 +152,14 @@ merge(Compressor.prototype, {
was_scope = true;
}
descend(node, this);
- node = node.optimize(this);
- if (was_scope && node instanceof AST_Scope) {
- node.drop_unused(this);
- descend(node, this);
+ descend(node, this);
+ var opt = node.optimize(this);
+ if (was_scope && opt instanceof AST_Scope) {
+ opt.drop_unused(this);
+ descend(opt, this);
}
- node._squeezed = true;
- return node;
+ if (opt === node) opt._squeezed = true;
+ return opt;
}
});
@@ -171,8 +172,7 @@ merge(Compressor.prototype, {
if (compressor.has_directive("use asm")) return self;
var opt = optimizer(self, compressor);
opt._optimized = true;
- if (opt === self) return opt;
- return opt.transform(compressor);
+ return opt;
});
};
@@ -914,7 +914,7 @@ merge(Compressor.prototype, {
if (stat instanceof AST_LoopControl) {
var lct = compressor.loopcontrol_target(stat.label);
if ((stat instanceof AST_Break
- && lct instanceof AST_BlockStatement
+ && !(lct instanceof AST_IterationStatement)
&& loop_body(lct) === self) || (stat instanceof AST_Continue
&& loop_body(lct) === self)) {
if (stat.label) {
@@ -1646,8 +1646,8 @@ merge(Compressor.prototype, {
return thing && thing.aborts();
};
(function(def){
- def(AST_Statement, function(){ return null });
- def(AST_Jump, function(){ return this });
+ def(AST_Statement, return_null);
+ def(AST_Jump, return_this);
function block_aborts(){
var n = this.body.length;
return n > 0 && aborts(this.body[n - 1]);
@@ -2077,14 +2077,6 @@ merge(Compressor.prototype, {
// drop_side_effect_free()
// remove side-effect-free parts which only affects return value
(function(def){
- function return_this() {
- return this;
- }
-
- function return_null() {
- return null;
- }
-
// Drop side-effect-free elements from an array of expressions.
// Returns an array of expressions with side-effects or null
// if all elements were dropped. Note: original array may be
@@ -2358,7 +2350,7 @@ merge(Compressor.prototype, {
extract_declarations_from_unreachable_code(compressor, self.alternative, a);
}
a.push(self.body);
- return make_node(AST_BlockStatement, self, { body: a }).transform(compressor);
+ return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
}
} else {
compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
@@ -2366,7 +2358,7 @@ merge(Compressor.prototype, {
var a = [];
extract_declarations_from_unreachable_code(compressor, self.body, a);
if (self.alternative) a.push(self.alternative);
- return make_node(AST_BlockStatement, self, { body: a }).transform(compressor);
+ return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
}
}
}
@@ -2385,8 +2377,8 @@ merge(Compressor.prototype, {
}
if (is_empty(self.body) && is_empty(self.alternative)) {
return make_node(AST_SimpleStatement, self.condition, {
- body: self.condition
- }).transform(compressor);
+ body: self.condition.clone()
+ }).optimize(compressor);
}
if (self.body instanceof AST_SimpleStatement
&& self.alternative instanceof AST_SimpleStatement) {
@@ -2396,7 +2388,7 @@ merge(Compressor.prototype, {
consequent : statement_to_expression(self.body),
alternative : statement_to_expression(self.alternative)
})
- }).transform(compressor);
+ }).optimize(compressor);
}
if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) {
if (self_condition_length === negated_length && !negated_is_best
@@ -2412,14 +2404,14 @@ merge(Compressor.prototype, {
left : negated,
right : statement_to_expression(self.body)
})
- }).transform(compressor);
+ }).optimize(compressor);
return make_node(AST_SimpleStatement, self, {
body: make_node(AST_Binary, self, {
operator : "&&",
left : self.condition,
right : statement_to_expression(self.body)
})
- }).transform(compressor);
+ }).optimize(compressor);
}
if (self.body instanceof AST_EmptyStatement
&& self.alternative
@@ -2430,7 +2422,7 @@ merge(Compressor.prototype, {
left : self.condition,
right : statement_to_expression(self.alternative)
})
- }).transform(compressor);
+ }).optimize(compressor);
}
if (self.body instanceof AST_Exit
&& self.alternative instanceof AST_Exit
@@ -2440,18 +2432,21 @@ merge(Compressor.prototype, {
condition : self.condition,
consequent : self.body.value || make_node(AST_Undefined, self.body),
alternative : self.alternative.value || make_node(AST_Undefined, self.alternative)
- })
- }).transform(compressor);
+ }).transform(compressor)
+ }).optimize(compressor);
}
if (self.body instanceof AST_If
&& !self.body.alternative
&& !self.alternative) {
- self.condition = make_node(AST_Binary, self.condition, {
- operator: "&&",
- left: self.condition,
- right: self.body.condition
- }).transform(compressor);
- self.body = self.body.body;
+ self = make_node(AST_If, self, {
+ condition: make_node(AST_Binary, self.condition, {
+ operator: "&&",
+ left: self.condition,
+ right: self.body.condition
+ }),
+ body: self.body.body,
+ alternative: null
+ });
}
if (aborts(self.body)) {
if (self.alternative) {
@@ -2459,7 +2454,7 @@ merge(Compressor.prototype, {
self.alternative = null;
return make_node(AST_BlockStatement, self, {
body: [ self, alt ]
- }).transform(compressor);
+ }).optimize(compressor);
}
}
if (aborts(self.alternative)) {
@@ -2469,7 +2464,7 @@ merge(Compressor.prototype, {
self.alternative = null;
return make_node(AST_BlockStatement, self, {
body: [ self, body ]
- }).transform(compressor);
+ }).optimize(compressor);
}
return self;
});
diff --git a/lib/utils.js b/lib/utils.js
index da66354..fdb2047 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -126,9 +126,11 @@ function merge(obj, ext) {
return count;
};
-function noop() {};
+function noop() {}
function return_false() { return false; }
function return_true() { return true; }
+function return_this() { return this; }
+function return_null() { return null; }
var MAP = (function(){
function MAP(a, f, backwards) {
diff --git a/test/compress/transform.js b/test/compress/transform.js
new file mode 100644
index 0000000..7b616e4
--- /dev/null
+++ b/test/compress/transform.js
@@ -0,0 +1,129 @@
+booleans_evaluate: {
+ options = {
+ booleans: true,
+ evaluate: true,
+ }
+ input: {
+ console.log(typeof void 0 != "undefined");
+ console.log(1 == 1, 1 === 1)
+ console.log(1 != 1, 1 !== 1)
+ }
+ expect: {
+ console.log(!1);
+ console.log(!0, !0);
+ console.log(!1, !1);
+ }
+}
+
+booleans_global_defs: {
+ options = {
+ booleans: true,
+ evaluate: true,
+ global_defs: {
+ A: true,
+ },
+ }
+ input: {
+ console.log(A == 1);
+ }
+ expect: {
+ console.log(!0);
+ }
+}
+
+condition_evaluate: {
+ options = {
+ booleans: true,
+ dead_code: false,
+ evaluate: true,
+ loops: false,
+ }
+ input: {
+ while (1 === 2);
+ for (; 1 == true;);
+ if (void 0 == null);
+ }
+ expect: {
+ while (!1);
+ for (; !0;);
+ if (!0);
+ }
+}
+
+if_else_empty: {
+ options = {
+ conditionals: true,
+ }
+ input: {
+ if ({} ? a : b); else {}
+ }
+ expect: {
+ !{} ? b : a;
+ }
+}
+
+label_if_break: {
+ options = {
+ conditionals: true,
+ dead_code: true,
+ evaluate: true,
+ }
+ input: {
+ L: if (true) {
+ a;
+ break L;
+ }
+ }
+ expect: {
+ a;
+ }
+}
+
+while_if_break: {
+ options = {
+ conditionals: true,
+ loops: true,
+ sequences: true,
+ }
+ input: {
+ while (a) {
+ if (b) if(c) d;
+ if (e) break;
+ }
+ }
+ expect: {
+ for(; a && (b && c && d, !e););
+ }
+}
+
+if_return: {
+ options = {
+ booleans: true,
+ conditionals: true,
+ if_return: true,
+ sequences: true,
+ }
+ input: {
+ function f(w, x, y, z) {
+ if (x) return;
+ if (w) {
+ if (y) return;
+ } else if (z) return;
+ if (x == y) return true;
+
+ if (x) w();
+ if (y) z();
+ return true;
+ }
+ }
+ expect: {
+ function f(w, x, y, z) {
+ if (!x) {
+ if (w) {
+ if (y) return;
+ } else if (z) return;
+ return x == y || (x && w(), y && z(), !0);
+ }
+ }
+ }
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/uglifyjs.git
More information about the Pkg-javascript-commits
mailing list