aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2019-04-24 02:50:15 +0800
committerGitHub <noreply@github.com>2019-04-24 02:50:15 +0800
commita84beafd1bbdb61ea5fc3662e349f6c960f1ba66 (patch)
treec2a54c6277c58459b5d760f3b801c9e4d11fb844
parentf01cc1e413990a2da37716fbe8627d651f489fff (diff)
downloadtracifyjs-a84beafd1bbdb61ea5fc3662e349f6c960f1ba66.tar.gz
tracifyjs-a84beafd1bbdb61ea5fc3662e349f6c960f1ba66.zip
fix corner case in `assignments` (#3376)
fixes #3375
-rw-r--r--lib/ast.js2
-rw-r--r--lib/compress.js20
-rw-r--r--test/compress/assignment.js22
-rw-r--r--test/compress/drop-unused.js21
4 files changed, 56 insertions, 9 deletions
diff --git a/lib/ast.js b/lib/ast.js
index 09c29b41..f496095a 100644
--- a/lib/ast.js
+++ b/lib/ast.js
@@ -773,7 +773,7 @@ var AST_Label = DEFNODE("Label", "references", {
}
}, AST_Symbol);
-var AST_SymbolRef = DEFNODE("SymbolRef", null, {
+var AST_SymbolRef = DEFNODE("SymbolRef", "fixed", {
$documentation: "Reference to some symbol (not definition/declaration)",
}, AST_Symbol);
diff --git a/lib/compress.js b/lib/compress.js
index 87082807..3fb835f5 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -551,6 +551,7 @@ merge(Compressor.prototype, {
mark_assignment_to_arguments(sym);
return;
}
+ if (sym.fixed) delete sym.fixed;
var d = sym.definition();
var safe = safe_to_assign(tw, d, sym.scope, node.right);
d.assignments++;
@@ -560,7 +561,7 @@ merge(Compressor.prototype, {
var value = eq ? node.right : node;
if (is_modified(compressor, tw, node, value, 0)) return;
if (!eq) d.chained = true;
- d.fixed = eq ? function() {
+ sym.fixed = d.fixed = eq ? function() {
return node.right;
} : function() {
return make_node(AST_Binary, node, {
@@ -574,7 +575,7 @@ merge(Compressor.prototype, {
mark(tw, d, false);
node.right.walk(tw);
mark(tw, d, true);
- mark_escaped(tw, d, sym.scope, node, value, 0, 1);
+ if (eq) mark_escaped(tw, d, sym.scope, node, value, 0, 1);
return true;
});
def(AST_Binary, function(tw) {
@@ -730,6 +731,7 @@ merge(Compressor.prototype, {
this.definition().fixed = false;
});
def(AST_SymbolRef, function(tw, descend, compressor) {
+ if (this.fixed) delete this.fixed;
var d = this.definition();
d.references.push(this);
if (d.references.length == 1
@@ -797,13 +799,14 @@ merge(Compressor.prototype, {
mark_assignment_to_arguments(exp);
return;
}
+ if (exp.fixed) delete exp.fixed;
var d = exp.definition();
var safe = safe_to_assign(tw, d, exp.scope, true);
d.assignments++;
var fixed = d.fixed;
if (!fixed) return;
d.chained = true;
- d.fixed = function() {
+ exp.fixed = d.fixed = function() {
return make_node(AST_Binary, node, {
operator: node.operator.slice(0, -1),
left: make_node(AST_UnaryPrefix, node, {
@@ -874,10 +877,11 @@ merge(Compressor.prototype, {
this.walk(tw);
});
- AST_Symbol.DEFMETHOD("fixed_value", function() {
+ AST_Symbol.DEFMETHOD("fixed_value", function(final) {
var fixed = this.definition().fixed;
- if (!fixed || fixed instanceof AST_Node) return fixed;
- return fixed();
+ if (!fixed) return fixed;
+ if (!final && this.fixed) fixed = this.fixed;
+ return fixed instanceof AST_Node ? fixed : fixed();
});
AST_SymbolRef.DEFMETHOD("is_immutable", function() {
@@ -3514,7 +3518,7 @@ merge(Compressor.prototype, {
if (def.value.has_side_effects(compressor)) {
def.value.walk(tw);
}
- if (!node_def.chained && def.name.fixed_value() === def.value) {
+ if (!node_def.chained && def.name.fixed_value(true) === def.value) {
fixed_ids[node_def.id] = def;
}
}
@@ -3785,7 +3789,7 @@ merge(Compressor.prototype, {
if (node instanceof AST_Assign) {
node.right.walk(tw);
if (node.left === sym) {
- if (!node_def.chained && sym.fixed_value() === node.right) {
+ if (!node_def.chained && sym.fixed_value(true) === node.right) {
fixed_ids[node_def.id] = node;
}
if (!node.write_only) {
diff --git a/test/compress/assignment.js b/test/compress/assignment.js
index ba412583..ece0185d 100644
--- a/test/compress/assignment.js
+++ b/test/compress/assignment.js
@@ -289,3 +289,25 @@ increment_decrement_2: {
}
expect_stdout: "42"
}
+
+issue_3375: {
+ options = {
+ assignments: true,
+ reduce_vars: true,
+ }
+ input: {
+ console.log(typeof function(b) {
+ var a = b += 1;
+ --b;
+ return a;
+ }("object"));
+ }
+ expect: {
+ console.log(typeof function(b) {
+ var a = b += 1;
+ --b;
+ return a;
+ }("object"));
+ }
+ expect_stdout: "string"
+}
diff --git a/test/compress/drop-unused.js b/test/compress/drop-unused.js
index b75c3ac5..74fe3693 100644
--- a/test/compress/drop-unused.js
+++ b/test/compress/drop-unused.js
@@ -2005,3 +2005,24 @@ issue_3233: {
}
expect_stdout: "PASS"
}
+
+issue_3375: {
+ options = {
+ reduce_vars: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ var b = 1;
+ var a = c = [], c = --b + ("function" == typeof f && f());
+ var a = c && c[a];
+ console.log(a, b);
+ }
+ expect: {
+ var b = 1;
+ var a = [], c = --b + ("function" == typeof f && f());
+ a = c && c[a];
+ console.log(a, b);
+ }
+ expect_stdout: "0 0"
+}