aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/compress.js51
-rw-r--r--test/compress/dead-code.js29
-rw-r--r--test/compress/drop-unused.js34
3 files changed, 96 insertions, 18 deletions
diff --git a/lib/compress.js b/lib/compress.js
index ad47621a..33943ff0 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -3441,6 +3441,7 @@ merge(Compressor.prototype, {
return true;
}
if (node instanceof AST_Scope) {
+ if (node === self) return;
scopes.push(node);
descend();
scopes.pop();
@@ -3451,6 +3452,7 @@ merge(Compressor.prototype, {
result = false;
return true;
}
+ if (self.variables.has(node.name)) return true;
var def = node.definition();
if (member(def.scope, scopes)) return true;
if (scope) {
@@ -6429,24 +6431,37 @@ merge(Compressor.prototype, {
var ASSIGN_OPS = makePredicate("+ - / * % >> << >>> | ^ &");
var ASSIGN_OPS_COMMUTATIVE = makePredicate("* | ^ &");
OPT(AST_Assign, function(self, compressor) {
- var def;
- if (compressor.option("dead_code")
- && self.left instanceof AST_SymbolRef
- && (def = self.left.definition()).scope === compressor.find_parent(AST_Lambda)) {
- if (self.left.is_immutable()) return strip_assignment();
- var level = 0, node, parent = self;
- do {
- node = parent;
- parent = compressor.parent(level++);
- if (parent instanceof AST_Exit) {
- if (in_try(level, parent)) break;
- if (is_reachable(def.scope, [ def ])) break;
- def.fixed = false;
- return strip_assignment();
- }
- } while (parent instanceof AST_Binary && parent.right === node
- || parent instanceof AST_Sequence && parent.tail_node() === node
- || parent instanceof AST_UnaryPrefix);
+ if (compressor.option("dead_code")) {
+ if (self.left instanceof AST_PropAccess) {
+ var exp = self.left.expression;
+ if (exp instanceof AST_Lambda
+ || !compressor.has_directive("use strict")
+ && exp instanceof AST_Constant
+ && !exp.may_throw_on_access(compressor)) {
+ return self.left instanceof AST_Dot ? self.right : make_sequence(self, [
+ self.left.property,
+ self.right
+ ]).optimize(compressor);
+ }
+ } else if (self.left instanceof AST_SymbolRef) {
+ var def = self.left.definition();
+ if (def.scope === compressor.find_parent(AST_Lambda)) {
+ if (self.left.is_immutable()) return strip_assignment();
+ var level = 0, node, parent = self;
+ do {
+ node = parent;
+ parent = compressor.parent(level++);
+ if (parent instanceof AST_Exit) {
+ if (in_try(level, parent)) break;
+ if (is_reachable(def.scope, [ def ])) break;
+ def.fixed = false;
+ return strip_assignment();
+ }
+ } while (parent instanceof AST_Binary && parent.right === node
+ || parent instanceof AST_Sequence && parent.tail_node() === node
+ || parent instanceof AST_UnaryPrefix);
+ }
+ }
}
self = self.lift_sequences(compressor);
if (!compressor.option("assignments")) return self;
diff --git a/test/compress/dead-code.js b/test/compress/dead-code.js
index 190a3243..501d55ec 100644
--- a/test/compress/dead-code.js
+++ b/test/compress/dead-code.js
@@ -1013,3 +1013,32 @@ issue_3406: {
}
expect_stdout: "true"
}
+
+function_assign: {
+ options = {
+ dead_code: true,
+ }
+ input: {
+ console.log(function() {
+ var a = "PASS";
+ function h(c) {
+ return c;
+ }
+ h.p = function(b) {
+ return b;
+ }.p = a;
+ return h;
+ }().p);
+ }
+ expect: {
+ console.log(function() {
+ var a = "PASS";
+ function h(c) {
+ return c;
+ }
+ h.p = a;
+ return h;
+ }().p);
+ }
+ expect_stdout: "PASS"
+}
diff --git a/test/compress/drop-unused.js b/test/compress/drop-unused.js
index f77072b0..7cb2e899 100644
--- a/test/compress/drop-unused.js
+++ b/test/compress/drop-unused.js
@@ -2187,3 +2187,37 @@ issue_3515_3: {
}
expect_stdout: "PASS"
}
+
+function_assign: {
+ options = {
+ pure_getters: "strict",
+ reduce_vars: true,
+ side_effects: true,
+ unused: true,
+ }
+ input: {
+ console.log(function() {
+ var a = "PASS";
+ function g(b) {
+ return b;
+ }
+ g.p = a;
+ function h(c) {
+ return c;
+ }
+ h.p = a;
+ return h;
+ }().p);
+ }
+ expect: {
+ console.log(function() {
+ var a = "PASS";
+ function h(c) {
+ return c;
+ }
+ h.p = a;
+ return h;
+ }().p);
+ }
+ expect_stdout: "PASS"
+}