enhance side_effects (#5304)

This commit is contained in:
Alex Lam S.L
2022-01-17 15:18:42 +00:00
committed by GitHub
parent b636e97e3b
commit 8c2b76eff9
2 changed files with 63 additions and 18 deletions

View File

@@ -5303,21 +5303,43 @@ Compressor.prototype.compress = function(node) {
return map && map[prop]; return map && map[prop];
}); });
function spread_side_effects(exp) { // determine if object spread syntax may cause runtime exception
while ((exp = exp.tail_node()) instanceof AST_SymbolRef) { (function(def) {
exp = exp.fixed_value(); def(AST_Node, return_false);
if (!exp) return true; def(AST_Array, return_true);
} def(AST_Assign, function() {
return !(exp instanceof AST_Array switch (this.operator) {
|| exp.TYPE == "Binary" && !lazy_op[exp.operator] case "=":
|| exp instanceof AST_Constant return this.right.safe_to_spread();
|| exp instanceof AST_Lambda case "&&=":
|| exp instanceof AST_Object && all(exp.properties, function(prop) { case "||=":
case "??=":
return this.left.safe_to_spread() && this.right.safe_to_spread();
}
return true;
});
def(AST_Binary, function() {
return !lazy_op[this.operator] || this.left.safe_to_spread() && this.right.safe_to_spread();
});
def(AST_Constant, return_true);
def(AST_Lambda, return_true);
def(AST_Object, function() {
return all(this.properties, function(prop) {
return !(prop instanceof AST_ObjectGetter || prop instanceof AST_Spread); return !(prop instanceof AST_ObjectGetter || prop instanceof AST_Spread);
}) });
|| exp instanceof AST_ObjectIdentity });
|| exp instanceof AST_Unary); def(AST_ObjectIdentity, return_true);
} def(AST_Sequence, function() {
return this.tail_node().safe_to_spread();
});
def(AST_SymbolRef, function() {
var fixed = this.fixed_value();
return fixed && fixed.safe_to_spread();
});
def(AST_Unary, return_true);
})(function(node, func) {
node.DEFMETHOD("safe_to_spread", func);
});
// determine if expression has side effects // determine if expression has side effects
(function(def) { (function(def) {
@@ -5329,7 +5351,8 @@ Compressor.prototype.compress = function(node) {
}); });
} }
function array_spread(node, compressor) { function array_spread(node, compressor) {
return !node.expression.is_string(compressor) || node.expression.has_side_effects(compressor); var exp = node.expression;
return !exp.is_string(compressor) || exp.has_side_effects(compressor);
} }
def(AST_Node, return_true); def(AST_Node, return_true);
def(AST_Array, function(compressor) { def(AST_Array, function(compressor) {
@@ -5411,7 +5434,7 @@ Compressor.prototype.compress = function(node) {
def(AST_Object, function(compressor) { def(AST_Object, function(compressor) {
return any(this.properties, compressor, function(node, compressor) { return any(this.properties, compressor, function(node, compressor) {
var exp = node.expression; var exp = node.expression;
return spread_side_effects(exp) || exp.has_side_effects(compressor); return !exp.safe_to_spread() || exp.has_side_effects(compressor);
}); });
}); });
def(AST_ObjectIdentity, return_false); def(AST_ObjectIdentity, return_false);
@@ -8387,7 +8410,7 @@ Compressor.prototype.compress = function(node) {
}); });
var values = trim(exprs, compressor, first_in_statement, function(node, compressor, first_in_statement) { var values = trim(exprs, compressor, first_in_statement, function(node, compressor, first_in_statement) {
var exp = node.expression; var exp = node.expression;
return spread_side_effects(exp) ? node : exp.drop_side_effect_free(compressor, first_in_statement); return exp.safe_to_spread() ? exp.drop_side_effect_free(compressor, first_in_statement) : node;
}); });
if (!values) return null; if (!values) return null;
if (values === exprs && !all(values, function(node) { if (values === exprs && !all(values, function(node) {

View File

@@ -241,7 +241,29 @@ drop_empty_call_2: {
node_version: ">=6" node_version: ">=6"
} }
convert_hole: { convert_hole_array: {
options = {
spreads: true,
}
input: {
[ ...[ "PASS", , 42 ] ].forEach(function(a) {
console.log(a);
});
}
expect: {
[ "PASS", void 0, 42 ].forEach(function(a) {
console.log(a);
});
}
expect_stdout: [
"PASS",
"undefined",
"42",
]
node_version: ">=6"
}
convert_hole_call: {
options = { options = {
spreads: true, spreads: true,
} }