aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/compress.js21
-rw-r--r--lib/output.js1
-rw-r--r--test/compress/collapse_vars.js31
-rw-r--r--test/compress/pure_funcs.js2
-rw-r--r--test/compress/side_effects.js23
-rw-r--r--test/mocha/operator.js15
-rw-r--r--test/ufuzz/index.js24
7 files changed, 106 insertions, 11 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 749abef5..c8c08a0e 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -1464,6 +1464,7 @@ merge(Compressor.prototype, {
}
function is_last_node(node, parent) {
+ if (node.TYPE == "Binary") return node.operator == "in" && !is_object(node.right.tail_node());
if (node instanceof AST_Call) {
var fn = node.expression;
if (fn instanceof AST_SymbolRef) {
@@ -3824,7 +3825,8 @@ merge(Compressor.prototype, {
def(AST_Assign, return_true);
def(AST_Binary, function(compressor) {
return this.left.has_side_effects(compressor)
- || this.right.has_side_effects(compressor);
+ || this.right.has_side_effects(compressor)
+ || this.operator == "in" && !is_object(this.right.tail_node());
});
def(AST_Block, function(compressor) {
return any(this.body, compressor);
@@ -5131,6 +5133,15 @@ merge(Compressor.prototype, {
return this;
});
def(AST_Binary, function(compressor, first_in_statement) {
+ if (this.operator == "in" && !is_object(this.right.tail_node())) {
+ var left = this.left.drop_side_effect_free(compressor, first_in_statement);
+ if (left === this.left) return this;
+ var node = this.clone();
+ node.left = left || make_node(AST_Number, this.left, {
+ value: 0
+ });
+ return node;
+ }
var right = this.right.drop_side_effect_free(compressor, first_in_statement);
if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement);
if (lazy_op[this.operator] && !(right instanceof AST_Function)) {
@@ -6879,8 +6890,14 @@ merge(Compressor.prototype, {
var indexFns = makePredicate("indexOf lastIndexOf");
var commutativeOperators = makePredicate("== === != !== * & | ^");
function is_object(node) {
+ while (node instanceof AST_SymbolRef) {
+ node = node.fixed_value();
+ if (!node) return false;
+ node = node.tail_node();
+ }
return node instanceof AST_Array
|| node instanceof AST_Lambda
+ || node instanceof AST_New
|| node instanceof AST_Object;
}
@@ -6980,7 +6997,7 @@ merge(Compressor.prototype, {
else if (self.left instanceof AST_SymbolRef
&& self.right instanceof AST_SymbolRef
&& self.left.definition() === self.right.definition()
- && is_object(self.left.fixed_value())) {
+ && is_object(self.left)) {
return make_node(self.operator[0] == "=" ? AST_True : AST_False, self);
}
break;
diff --git a/lib/output.js b/lib/output.js
index 62050b4d..a9e0ca7b 100644
--- a/lib/output.js
+++ b/lib/output.js
@@ -305,6 +305,7 @@ function OutputStream(options) {
|| (ch == "/" && ch == prev)
|| ((ch == "+" || ch == "-") && ch == last)
|| str == "--" && last == "!"
+ || str == "in" && prev == "/"
|| last == "--" && ch == ">") {
OUTPUT += " ";
current_col++;
diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js
index 0c232aa0..f99e0124 100644
--- a/test/compress/collapse_vars.js
+++ b/test/compress/collapse_vars.js
@@ -8164,3 +8164,34 @@ issue_3927: {
}
expect_stdout: "PASS"
}
+
+operator_in: {
+ options = {
+ collapse_vars: true,
+ }
+ input: {
+ function log(msg) {
+ console.log(msg);
+ }
+ var a = "FAIL";
+ try {
+ a = "PASS";
+ 0 in null;
+ log("FAIL", a);
+ } catch (e) {}
+ log(a);
+ }
+ expect: {
+ function log(msg) {
+ console.log(msg);
+ }
+ var a = "FAIL";
+ try {
+ a = "PASS";
+ 0 in null;
+ log("FAIL", a);
+ } catch (e) {}
+ log(a);
+ }
+ expect_stdout: "PASS"
+}
diff --git a/test/compress/pure_funcs.js b/test/compress/pure_funcs.js
index d65399f1..09f0bd45 100644
--- a/test/compress/pure_funcs.js
+++ b/test/compress/pure_funcs.js
@@ -136,7 +136,7 @@ relational: {
side_effects :true,
}
input: {
- foo() in foo();
+ foo() in new foo();
foo() instanceof bar();
foo() < "bar";
bar() > foo();
diff --git a/test/compress/side_effects.js b/test/compress/side_effects.js
index 63282660..b7ffe47a 100644
--- a/test/compress/side_effects.js
+++ b/test/compress/side_effects.js
@@ -274,3 +274,26 @@ drop_value: {
foo(), bar();
}
}
+
+operator_in: {
+ options = {
+ side_effects: true,
+ }
+ input: {
+ try {
+ "foo" in true;
+ console.log("FAIL");
+ } catch (e) {
+ console.log("PASS");
+ }
+ }
+ expect: {
+ try {
+ 0 in true;
+ console.log("FAIL");
+ } catch (e) {
+ console.log("PASS");
+ }
+ }
+ expect_stdout: "PASS"
+}
diff --git a/test/mocha/operator.js b/test/mocha/operator.js
index d36d3a1d..8dfea547 100644
--- a/test/mocha/operator.js
+++ b/test/mocha/operator.js
@@ -486,4 +486,19 @@ describe("operator", function() {
assert.strictEqual(UglifyJS.parse(exp[0]).print_to_string(), exp[1] + ";");
});
});
+ it("Should preserve space between /regex/ and `in`", function() {
+ [
+ "/regex/ in {}",
+ "/regex/g in {}",
+ "0 + /regex/ in {}",
+ "0 + /regex/g in {}",
+ ].forEach(function(exp) {
+ var code = UglifyJS.parse(exp).print_to_string();
+ try {
+ assert.strictEqual(UglifyJS.parse(code).print_to_string(), code);
+ } catch (ex) {
+ assert.fail("Failed to reparse: " + exp + "\n" + ex);
+ }
+ });
+ });
});
diff --git a/test/ufuzz/index.js b/test/ufuzz/index.js
index edd2ab80..eec4ab4a 100644
--- a/test/ufuzz/index.js
+++ b/test/ufuzz/index.js
@@ -168,7 +168,7 @@ var VALUES = [
"this",
];
-var BINARY_OPS_NO_COMMA = [
+var BINARY_OPS = [
" + ", // spaces needed to disambiguate with ++ cases (could otherwise cause syntax errors)
" - ",
"/",
@@ -190,9 +190,14 @@ var BINARY_OPS_NO_COMMA = [
"%",
"&&",
"||",
- "^" ];
-
-var BINARY_OPS = [","].concat(BINARY_OPS_NO_COMMA);
+ "^",
+ ",",
+];
+BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
+BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
+BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
+BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
+BINARY_OPS.push(" in ");
var ASSIGNMENTS = [
"=",
@@ -879,7 +884,7 @@ function createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
}
function _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
return "(" + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow)
- + createBinaryOp(noComma) + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ")";
+ + createBinaryOp(noComma, canThrow) + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ")";
}
function _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
// intentionally generate more hardcore ops
@@ -929,9 +934,12 @@ function createValue() {
return VALUES[rng(VALUES.length)];
}
-function createBinaryOp(noComma) {
- if (noComma) return BINARY_OPS_NO_COMMA[rng(BINARY_OPS_NO_COMMA.length)];
- return BINARY_OPS[rng(BINARY_OPS.length)];
+function createBinaryOp(noComma, canThrow) {
+ var op;
+ do {
+ op = BINARY_OPS[rng(BINARY_OPS.length)];
+ } while (noComma && op == "," || !canThrow && op == " in ");
+ return op;
}
function createAssignment() {