fix AST_PropAccess in collapse_vars (take 3) (#2375)
Suppress scanning beyond assignment to `a.b`
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user