fix corner cases in evaluate & side_effects (#5726)
This commit is contained in:
@@ -2566,7 +2566,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
|
|
||||||
function is_last_node(node, parent) {
|
function is_last_node(node, parent) {
|
||||||
if (node instanceof AST_Await) return true;
|
if (node instanceof AST_Await) return true;
|
||||||
if (node.TYPE == "Binary") return !can_drop_op(node.operator, node.right, compressor);
|
if (node.TYPE == "Binary") return !can_drop_op(node, compressor);
|
||||||
if (node instanceof AST_Call) {
|
if (node instanceof AST_Call) {
|
||||||
var def, fn = node.expression;
|
var def, fn = node.expression;
|
||||||
if (fn instanceof AST_SymbolRef) {
|
if (fn instanceof AST_SymbolRef) {
|
||||||
@@ -5820,7 +5820,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
def(AST_Binary, function(compressor) {
|
def(AST_Binary, function(compressor) {
|
||||||
return this.left.has_side_effects(compressor)
|
return this.left.has_side_effects(compressor)
|
||||||
|| this.right.has_side_effects(compressor)
|
|| this.right.has_side_effects(compressor)
|
||||||
|| !can_drop_op(this.operator, this.right, compressor);
|
|| !can_drop_op(this, compressor);
|
||||||
});
|
});
|
||||||
def(AST_Block, function(compressor) {
|
def(AST_Block, function(compressor) {
|
||||||
return any(this.body, compressor);
|
return any(this.body, compressor);
|
||||||
@@ -5974,7 +5974,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
def(AST_Binary, function(compressor) {
|
def(AST_Binary, function(compressor) {
|
||||||
return this.left.may_throw(compressor)
|
return this.left.may_throw(compressor)
|
||||||
|| this.right.may_throw(compressor)
|
|| this.right.may_throw(compressor)
|
||||||
|| !can_drop_op(this.operator, this.right, compressor);
|
|| !can_drop_op(this, compressor);
|
||||||
});
|
});
|
||||||
def(AST_Block, function(compressor) {
|
def(AST_Block, function(compressor) {
|
||||||
return any(this.body, compressor);
|
return any(this.body, compressor);
|
||||||
@@ -6091,7 +6091,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
def(AST_Binary, function(scope) {
|
def(AST_Binary, function(scope) {
|
||||||
return this.left.is_constant_expression(scope)
|
return this.left.is_constant_expression(scope)
|
||||||
&& this.right.is_constant_expression(scope)
|
&& this.right.is_constant_expression(scope)
|
||||||
&& can_drop_op(this.operator, this.right);
|
&& can_drop_op(this);
|
||||||
});
|
});
|
||||||
def(AST_Class, function(scope) {
|
def(AST_Class, function(scope) {
|
||||||
var base = this.extends;
|
var base = this.extends;
|
||||||
@@ -8813,11 +8813,17 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var left = this.left;
|
var left = this.left;
|
||||||
var right = this.right;
|
var right = this.right;
|
||||||
var op = this.operator;
|
var op = this.operator;
|
||||||
if (!can_drop_op(op, right, compressor)) {
|
if (!can_drop_op(this, compressor)) {
|
||||||
var lhs = left.drop_side_effect_free(compressor, first_in_statement);
|
var lhs = left.drop_side_effect_free(compressor, first_in_statement);
|
||||||
if (lhs === left) return this;
|
if (lhs === left) return this;
|
||||||
var node = this.clone();
|
var node = this.clone();
|
||||||
node.left = lhs || make_node(AST_Number, left, { value: 0 });
|
if (lhs) {
|
||||||
|
node.left = lhs;
|
||||||
|
} else if (op == "instanceof" && !left.is_constant()) {
|
||||||
|
node.left = make_node(AST_Array, left, { elements: [] });
|
||||||
|
} else {
|
||||||
|
node.left = make_node(AST_Number, left, { value: 0 });
|
||||||
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
var rhs = right.drop_side_effect_free(compressor, first_in_statement);
|
var rhs = right.drop_side_effect_free(compressor, first_in_statement);
|
||||||
@@ -11566,13 +11572,16 @@ Compressor.prototype.compress = function(node) {
|
|||||||
|| node instanceof AST_Object;
|
|| node instanceof AST_Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
function can_drop_op(op, rhs, compressor) {
|
function can_drop_op(node, compressor) {
|
||||||
switch (op) {
|
var rhs = node.right;
|
||||||
|
switch (node.operator) {
|
||||||
case "in":
|
case "in":
|
||||||
return is_object(rhs) || compressor && compressor.option("unsafe_comps");
|
return is_object(rhs) || compressor && compressor.option("unsafe_comps");
|
||||||
case "instanceof":
|
case "instanceof":
|
||||||
if (rhs instanceof AST_SymbolRef) rhs = rhs.fixed_value();
|
if (rhs instanceof AST_SymbolRef) rhs = rhs.fixed_value();
|
||||||
return is_lambda(rhs) || compressor && compressor.option("unsafe_comps");
|
if (rhs instanceof AST_Defun || rhs instanceof AST_Function || is_generator(rhs)) return true;
|
||||||
|
if (is_lambda(rhs) && node.left.is_constant()) return true;
|
||||||
|
return compressor && compressor.option("unsafe_comps");
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -12118,8 +12127,10 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "instanceof":
|
case "instanceof":
|
||||||
|
if (!can_drop_op(self, compressor)) break;
|
||||||
if (is_lambda(self.right)) return make_sequence(self, [
|
if (is_lambda(self.right)) return make_sequence(self, [
|
||||||
self,
|
self.left,
|
||||||
|
self.right,
|
||||||
make_node(AST_False, self),
|
make_node(AST_False, self),
|
||||||
]).optimize(compressor);
|
]).optimize(compressor);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -690,6 +690,65 @@ inline_iife_within_arrow: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instanceof_lambda_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(42 instanceof (() => {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(false);
|
||||||
|
}
|
||||||
|
expect_stdout: "false"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
instanceof_lambda_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(null instanceof (() => {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log((null, () => {}, false));
|
||||||
|
}
|
||||||
|
expect_stdout: "false"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
instanceof_lambda_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log({} instanceof (() => {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log({} instanceof (() => {}));
|
||||||
|
}
|
||||||
|
expect_stdout: TypeError("Function has non-object prototype 'undefined' in instanceof check")
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
instanceof_lambda_4: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
({ p: "foo" }) instanceof (() => {});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
[] instanceof (() => {});
|
||||||
|
}
|
||||||
|
expect_stdout: TypeError("Function has non-object prototype 'undefined' in instanceof check")
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
issue_4388: {
|
issue_4388: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
|
|||||||
@@ -1348,7 +1348,7 @@ functions_inner_var: {
|
|||||||
node_version: ">=8"
|
node_version: ">=8"
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceof_lambda: {
|
instanceof_lambda_1: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -1363,6 +1363,50 @@ instanceof_lambda: {
|
|||||||
node_version: ">=8"
|
node_version: ">=8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instanceof_lambda_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(null instanceof async function() {});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log((null, async function() {}, false));
|
||||||
|
}
|
||||||
|
expect_stdout: "false"
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
|
instanceof_lambda_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log({} instanceof async function() {});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log({} instanceof async function() {});
|
||||||
|
}
|
||||||
|
expect_stdout: TypeError("Function has non-object prototype 'undefined' in instanceof check")
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
|
instanceof_lambda_4: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
({ p: "foo" }) instanceof async function() {};
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
[] instanceof async function() {};
|
||||||
|
}
|
||||||
|
expect_stdout: TypeError("Function has non-object prototype 'undefined' in instanceof check")
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
issue_4335_1: {
|
issue_4335_1: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ relational: {
|
|||||||
"bar" >= "bar";
|
"bar" >= "bar";
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
0 instanceof bar();
|
[] instanceof bar();
|
||||||
bar();
|
bar();
|
||||||
bar(), bar();
|
bar(), bar();
|
||||||
bar();
|
bar();
|
||||||
|
|||||||
Reference in New Issue
Block a user