Skip to content

Commit

Permalink
fix corner cases with instanceof (#5509)
Browse files Browse the repository at this point in the history
- enhance `evaluate`
  • Loading branch information
alexlamsl committed Jun 12, 2022
1 parent 99946a3 commit 139fad0
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 25 deletions.
28 changes: 23 additions & 5 deletions lib/compress.js
Original file line number Diff line number Diff line change
Expand Up @@ -2452,7 +2452,7 @@ Compressor.prototype.compress = function(node) {

function is_last_node(node, parent) {
if (node instanceof AST_Await) return true;
if (node.TYPE == "Binary") return node.operator == "in" && !is_object(node.right);
if (node.TYPE == "Binary") return !can_drop_op(node.operator, node.right);
if (node instanceof AST_Call) {
var def, fn = node.expression;
if (fn instanceof AST_SymbolRef) {
Expand Down Expand Up @@ -5551,7 +5551,7 @@ Compressor.prototype.compress = function(node) {
def(AST_Binary, function(compressor) {
return this.left.has_side_effects(compressor)
|| this.right.has_side_effects(compressor)
|| this.operator == "in" && !is_object(this.right);
|| !can_drop_op(this.operator, this.right);
});
def(AST_Block, function(compressor) {
return any(this.body, compressor);
Expand Down Expand Up @@ -5705,7 +5705,7 @@ Compressor.prototype.compress = function(node) {
def(AST_Binary, function(compressor) {
return this.left.may_throw(compressor)
|| this.right.may_throw(compressor)
|| this.operator == "in" && !is_object(this.right);
|| !can_drop_op(this.operator, this.right);
});
def(AST_Block, function(compressor) {
return any(this.body, compressor);
Expand Down Expand Up @@ -5822,7 +5822,7 @@ Compressor.prototype.compress = function(node) {
def(AST_Binary, function(scope) {
return this.left.is_constant_expression(scope)
&& this.right.is_constant_expression(scope)
&& (this.operator != "in" || is_object(this.right));
&& can_drop_op(this.operator, this.right);
});
def(AST_Class, function(scope) {
var base = this.extends;
Expand Down Expand Up @@ -8533,7 +8533,7 @@ Compressor.prototype.compress = function(node) {
var left = this.left;
var right = this.right;
var op = this.operator;
if (op == "in" && !is_object(right)) {
if (!can_drop_op(op, right)) {
var lhs = left.drop_side_effect_free(compressor, first_in_statement);
if (lhs === left) return this;
var node = this.clone();
Expand Down Expand Up @@ -11202,6 +11202,18 @@ Compressor.prototype.compress = function(node) {
|| node instanceof AST_Object;
}

function can_drop_op(op, rhs) {
switch (op) {
case "in":
return is_object(rhs);
case "instanceof":
if (rhs instanceof AST_SymbolRef) rhs = rhs.fixed_value();
return is_lambda(rhs);
default:
return true;
}
}

function is_primitive(compressor, node) {
if (node.is_constant()) return true;
if (node instanceof AST_Assign) return node.operator != "=" || is_primitive(compressor, node.right);
Expand Down Expand Up @@ -11708,6 +11720,12 @@ Compressor.prototype.compress = function(node) {
}
}
break;
case "instanceof":
if (is_lambda(self.right)) return make_sequence(self, [
self,
make_node(AST_False, self),
]).optimize(compressor);
break;
}
if (!(parent instanceof AST_UnaryPrefix && parent.operator == "delete")) {
if (self.left instanceof AST_Number && !self.right.is_constant()) switch (self.operator) {
Expand Down
28 changes: 11 additions & 17 deletions lib/output.js
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,15 @@ function OutputStream(options) {

var require_semicolon = makePredicate("( [ + * / - , .");

function require_space(prev, ch, str) {
return is_identifier_char(prev) && (is_identifier_char(ch) || ch == "\\")
|| (ch == "/" && ch == prev)
|| ((ch == "+" || ch == "-") && ch == last)
|| last == "--" && ch == ">"
|| last == "!" && str == "--"
|| prev == "/" && (str == "in" || str == "instanceof");
}

var print = options.beautify
|| options.comments
|| options.max_line_len
Expand Down Expand Up @@ -312,12 +321,7 @@ function OutputStream(options) {
}

if (might_need_space) {
if (is_identifier_char(prev) && (is_identifier_char(ch) || ch == "\\")
|| (ch == "/" && ch == prev)
|| ((ch == "+" || ch == "-") && ch == last)
|| str == "--" && last == "!"
|| str == "in" && prev == "/"
|| last == "--" && ch == ">") {
if (require_space(prev, ch, str)) {
output += " ";
current_col++;
}
Expand Down Expand Up @@ -355,14 +359,7 @@ function OutputStream(options) {
}
}
if (might_need_space) {
if (is_identifier_char(prev) && (is_identifier_char(ch) || ch == "\\")
|| (ch == "/" && ch == prev)
|| ((ch == "+" || ch == "-") && ch == last)
|| str == "--" && last == "!"
|| str == "in" && prev == "/"
|| last == "--" && ch == ">") {
output += " ";
}
if (require_space(prev, ch, str)) output += " ";
if (prev != "<" || str != "!") might_need_space = false;
}
output += str;
Expand Down Expand Up @@ -1819,9 +1816,6 @@ function OutputStream(options) {
case "\u2029": return "\\u2029";
}
}));
var p = output.parent();
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === this)
output.print(" ");
});

function force_statement(stat, output) {
Expand Down
15 changes: 15 additions & 0 deletions test/compress/awaits.js
Original file line number Diff line number Diff line change
Expand Up @@ -1293,6 +1293,21 @@ functions_inner_var: {
node_version: ">=8"
}

instanceof_lambda: {
options = {
evaluate: true,
side_effects: true,
}
input: {
console.log(42 instanceof async function() {});
}
expect: {
console.log(false);
}
expect_stdout: "false"
node_version: ">=8"
}

issue_4335_1: {
options = {
inline: true,
Expand Down
17 changes: 17 additions & 0 deletions test/compress/classes.js
Original file line number Diff line number Diff line change
Expand Up @@ -1266,6 +1266,23 @@ keep_fnames: {
node_version: ">=4"
}

instanceof_lambda: {
options = {
evaluate: true,
side_effects: true,
}
input: {
"use strict";
console.log(42 instanceof class {});
}
expect: {
"use strict";
console.log(false);
}
expect_stdout: "false"
node_version: ">=4"
}

issue_805_1: {
options = {
inline: true,
Expand Down
14 changes: 14 additions & 0 deletions test/compress/evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,20 @@ chained_side_effects: {
]
}

instanceof_lambda: {
options = {
evaluate: true,
side_effects: true,
}
input: {
console.log(42 instanceof function() {});
}
expect: {
console.log(false);
}
expect_stdout: "false"
}

issue_1649: {
options = {
evaluate: true,
Expand Down
2 changes: 1 addition & 1 deletion test/compress/pure_funcs.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ relational: {
"bar" >= "bar";
}
expect: {
bar();
0 instanceof bar();
bar();
bar(), bar();
bar();
Expand Down
16 changes: 16 additions & 0 deletions test/compress/regexp.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ regexp_properties: {
expect_stdout: "abc true false 0 false"
}

instanceof_1: {
input: {
console.log(/foo/ instanceof RegExp);
}
expect_exact: "console.log(/foo/ instanceof RegExp);"
expect_stdout: "true"
}

instanceof_2: {
input: {
console.log(42 + /foo/ instanceof Object);
}
expect_exact: "console.log(42+/foo/ instanceof Object);"
expect_stdout: "false"
}

issue_3434_1: {
options = {
evaluate: true,
Expand Down
53 changes: 53 additions & 0 deletions test/compress/side_effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -645,3 +645,56 @@ issue_4751: {
}
expect_stdout: "PASS"
}

drop_instanceof: {
options = {
side_effects: true,
}
input: {
42 instanceof function() {};
console.log("PASS");
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
}

drop_instanceof_reference: {
options = {
reduce_vars: true,
side_effects: true,
toplevel: true,
}
input: {
function f() {}
42 instanceof f;
console.log("PASS");
}
expect: {
function f() {}
console.log("PASS");
}
expect_stdout: "PASS"
}

retain_instanceof: {
options = {
side_effects: true,
}
input: {
try {
42 instanceof "foo";
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
0 instanceof "foo";
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
}
15 changes: 15 additions & 0 deletions test/compress/yields.js
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,21 @@ drop_unused_call: {
node_version: ">=4"
}

instanceof_lambda: {
options = {
evaluate: true,
side_effects: true,
}
input: {
console.log(42 instanceof function*() {});
}
expect: {
console.log(false);
}
expect_stdout: "false"
node_version: ">=4"
}

issue_4454_1: {
rename = false
options = {
Expand Down
4 changes: 2 additions & 2 deletions test/ufuzz/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
if (SUPPORT.exponentiation) BINARY_OPS.push("**");
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
BINARY_OPS.push(" in ");
BINARY_OPS.push(" in ", " instanceof ");

var ASSIGNMENTS = [ "=" ];
ASSIGNMENTS = ASSIGNMENTS.concat(ASSIGNMENTS);
Expand Down Expand Up @@ -2009,7 +2009,7 @@ function createBinaryOp(noComma, canThrow) {
var op;
do {
op = BINARY_OPS[rng(BINARY_OPS.length)];
} while (noComma && op == "," || !canThrow && op == " in ");
} while (noComma && op == "," || !canThrow && /^ in/.test(op));
return op;
}

Expand Down

0 comments on commit 139fad0

Please sign in to comment.