Skip to content

Commit

Permalink
fix corner case in reduce_vars (#5964)
Browse files Browse the repository at this point in the history
fixes #5963
  • Loading branch information
alexlamsl authored Nov 22, 2024
1 parent d02156d commit 111746b
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 23 deletions.
45 changes: 22 additions & 23 deletions lib/compress.js
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,15 @@ Compressor.prototype.compress = function(node) {
return !assigned || assigned === seq;
}

function dot(expr, tw) {
while (expr instanceof AST_Assign && expr.operator == "=") {
var lhs = expr.left;
if (lhs instanceof AST_SymbolRef) access(tw, lhs.definition());
expr = expr.right;
}
if (expr instanceof AST_SymbolRef) access(tw, expr.definition());
}

function mark(tw, def) {
tw.safe_ids[def.id] = {};
}
Expand Down Expand Up @@ -1032,7 +1041,9 @@ Compressor.prototype.compress = function(node) {
return true;
}
mark_assignment_to_arguments(left);
return;
descend();
if (left instanceof AST_PropAccess) dot(left.expression, tw);
return true;
case "&&=":
case "||=":
case "??=":
Expand Down Expand Up @@ -1108,6 +1119,7 @@ Compressor.prototype.compress = function(node) {
if (!(sym instanceof AST_SymbolRef)) {
mark_assignment_to_arguments(sym);
walk();
if (sym instanceof AST_PropAccess) dot(sym.expression, tw);
return;
}
var d = sym.definition();
Expand Down Expand Up @@ -1291,15 +1303,7 @@ Compressor.prototype.compress = function(node) {
def(AST_Dot, function(tw, descend) {
descend();
var node = this;
var expr = node.expression;
if (!node.optional) {
while (expr instanceof AST_Assign && expr.operator == "=") {
var lhs = expr.left;
if (lhs instanceof AST_SymbolRef) access(tw, lhs.definition());
expr = expr.right;
}
if (expr instanceof AST_SymbolRef) access(tw, expr.definition());
}
if (!node.optional && !is_direct_assignment(node, tw.parent())) dot(node.expression, tw);
return true;
});
def(AST_For, function(tw, descend, compressor) {
Expand Down Expand Up @@ -1410,12 +1414,7 @@ Compressor.prototype.compress = function(node) {
prop.walk(tw);
pop(tw);
} else {
while (expr instanceof AST_Assign && expr.operator == "=") {
var lhs = expr.left;
if (lhs instanceof AST_SymbolRef) access(tw, lhs.definition());
expr = expr.right;
}
if (expr instanceof AST_SymbolRef) access(tw, expr.definition());
if (!is_direct_assignment(node, tw.parent())) dot(expr, tw);
prop.walk(tw);
}
return true;
Expand Down Expand Up @@ -1974,6 +1973,13 @@ Compressor.prototype.compress = function(node) {
return array;
}

function is_direct_assignment(node, parent) {
if (parent instanceof AST_Assign) return parent.operator == "=" && parent.left === node;
if (parent instanceof AST_DefaultValue) return parent.name === node;
if (parent instanceof AST_DestructuredArray) return true;
if (parent instanceof AST_DestructuredKeyVal) return parent.value === node;
}

function is_lexical_definition(stat) {
return stat instanceof AST_Const || stat instanceof AST_DefClass || stat instanceof AST_Let;
}
Expand Down Expand Up @@ -2614,13 +2620,6 @@ Compressor.prototype.compress = function(node) {
}
}

function is_direct_assignment(node, parent) {
if (parent instanceof AST_Assign) return parent.operator == "=" && parent.left === node;
if (parent instanceof AST_DefaultValue) return parent.name === node;
if (parent instanceof AST_DestructuredArray) return true;
if (parent instanceof AST_DestructuredKeyVal) return parent.value === node;
}

function should_stop(node, parent) {
if (node === rvalue) return true;
if (parent instanceof AST_For) {
Expand Down
23 changes: 23 additions & 0 deletions test/compress/default-values.js
Original file line number Diff line number Diff line change
Expand Up @@ -3135,3 +3135,26 @@ issue_5863: {
expect_stdout: "function"
node_version: ">=6"
}

issue_5963: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
var a = Object.create(null);
[ a.PASS = 42 ] = [];
a.FAIL;
for (var p in a)
console.log(p);
}
expect: {
var a = Object.create(null);
[ a.PASS = 42 ] = [];
for (var p in a)
console.log(p);
}
expect_stdout: "PASS"
node_version: ">=6"
}
46 changes: 46 additions & 0 deletions test/compress/destructured.js
Original file line number Diff line number Diff line change
Expand Up @@ -4289,3 +4289,49 @@ issue_5899_2: {
]
node_version: ">=6"
}

issue_5963_array: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
var a = Object.create(null);
[ a.PASS ] = [ 42 ];
a.FAIL;
for (var p in a)
console.log(p);
}
expect: {
var a = Object.create(null);
[ a.PASS ] = [ 42 ];
for (var p in a)
console.log(p);
}
expect_stdout: "PASS"
node_version: ">=6"
}

issue_5963_object: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
var a = Object.create(null);
({ p: a.PASS } = { p: 42 });
a.FAIL;
for (var p in a)
console.log(p);
}
expect: {
var a = Object.create(null);
({ p: a.PASS } = { p: 42 });
for (var p in a)
console.log(p);
}
expect_stdout: "PASS"
node_version: ">=6"
}
122 changes: 122 additions & 0 deletions test/compress/properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -2046,3 +2046,125 @@ issue_5949_2: {
}
expect_stdout: "PASS"
}

issue_5963_dot: {
options = {
collapse_vars: true,
evaluate: true,
pure_getters: "strict",
reduce_vars: true,
}
input: {
var a = "PASS", b;
try {
b.p = (b.q = null, a = "FAIL 1", !0);
console.log("FAIL 2")
} catch (e) {
console.log(a);
}
}
expect: {
var a = "PASS", b;
try {
b.p = (b.q = null, a = "FAIL 1", !0);
console.log("FAIL 2")
} catch (e) {
console.log(a);
}
}
expect_stdout: "PASS"
}

issue_5963_sub: {
options = {
collapse_vars: true,
evaluate: true,
pure_getters: "strict",
reduce_vars: true,
}
input: {
var a = "PASS", b;
try {
b[42] = (b.q = null, a = "FAIL 1", !0);
console.log("FAIL 2")
} catch (e) {
console.log(a);
}
}
expect: {
var a = "PASS", b;
try {
b[42] = (b.q = null, a = "FAIL 1", !0);
console.log("FAIL 2")
} catch (e) {
console.log(a);
}
}
expect_stdout: "PASS"
}

issue_5963_assign: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
var a = Object.create(null);
a.PASS = 42;
a.FAIL;
for (var p in a)
console.log(p);
}
expect: {
var a = Object.create(null);
a.PASS = 42;
for (var p in a)
console.log(p);
}
expect_stdout: "PASS"
}

issue_5963_compound_assign: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
var a = Object.create(null);
a.PASS ^= 42;
a.FAIL;
for (var p in a)
console.log(p);
}
expect: {
var a = Object.create(null);
a.PASS ^= 42;
for (var p in a)
console.log(p);
}
expect_stdout: "PASS"
}

issue_5963_unary: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
var a = Object.create(null);
a.PASS++;
a.FAIL;
for (var p in a)
console.log(p);
}
expect: {
var a = Object.create(null);
a.PASS++;
for (var p in a)
console.log(p);
}
expect_stdout: "PASS"
}

0 comments on commit 111746b

Please sign in to comment.