aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2017-11-09 23:30:00 +0800
committerGitHub <noreply@github.com>2017-11-09 23:30:00 +0800
commit1127a2caf305ad1df370c34faf7283e53423cc10 (patch)
tree863afaf693e2f5337849c46615927fd7cbcd3f25
parent246d9d4e83e857a26347944ada65fea95ad6381d (diff)
downloadtracifyjs-1127a2caf305ad1df370c34faf7283e53423cc10.tar.gz
tracifyjs-1127a2caf305ad1df370c34faf7283e53423cc10.zip
fix multiple nested function substitutions (#2458)
fixes #2449
-rw-r--r--lib/compress.js45
-rw-r--r--test/compress/collapse_vars.js1
-rw-r--r--test/compress/drop-unused.js4
-rw-r--r--test/compress/functions.js2
-rw-r--r--test/compress/reduce_vars.js36
5 files changed, 64 insertions, 24 deletions
diff --git a/lib/compress.js b/lib/compress.js
index e457d808..d915e23e 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -313,19 +313,14 @@ merge(Compressor.prototype, {
if (node instanceof AST_SymbolRef) {
var d = node.definition();
d.references.push(node);
+ var value;
if (d.fixed === undefined || !safe_to_read(d) || d.single_use == "m") {
d.fixed = false;
} else if (d.fixed) {
- var value = node.fixed_value();
+ value = node.fixed_value();
if (value && ref_once(d)) {
- if (value instanceof AST_Lambda) {
- d.single_use = d.scope === node.scope
- && !(d.orig[0] instanceof AST_SymbolFunarg)
- || value.is_constant_expression(node.scope);
- } else {
- d.single_use = d.scope === node.scope
- && value.is_constant_expression();
- }
+ d.single_use = value instanceof AST_Lambda
+ || d.scope === node.scope && value.is_constant_expression();
} else {
d.single_use = false;
}
@@ -335,10 +330,9 @@ merge(Compressor.prototype, {
} else {
d.fixed = false;
}
- } else {
- mark_escaped(d, node, value, 0);
}
}
+ mark_escaped(d, node, value, 0);
}
if (node instanceof AST_SymbolCatch) {
node.definition().fixed = false;
@@ -385,10 +379,7 @@ merge(Compressor.prototype, {
d.fixed = node;
loop_ids[d.id] = in_loop;
mark(d, true);
- if (ref_once(d)) {
- d.single_use = d.scope === d.references[0].scope
- || node.is_constant_expression(d.references[0].scope);
- }
+ d.single_use = ref_once(d);
}
var save_ids = safe_ids;
safe_ids = Object.create(null);
@@ -2209,7 +2200,10 @@ merge(Compressor.prototype, {
&& !self.variables.has(def.name)) {
if (scope) {
var scope_def = scope.find_variable(node);
- if (def.undeclared ? !scope_def : scope_def === def) return true;
+ if (def.undeclared ? !scope_def : scope_def === def) {
+ result = "f";
+ return true;
+ }
}
result = false;
}
@@ -4256,11 +4250,20 @@ merge(Compressor.prototype, {
if (fixed instanceof AST_Defun) {
d.fixed = fixed = make_node(AST_Function, fixed, fixed);
}
- if (fixed
- && d.single_use
- && !(fixed instanceof AST_Function
- && (d.escaped && d.scope !== self.scope
- || recursive_ref(compressor, d)))) {
+ if (d.single_use && fixed instanceof AST_Function) {
+ if (d.escaped && d.scope !== self.scope || recursive_ref(compressor, d)) {
+ d.single_use = false;
+ } else if (d.scope !== self.scope || d.orig[0] instanceof AST_SymbolFunarg) {
+ d.single_use = fixed.is_constant_expression(self.scope);
+ if (d.single_use == "f") {
+ var scope = self.scope;
+ do {
+ if (scope.name) scope.name.definition().single_use = false;
+ } while (scope = scope.parent_scope);
+ }
+ }
+ }
+ if (d.single_use && fixed) {
var value = fixed.optimize(compressor);
return value === fixed ? fixed.clone(true) : value;
}
diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js
index fe8e4097..34489717 100644
--- a/test/compress/collapse_vars.js
+++ b/test/compress/collapse_vars.js
@@ -3036,6 +3036,7 @@ issue_2437: {
conditionals: true,
inline: true,
join_vars: true,
+ passes: 2,
reduce_vars: true,
side_effects: true,
sequences: true,
diff --git a/test/compress/drop-unused.js b/test/compress/drop-unused.js
index af6a7a47..ebb0b8fa 100644
--- a/test/compress/drop-unused.js
+++ b/test/compress/drop-unused.js
@@ -1113,7 +1113,7 @@ issue_2105_1: {
options = {
collapse_vars: true,
inline: true,
- passes: 2,
+ passes: 3,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -1153,7 +1153,7 @@ issue_2105_2: {
options = {
collapse_vars: true,
inline: true,
- passes: 2,
+ passes: 3,
properties: true,
pure_getters: "strict",
reduce_vars: true,
diff --git a/test/compress/functions.js b/test/compress/functions.js
index 3c2ccce3..c5aab171 100644
--- a/test/compress/functions.js
+++ b/test/compress/functions.js
@@ -513,7 +513,7 @@ issue_2428: {
options = {
collapse_vars: true,
inline: true,
- passes: 2,
+ passes: 3,
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index 8afea850..d7c5601a 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -3714,6 +3714,7 @@ recursive_inlining_2: {
recursive_inlining_3: {
options = {
+ passes: 2,
reduce_vars: true,
unused: true,
}
@@ -3989,3 +3990,38 @@ issue_2450_5: {
"true",
]
}
+
+issue_2449: {
+ options = {
+ passes: 10,
+ reduce_vars: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ var a = "PASS";
+ function f() {
+ return a;
+ }
+ function g() {
+ return f();
+ }
+ (function() {
+ var a = "FAIL";
+ if (a == a) console.log(g());
+ })();
+ }
+ expect: {
+ var a = "PASS";
+ function g() {
+ return function() {
+ return a;
+ }();
+ }
+ (function() {
+ var a = "FAIL";
+ if (a == a) console.log(g());
+ })();
+ }
+ expect_stdout: "PASS"
+}