fix AST_PropAccess in collapse_vars (take 3) (#2375)

Suppress scanning beyond assignment to `a.b`
This commit is contained in:
Alex Lam S.L
2017-10-18 02:54:51 +08:00
committed by GitHub
parent c1346e06b7
commit 7e5b5cac97
2 changed files with 175 additions and 21 deletions

View File

@@ -838,11 +838,12 @@ merge(Compressor.prototype, {
if (node instanceof AST_Call if (node instanceof AST_Call
|| node instanceof AST_Exit || node instanceof AST_Exit
|| node instanceof AST_PropAccess || node instanceof AST_PropAccess
&& (side_effects || node.has_side_effects(compressor)) && (side_effects || node.expression.may_throw_on_access(compressor))
|| node instanceof AST_SymbolRef || node instanceof AST_SymbolRef
&& (lvalues[node.name] && (lvalues[node.name]
|| side_effects && !references_in_scope(node.definition())) || side_effects && !references_in_scope(node.definition()))
|| (sym = lhs_or_def(node)) && get_symbol(sym).name in lvalues || (sym = lhs_or_def(node))
&& (sym instanceof AST_PropAccess || sym.name in lvalues)
|| parent instanceof AST_Binary && lazy_op(parent.operator) || parent instanceof AST_Binary && lazy_op(parent.operator)
|| parent instanceof AST_Case || parent instanceof AST_Case
|| parent instanceof AST_Conditional || parent instanceof AST_Conditional
@@ -933,30 +934,15 @@ merge(Compressor.prototype, {
} }
} }
function get_symbol(node) {
while (node instanceof AST_PropAccess) node = node.expression;
return node;
}
function get_lvalues(expr) { function get_lvalues(expr) {
var lvalues = Object.create(null); var lvalues = Object.create(null);
if (expr instanceof AST_Unary) return lvalues; if (expr instanceof AST_Unary) return lvalues;
var scope;
var tw = new TreeWalker(function(node, descend) { var tw = new TreeWalker(function(node, descend) {
if (node instanceof AST_Scope) { var sym = node;
var save_scope = scope; while (sym instanceof AST_PropAccess) sym = sym.expression;
descend(); if (sym instanceof AST_SymbolRef || sym instanceof AST_This) {
scope = save_scope;
return true;
}
if (node instanceof AST_PropAccess
|| node instanceof AST_SymbolRef
|| node instanceof AST_This) {
var sym = get_symbol(node);
if (sym instanceof AST_SymbolRef || node instanceof AST_This) {
lvalues[sym.name] = lvalues[sym.name] || is_lhs(node, tw.parent()); lvalues[sym.name] = lvalues[sym.name] || is_lhs(node, tw.parent());
} }
}
}); });
expr[expr instanceof AST_Assign ? "right" : "value"].walk(tw); expr[expr instanceof AST_Assign ? "right" : "value"].walk(tw);
return lvalues; return lvalues;

View File

@@ -2783,3 +2783,171 @@ issue_2364_4: {
} }
expect_stdout: "1 0" expect_stdout: "1 0"
} }
issue_2364_5: {
options = {
collapse_vars: true,
evaluate: true,
pure_getters: true,
properties: true,
reduce_vars: true,
unused: true,
}
input: {
function f0(o, a, h) {
var b = 3 - a;
var obj = o;
var seven = 7;
var prop = 'run';
var t = obj[prop](b)[seven] = h;
return t;
}
}
expect: {
function f0(o, a, h) {
return o.run(3 - a)[7] = h;
}
}
}
issue_2364_6: {
options = {
collapse_vars: true,
pure_getters: true,
}
input: {
function f(a, b) {
var c = a.p;
b.p = "FAIL";
return c;
}
var o = {
p: "PASS"
}
console.log(f(o, o));
}
expect: {
function f(a, b) {
var c = a.p;
b.p = "FAIL";
return c;
}
var o = {
p: "PASS"
}
console.log(f(o, o));
}
expect_stdout: "PASS"
}
issue_2364_7: {
options = {
collapse_vars: true,
pure_getters: true,
}
input: {
function f(a, b) {
var c = a.p;
b.f();
return c;
}
var o = {
p: "PASS",
f: function() {
this.p = "FAIL";
}
}
console.log(f(o, o));
}
expect: {
function f(a, b) {
var c = a.p;
b.f();
return c;
}
var o = {
p: "PASS",
f: function() {
this.p = "FAIL";
}
}
console.log(f(o, o));
}
expect_stdout: "PASS"
}
issue_2364_8: {
options = {
collapse_vars: true,
pure_getters: true,
}
input: {
function f(a, b, c) {
var d = a[b.f = function() {
return "PASS";
}];
return c.f(d);
}
var o = {
f: function() {
return "FAIL";
}
};
console.log(f({}, o, o));
}
expect: {
function f(a, b, c) {
var d = a[b.f = function() {
return "PASS";
}];
return c.f(d);
}
var o = {
f: function() {
return "FAIL";
}
};
console.log(f({}, o, o));
}
expect_stdout: "PASS"
}
issue_2364_9: {
options = {
collapse_vars: true,
pure_getters: true,
}
input: {
function f(a, b) {
var d = a();
return b.f(d);
}
var o = {
f: function() {
return "FAIL";
}
};
console.log(f(function() {
o.f = function() {
return "PASS";
};
}, o));
}
expect: {
function f(a, b) {
var d = a();
return b.f(d);
}
var o = {
f: function() {
return "FAIL";
}
};
console.log(f(function() {
o.f = function() {
return "PASS";
};
}, o));
}
expect_stdout: "PASS"
}