// a - -b => a + b
if (self.right instanceof AST_UnaryPrefix
&& self.right.operator == "-"
- && self.left.is_number(compressor)) {
+ && self.left.is_number(compressor)
+ && self.right.expression.is_number(compressor)) {
self = make_node(AST_Binary, self, {
operator: "+",
left: self.left,
// a + (b + c) => (a + b) + c
if (self.right instanceof AST_Binary
&& self.right.operator != "%"
+ && self.right.is_number(compressor)
&& PRECEDENCE[self.right.operator] == PRECEDENCE[self.operator]) {
self = make_node(AST_Binary, self, {
operator: align(self.operator, self.right.operator),
}),
right: self.right.right
});
+ if (self.operator == "+"
+ && !self.right.is_boolean(compressor)
+ && !self.right.is_number(compressor)) {
+ self.right = make_node(AST_UnaryPrefix, self.right, {
+ operator: "+",
+ expression: self.right
+ });
+ }
}
// (2 * n) * 3 => 6 * n
// (n + 2) + 3 => n + 5
&& self.left instanceof AST_Binary
&& self.left.operator != "%"
&& PRECEDENCE[self.left.operator] == PRECEDENCE[self.operator]) {
- if (self.left.left instanceof AST_Constant) {
+ if (self.left.left instanceof AST_Constant
+ && (self.left.operator != "+" || self.left.right.is_number(compressor))) {
self = make_node(AST_Binary, self, {
operator: self.left.operator,
left: make_node(AST_Binary, self.left, {
}),
right: self.left.right
});
- } else if (self.left.right instanceof AST_Constant) {
+ } else if (self.left.right instanceof AST_Constant
+ && (self.left.operator != "+" || self.left.left.is_number(compressor))) {
self = make_node(AST_Binary, self, {
operator: self.left.operator,
left: self.left.left,
}
input: {
var x = "42", y = null;
- console.log(
+ [
x + 1 + 2,
x * 1 * 2,
+x + 1 + 2,
1 + (2 + ~x + 3),
-y + (2 + ~x + 3),
1 & (2 & x & 3),
- 1 + (2 + (x |= 0) + 3)
- );
+ 1 + (2 + (x |= 0) + 3),
+ ].forEach(function(n) {
+ console.log(typeof n, n);
+ });
}
expect: {
var x = "42", y = null;
- console.log(
+ [
x + 1 + 2,
1 * x * 2,
+x + 1 + 2,
2 + ~x + 3 + 1,
2 + ~x + 3 - y,
0 & x,
- 2 + (x |= 0) + 3 + 1
- );
+ 2 + (x |= 0) + 3 + 1,
+ ].forEach(function(n) {
+ console.log(typeof n, n);
+ });
}
- expect_stdout: "4212 84 45 14223 43 48 6 47 -36 -37 0 47"
+ expect_stdout: [
+ "string 4212",
+ "number 84",
+ "number 45",
+ "string 14223",
+ "number 43",
+ "number 48",
+ "number 6",
+ "number 47",
+ "number -36",
+ "number -37",
+ "number 0",
+ "number 47",
+ ]
}
evaluate_2_unsafe_math: {
}
input: {
var x = "42", y = null;
- console.log(
+ [
x + 1 + 2,
x * 1 * 2,
+x + 1 + 2,
1 + (2 + ~x + 3),
-y + (2 + ~x + 3),
1 & (2 & x & 3),
- 1 + (2 + (x |= 0) + 3)
- );
+ 1 + (2 + (x |= 0) + 3),
+ ].forEach(function(n) {
+ console.log(typeof n, n);
+ });
}
expect: {
var x = "42", y = null;
- console.log(
+ [
x + 1 + 2,
2 * x,
+x + 3,
6 + ~x,
5 + ~x - y,
0 & x,
- 6 + (x |= 0)
- );
+ 6 + (x |= 0),
+ ].forEach(function(n) {
+ console.log(typeof n, n);
+ });
}
- expect_stdout: "4212 84 45 14223 43 48 6 47 -36 -37 0 47"
+ expect_stdout: [
+ "string 4212",
+ "number 84",
+ "number 45",
+ "string 14223",
+ "number 43",
+ "number 48",
+ "number 6",
+ "number 47",
+ "number -36",
+ "number -37",
+ "number 0",
+ "number 47",
+ ]
}
evaluate_3: {
unsafe_math: false,
}
input: {
- var a = true;
- console.log(
+ var a = "1";
+ [
+a + 2 + 3,
+a + 2 - 3,
+a - 2 + 3,
2 + 3 + +a,
2 + 3 - +a,
2 - 3 + +a,
- 2 - 3 - +a
- );
+ 2 - 3 - +a,
+ ].forEach(function(n) {
+ console.log(typeof n, n);
+ });
}
expect: {
- var a = true;
- console.log(
+ var a = "1";
+ [
+a + 2 + 3,
+a + 2 - 3,
a - 2 + 3,
+a + 5,
5 - a,
+a - 1,
- -1 - a
- );
+ -1 - a,
+ ].forEach(function(n) {
+ console.log(typeof n, n);
+ });
}
- expect_stdout: "6 0 2 -4 6 0 4 -2 6 4 0 -2"
+ expect_stdout: [
+ "number 6",
+ "number 0",
+ "number 2",
+ "number -4",
+ "number 6",
+ "number 0",
+ "number 4",
+ "number -2",
+ "number 6",
+ "number 4",
+ "number 0",
+ "number -2",
+ ]
}
evaluate_5_unsafe_math: {
unsafe_math: true,
}
input: {
- var a = true;
- console.log(
+ var a = "1";
+ [
+a + 2 + 3,
+a + 2 - 3,
+a - 2 + 3,
2 + 3 + +a,
2 + 3 - +a,
2 - 3 + +a,
- 2 - 3 - +a
- );
+ 2 - 3 - +a,
+ ].forEach(function(n) {
+ console.log(typeof n, n);
+ });
}
expect: {
- var a = true;
- console.log(
+ var a = "1";
+ [
+a + 5,
+a + -1,
a - -1,
+a + 5,
5 - a,
+a - 1,
- -1 - a
- );
+ -1 - a,
+ ].forEach(function(n) {
+ console.log(typeof n, n);
+ });
}
- expect_stdout: "6 0 2 -4 6 0 4 -2 6 4 0 -2"
+ expect_stdout: [
+ "number 6",
+ "number 0",
+ "number 2",
+ "number -4",
+ "number 6",
+ "number 0",
+ "number 4",
+ "number -2",
+ "number 6",
+ "number 4",
+ "number 0",
+ "number -2",
+ ]
}
evaluate_6: {
unsafe_math: false,
}
input: {
- var a = true;
- console.log(
+ var a = "1";
+ [
-a + 2 + 3,
-a + 2 - 3,
-a - 2 + 3,
2 + 3 + -a,
2 + 3 - -a,
2 - 3 + -a,
- 2 - 3 - -a
- );
+ 2 - 3 - -a,
+ ].forEach(function(n) {
+ console.log(typeof n, n);
+ });
}
expect: {
- var a = true;
- console.log(
+ var a = "1";
+ [
2 - a + 3,
2 - a - 3,
-a - 2 + 3,
-a - 2 - 3,
2 - a + 3,
2 - a - 3,
- 2 + a + 3,
- 2 + a - 3,
+ 2 - -a + 3,
+ 2 - -a - 3,
5 - a,
- 5 + a,
+ 5 - -a,
-1 - a,
- -1 + a
- );
+ -1 - -a,
+ ].forEach(function(n) {
+ console.log(typeof n, n);
+ });
}
- expect_stdout: "4 -2 0 -6 4 -2 6 0 4 6 -2 0"
+ expect_stdout: [
+ "number 4",
+ "number -2",
+ "number 0",
+ "number -6",
+ "number 4",
+ "number -2",
+ "number 6",
+ "number 0",
+ "number 4",
+ "number 6",
+ "number -2",
+ "number 0",
+ ]
}
evaluate_6_unsafe_math: {
unsafe_math: true,
}
input: {
- var a = true;
- console.log(
+ var a = "1";
+ [
-a + 2 + 3,
-a + 2 - 3,
-a - 2 + 3,
2 + 3 + -a,
2 + 3 - -a,
2 - 3 + -a,
- 2 - 3 - -a
- );
+ 2 - 3 - -a,
+ ].forEach(function(n) {
+ console.log(typeof n, n);
+ });
}
expect: {
- var a = true;
- console.log(
+ var a = "1";
+ [
5 - a,
-1 - a,
-a - -1,
-a - 5,
5 - a,
-1 - a,
- 2 + a + 3,
- -1 + a,
+ 5 - -a,
+ -1 - -a,
5 - a,
- 5 + a,
+ 5 - -a,
-1 - a,
- -1 + a
- );
+ -1 - -a,
+ ].forEach(function(n) {
+ console.log(typeof n, n);
+ });
}
- expect_stdout: "4 -2 0 -6 4 -2 6 0 4 6 -2 0"
+ expect_stdout: [
+ "number 4",
+ "number -2",
+ "number 0",
+ "number -6",
+ "number 4",
+ "number -2",
+ "number 6",
+ "number 0",
+ "number 4",
+ "number 6",
+ "number -2",
+ "number 0",
+ ]
}
evaluate_7: {
}
input: {
var x = "42", y;
- console.log(
+ [
+x + 2 + (3 + !y),
+x + 2 + (3 - !y),
+x + 2 - (3 + !y),
+x - 2 + (3 + !y),
+x - 2 + (3 - !y),
+x - 2 - (3 + !y),
- +x - 2 - (3 - !y)
- );
+ +x - 2 - (3 - !y),
+ ].forEach(function(n) {
+ console.log(typeof n, n);
+ });
}
expect: {
var x = "42", y;
- console.log(
+ [
+x + 2 + (3 + !y),
+x + 2 + (3 - !y),
+x + 2 - (3 + !y),
x - 2 + (3 + !y),
x - 2 + (3 - !y),
x - 2 - (3 + !y),
- x - 2 - (3 - !y)
- );
+ x - 2 - (3 - !y),
+ ].forEach(function(n) {
+ console.log(typeof n, n);
+ });
}
- expect_stdout: "48 46 40 42 44 42 36 38"
+ expect_stdout: [
+ "number 48",
+ "number 46",
+ "number 40",
+ "number 42",
+ "number 44",
+ "number 42",
+ "number 36",
+ "number 38",
+ ]
}
evaluate_7_unsafe_math: {
}
input: {
var x = "42", y;
- console.log(
+ [
+x + 2 + (3 + !y),
+x + 2 + (3 - !y),
+x + 2 - (3 + !y),
+x - 2 + (3 + !y),
+x - 2 + (3 - !y),
+x - 2 - (3 + !y),
- +x - 2 - (3 - !y)
- );
+ +x - 2 - (3 - !y),
+ ].forEach(function(n) {
+ console.log(typeof n, n);
+ });
}
expect: {
var x = "42", y;
- console.log(
+ [
+x + 5 + !y,
+x + 5 - !y,
+x + -1 - !y,
x - -1 + !y,
x - -1 - !y,
x - 5 - !y,
- x - 5 + !y
- );
+ x - 5 + !y,
+ ].forEach(function(n) {
+ console.log(typeof n, n);
+ });
}
- expect_stdout: "48 46 40 42 44 42 36 38"
+ expect_stdout: [
+ "number 48",
+ "number 46",
+ "number 40",
+ "number 42",
+ "number 44",
+ "number 42",
+ "number 36",
+ "number 38",
+ ]
}
NaN_redefined: {
}
expect_stdout: true
}
+
+issue_3531_1: {
+ options = {
+ evaluate: true,
+ unsafe_math: true,
+ }
+ input: {
+ var a = "1";
+ console.log(typeof (a + 1 - .1 - .1 - .1));
+ }
+ expect: {
+ var a = "1";
+ console.log(typeof (a + 1 - (.2 + .1)));
+ }
+ expect_stdout: "number"
+}
+
+issue_3531_2: {
+ options = {
+ evaluate: true,
+ unsafe_math: true,
+ }
+ input: {
+ console.log(1 - (2 - {}));
+ }
+ expect: {
+ console.log(-1 + +{});
+ }
+ expect_stdout: "NaN"
+}
+
+issue_3531_3: {
+ options = {
+ evaluate: true,
+ unsafe_math: true,
+ }
+ input: {
+ var a = "3";
+ console.log(1 - (2 + a));
+ }
+ expect: {
+ var a = "3";
+ console.log(1 - (2 + a));
+ }
+ expect_stdout: "-22"
+}