aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2020-10-07 15:01:39 +0100
committerGitHub <noreply@github.com>2020-10-07 22:01:39 +0800
commit9c0feb69e5cdd3d491c6b0600fc964a41a774710 (patch)
treedf6b2bb2d84ddc47661359a7e1ff5ec9c27eea1f
parentbc6e105174eb67547c2bd988899e4c4f2d8f6ada (diff)
downloadtracifyjs-9c0feb69e5cdd3d491c6b0600fc964a41a774710.tar.gz
tracifyjs-9c0feb69e5cdd3d491c6b0600fc964a41a774710.zip
fix corner case in `reduce_vars` (#4189)
fixes #4188
-rw-r--r--lib/compress.js30
-rw-r--r--lib/scope.js2
-rw-r--r--test/compress/reduce_vars.js66
3 files changed, 80 insertions, 18 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 29cc82a9..fa1cc383 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -354,6 +354,13 @@ merge(Compressor.prototype, {
return orig.length == 1 && orig[0] instanceof AST_SymbolFunarg;
}
+ function cross_scope(def, sym) {
+ do {
+ if (def === sym) return false;
+ if (sym instanceof AST_Scope) return true;
+ } while (sym = sym.parent_scope);
+ }
+
(function(def) {
def(AST_Node, noop);
@@ -506,6 +513,7 @@ merge(Compressor.prototype, {
function ref_once(compressor, def) {
return compressor.option("unused")
&& !def.scope.pinned()
+ && def.single_use !== false
&& def.references.length - def.recursive_refs == 1;
}
@@ -840,11 +848,13 @@ merge(Compressor.prototype, {
&& d.orig[0] instanceof AST_SymbolDefun) {
tw.loop_ids[d.id] = tw.in_loop;
}
- var value;
- if (d.fixed === undefined || !safe_to_read(tw, d)) {
+ if (d.fixed === false) {
+ var redef = d.redefined();
+ if (redef && cross_scope(d.scope, this.scope)) redef.single_use = false;
+ } else if (d.fixed === undefined || !safe_to_read(tw, d)) {
d.fixed = false;
} else if (d.fixed) {
- value = this.fixed_value();
+ var value = this.fixed_value();
var recursive = recursive_ref(tw, d);
if (recursive) {
d.recursive_refs++;
@@ -5140,13 +5150,6 @@ merge(Compressor.prototype, {
return rhs.right;
}
- function cross_scope(def, sym) {
- do {
- if (def === sym) return false;
- if (sym instanceof AST_Scope) return true;
- } while (sym = sym.parent_scope);
- }
-
function scan_ref_scoped(node, descend, init) {
if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) {
var def = node.left.definition();
@@ -8310,13 +8313,6 @@ merge(Compressor.prototype, {
return lhs instanceof AST_SymbolRef || lhs.TYPE === self.TYPE;
}
- function find_variable(compressor, name) {
- var level = 0, node;
- while (node = compressor.parent(level++)) {
- if (node.variables) return node.find_variable(name);
- }
- }
-
OPT(AST_Undefined, function(self, compressor) {
if (compressor.option("unsafe_undefined")) {
var undef = find_scope(compressor).find_variable("undefined");
diff --git a/lib/scope.js b/lib/scope.js
index 209ac235..ec2c1f6d 100644
--- a/lib/scope.js
+++ b/lib/scope.js
@@ -196,7 +196,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
var sym = node.scope.find_variable(name);
if (!sym) {
sym = self.def_global(node);
- } else if (sym.scope instanceof AST_Lambda && name == "arguments") {
+ } else if (name == "arguments" && sym.scope instanceof AST_Lambda) {
sym.scope.uses_arguments = true;
}
if (name == "eval") {
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index 414d6646..ea3703c1 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -7535,3 +7535,69 @@ global_assign: {
}
expect_stdout: "PASS"
}
+
+issue_4188_1: {
+ options = {
+ reduce_vars: true,
+ unused: true,
+ }
+ input: {
+ (function() {
+ try {
+ while (A)
+ var a = function() {}, b = a;
+ } catch (a) {
+ console.log(function() {
+ return typeof a;
+ }(), typeof b);
+ }
+ })();
+ }
+ expect: {
+ (function() {
+ try {
+ while (A)
+ var a = function() {}, b = a;
+ } catch (a) {
+ console.log(function() {
+ return typeof a;
+ }(), typeof b);
+ }
+ })();
+ }
+ expect_stdout: "object undefined"
+}
+
+issue_4188_2: {
+ options = {
+ reduce_vars: true,
+ unused: true,
+ }
+ input: {
+ (function() {
+ try {
+ throw 42;
+ } catch (a) {
+ console.log(function() {
+ return typeof a;
+ }(), typeof b);
+ }
+ while (!console)
+ var a = function() {}, b = a;
+ })();
+ }
+ expect: {
+ (function() {
+ try {
+ throw 42;
+ } catch (a) {
+ console.log(function() {
+ return typeof a;
+ }(), typeof b);
+ }
+ while (!console)
+ var a = function() {}, b = a;
+ })();
+ }
+ expect_stdout: "number undefined"
+}