Compare commits

...

15 Commits

Author SHA1 Message Date
Alex Lam S.L
8a191c0a84 v3.6.5 2019-10-29 12:55:28 +08:00
Alex Lam S.L
83fb8b4ca1 fix corner case in ie8 (#3543)
fixes #3542
2019-10-28 23:54:27 +08:00
Alex Lam S.L
f38e31bd1e fix corner case in evaluate (#3540)
fixes #3539
2019-10-28 19:56:42 +08:00
Alex Lam S.L
24e8b47977 improve ufuzz resilience (#3541) 2019-10-28 18:08:51 +08:00
Alex Lam S.L
95618793a4 fix corner case in ufuzz (#3538) 2019-10-28 16:04:07 +08:00
Alex Lam S.L
2f3b460212 fix & enhance unsafe_math (#3537)
closes #3535
fixes #3536
2019-10-28 13:37:08 +08:00
Alex Lam S.L
06e135e35f migrate CI workaround (#3534) 2019-10-27 17:29:54 +08:00
Alex Lam S.L
ebbf3d4a51 improve ufuzz resilience (#3533) 2019-10-27 14:17:35 +08:00
Alex Lam S.L
a270ba6b59 fix corner cases in unsafe_math (#3532)
fixes #3531
2019-10-27 08:25:11 +08:00
Alex Lam S.L
37f35e4ac2 prevent tty truncation in test/compress (#3530) 2019-10-27 05:00:21 +08:00
Alex Lam S.L
50a578c1f6 compress arithmetic expressions further (#3529) 2019-10-27 03:07:07 +08:00
Alex Lam S.L
85237b08d4 fix corner case in collapse_vars (#3527)
fixes #3526
2019-10-26 05:41:02 +08:00
Alex Lam S.L
27b159e711 separate ufuzz job failures (#3525) 2019-10-25 02:06:29 +08:00
Alex Lam S.L
82b3eed5ef fix corner case in ie8 & mangle (#3524)
fixes #3523
2019-10-24 23:43:19 +08:00
Alex Lam S.L
0f7aa41e33 fix corner case in collapse_vars (#3521)
fixes #3520
2019-10-24 01:13:57 +08:00
13 changed files with 1521 additions and 404 deletions

View File

@@ -5,6 +5,7 @@ on:
jobs:
ufuzz:
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest ]
name: ${{ matrix.os }}

View File

@@ -1128,6 +1128,8 @@ merge(Compressor.prototype, {
if (!stop_if_hit && in_conditional(node, parent)) {
stop_if_hit = parent;
}
// Skip transient nodes caused by single-use variable replacement
if (node.single_use && parent instanceof AST_VarDef && parent.value === node) return node;
// Replace variable with assignment when found
var hit_rhs;
if (can_replace
@@ -1226,6 +1228,7 @@ merge(Compressor.prototype, {
var scan_lhs = lhs && !side_effects && !is_lhs_read_only(lhs, compressor);
var scan_rhs = foldable(get_rhs(candidate));
if (!scan_lhs && !scan_rhs) continue;
var modify_toplevel = false;
// Locate symbols which may execute code outside of scanning range
var lvalues = get_lvalues(candidate);
var lhs_local = is_lhs_local(lhs);
@@ -1578,7 +1581,16 @@ merge(Compressor.prototype, {
if (candidate instanceof AST_VarDef) {
lvalues[candidate.name.name] = lhs;
}
var scan_iife = scope instanceof AST_Toplevel;
var tw = new TreeWalker(function(node) {
if (scan_iife && node.TYPE == "Call") {
var exp = node.expression;
if (exp instanceof AST_PropAccess) return;
if (exp instanceof AST_Function && !exp.contains_this()) return;
modify_toplevel = true;
scan_iife = false;
return;
}
var value;
if (node instanceof AST_SymbolRef) {
value = node.fixed_value() || node;
@@ -1665,6 +1677,7 @@ merge(Compressor.prototype, {
var def = sym.definition();
if (def.orig.length == 1 && def.orig[0] instanceof AST_SymbolDefun) return false;
if (def.scope !== scope) return true;
if (modify_toplevel && compressor.exposed(def)) return true;
return !all(def.references, function(ref) {
return ref.scope.resolve() === scope;
});
@@ -2424,9 +2437,10 @@ merge(Compressor.prototype, {
|| this.operator == "=" && this.right.is_number(compressor);
});
def(AST_Binary, function(compressor) {
return binary[this.operator] || this.operator == "+"
&& this.left.is_number(compressor)
&& this.right.is_number(compressor);
if (binary[this.operator]) return true;
if (this.operator != "+") return false;
return (this.left.is_boolean(compressor) || this.left.is_number(compressor))
&& (this.right.is_boolean(compressor) || this.right.is_number(compressor));
});
var fn = makePredicate([
"charCodeAt",
@@ -2885,7 +2899,20 @@ merge(Compressor.prototype, {
case ">=" : result = left >= right; break;
default : return this;
}
return isNaN(result) && compressor.find_parent(AST_With) ? this : result;
if (isNaN(result)) return compressor.find_parent(AST_With) ? this : result;
if (compressor.option("unsafe_math")
&& result
&& typeof result == "number"
&& (this.operator == "+" || this.operator == "-")) {
var digits = Math.max(0, decimals(left), decimals(right));
if (digits < 21) return +result.toFixed(digits);
}
return result;
function decimals(operand) {
var match = /(\.[0-9]*)?(e.+)?$/.exec(+operand);
return (match[1] || ".").length - 1 - (match[2] || "").slice(1);
}
});
def(AST_Conditional, function(compressor, cached, depth) {
var condition = this.condition._eval(compressor, cached, depth);
@@ -3737,9 +3764,7 @@ merge(Compressor.prototype, {
def.value = null;
head.push(def);
} else {
var value = def.value
&& !def.value.single_use
&& def.value.drop_side_effect_free(compressor);
var value = def.value && def.value.drop_side_effect_free(compressor);
if (value) {
AST_Node.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", template(def.name));
side_effects.push(value);
@@ -4213,7 +4238,7 @@ merge(Compressor.prototype, {
def(AST_Binary, function(compressor, first_in_statement) {
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]) {
if (lazy_op[this.operator] && !(right instanceof AST_Function)) {
var node = this;
if (right !== node.right) {
node = this.clone();
@@ -5766,6 +5791,7 @@ merge(Compressor.prototype, {
}
}
if (compressor.option("evaluate")) {
var associative = true;
switch (self.operator) {
case "&&":
var ll = fuzzy_eval(self.left);
@@ -5834,9 +5860,6 @@ merge(Compressor.prototype, {
}).optimize(compressor);
}
break;
}
var associative = true;
switch (self.operator) {
case "+":
// "foo" + ("bar" + x) => "foobar" + x
if (self.left instanceof AST_Constant
@@ -5916,13 +5939,39 @@ merge(Compressor.prototype, {
});
break;
}
case "-":
// a - -b => a + b
if (self.right instanceof AST_UnaryPrefix
&& self.right.operator == "-"
&& self.left.is_number(compressor)
&& self.right.expression.is_number(compressor)) {
self = make_node(AST_Binary, self, {
operator: "+",
left: self.left,
right: self.right.expression
});
break;
}
case "*":
case "/":
associative = compressor.option("unsafe_math");
// +a - b => a - b
// a - +b => a - b
if (self.operator != "+") {
if (self.left instanceof AST_UnaryPrefix && self.left.operator == "+") {
self.left = self.left.expression;
}
if (self.right instanceof AST_UnaryPrefix && self.right.operator == "+") {
self.right = self.right.expression;
}
}
case "&":
case "|":
case "^":
// a + +b => +b + a
if (self.left.is_number(compressor)
if (self.operator != "-"
&& self.operator != "/"
&& self.left.is_number(compressor)
&& self.right.is_number(compressor)
&& reversible()
&& !(self.left instanceof AST_Binary
@@ -5940,77 +5989,70 @@ merge(Compressor.prototype, {
self = best_of(compressor, self, reversed);
}
}
if (associative && self.is_number(compressor)) {
// a + (b + c) => (a + b) + c
if (self.right instanceof AST_Binary
&& self.right.operator == self.operator) {
self = make_node(AST_Binary, self, {
if (!associative || !self.is_number(compressor)) break;
// a + (b + c) => (a + b) + c
if (self.right instanceof AST_Binary
&& self.right.operator != "%"
&& PRECEDENCE[self.right.operator] == PRECEDENCE[self.operator]
&& self.right.is_number(compressor)
&& (self.operator != "+"
|| self.right.left.is_boolean(compressor)
|| self.right.left.is_number(compressor))) {
self = make_node(AST_Binary, self, {
operator: align(self.operator, self.right.operator),
left: make_node(AST_Binary, self.left, {
operator: self.operator,
left: make_node(AST_Binary, self.left, {
operator: self.operator,
left: self.left,
right: self.right.left,
start: self.left.start,
end: self.right.left.end
}),
right: self.right.right
});
}
// (n + 2) + 3 => 5 + n
// (2 * n) * 3 => 6 + n
if (self.right instanceof AST_Constant
&& self.left instanceof AST_Binary
&& self.left.operator == self.operator) {
if (self.left.left instanceof AST_Constant) {
self = make_node(AST_Binary, self, {
operator: self.operator,
left: make_node(AST_Binary, self.left, {
operator: self.operator,
left: self.left.left,
right: self.right,
start: self.left.left.start,
end: self.right.end
}),
right: self.left.right
});
} else if (self.left.right instanceof AST_Constant) {
self = make_node(AST_Binary, self, {
operator: self.operator,
left: make_node(AST_Binary, self.left, {
operator: self.operator,
left: self.left.right,
right: self.right,
start: self.left.right.start,
end: self.right.end
}),
right: self.left.left
});
}
}
// (a | 1) | (2 | d) => (3 | a) | b
if (self.left instanceof AST_Binary
&& self.left.operator == self.operator
&& self.left.right instanceof AST_Constant
&& self.right instanceof AST_Binary
&& self.right.operator == self.operator
&& self.right.left instanceof AST_Constant) {
self = make_node(AST_Binary, self, {
operator: self.operator,
left: make_node(AST_Binary, self.left, {
operator: self.operator,
left: make_node(AST_Binary, self.left.left, {
operator: self.operator,
left: self.left.right,
right: self.right.left,
start: self.left.right.start,
end: self.right.left.end
}),
right: self.left.left
}),
right: self.right.right
left: self.left,
right: self.right.left,
start: self.left.start,
end: self.right.left.end
}),
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
if (self.right instanceof AST_Constant
&& self.left instanceof AST_Binary
&& self.left.operator != "%"
&& PRECEDENCE[self.left.operator] == PRECEDENCE[self.operator]) {
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, {
operator: self.operator,
left: self.left.left,
right: self.right,
start: self.left.left.start,
end: self.right.end
}),
right: self.left.right
});
} 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,
right: make_node(AST_Binary, self.left, {
operator: align(self.left.operator, self.operator),
left: self.left.right,
right: self.right,
start: self.left.right.start,
end: self.right.end
})
});
}
}
break;
}
}
if (compressor.option("unsafe")) {
@@ -6075,6 +6117,17 @@ merge(Compressor.prototype, {
}
return self;
function align(ref, op) {
switch (ref) {
case "-":
return op == "+" ? "-" : "+";
case "/":
return op == "*" ? "/" : "*";
default:
return op;
}
}
function fuzzy_eval(node) {
if (node.truthy) return true;
if (node.falsy) return false;

View File

@@ -214,7 +214,13 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
function redefine(node, scope) {
var name = node.name;
var old_def = node.thedef;
var new_def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
var new_def = scope.find_variable(name);
if (new_def) {
var redef;
while (redef = new_def.redefined()) new_def = redef;
} else {
new_def = self.globals.get(name) || scope.def_variable(node);
}
old_def.orig.concat(old_def.references).forEach(function(node) {
node.thedef = new_def;
node.reference(options);

View File

@@ -3,7 +3,7 @@
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.6.4",
"version": "3.6.5",
"engines": {
"node": ">=0.8.0"
},

View File

@@ -94,6 +94,3 @@ urls.forEach(function(url) {
});
});
});
setInterval(function() {
process.stderr.write("\0");
}, 5 * 60 * 1000).unref();

View File

@@ -1,3 +1,7 @@
"use strict";
require("../tools/exit");
var assert = require("assert");
var child_process = require("child_process");
var fs = require("fs");

View File

@@ -96,7 +96,7 @@ asm_mixed: {
return +sum;
}
function geometricMean(start, end) {
return start |= 0, end |= 0, +exp(+logSum(start, end) / +(end - start | 0));
return start |= 0, end |= 0, +exp(logSum(start, end) / (end - start | 0));
}
var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer);
return { geometricMean: geometricMean };

View File

@@ -6258,3 +6258,93 @@ cond_sequence_return: {
}
expect_stdout: "2"
}
issue_3520: {
options = {
collapse_vars: true,
reduce_vars: true,
unused: true,
}
input: {
var a = 0;
var b = function(c) {
for (var i = 2; --i >= 0;) {
(function f() {
c = 0;
var i = void 0;
var f = f && f[i];
})();
a += b;
c && b++;
}
}(b = 1);
console.log(a);
}
expect: {
var a = 0;
var b = function(c) {
for (var i = 2; --i >= 0;) {
(function() {
c = 0;
var f = f && f[void 0];
})();
a += b;
c && b++;
}
}(b = 1);
console.log(a);
}
expect_stdout: "2"
}
issue_3526_1: {
options = {
collapse_vars: true,
}
input: {
var b = function() {
this.a = "FAIL";
}();
var a = "PASS";
var b;
var c = b;
console.log(a);
}
expect: {
var b = function() {
this.a = "FAIL";
}();
var a = "PASS";
var b;
var c = b;
console.log(a);
}
expect_stdout: "PASS"
}
issue_3526_2: {
options = {
collapse_vars: true,
}
input: {
function f() {
this.a = "FAIL";
}
var b = f();
var a = "PASS";
var b;
var c = b;
console.log(a);
}
expect: {
function f() {
this.a = "FAIL";
}
var b = f();
var a = "PASS";
var b;
var c = b;
console.log(a);
}
expect_stdout: "PASS"
}

View File

@@ -2121,7 +2121,8 @@ issue_3515_1: {
expect: {
var c = 0;
(function() {
for (var key20 in !(this[c++] = 0));
this[c++] = 0;
for (var key20 in !0);
})();
console.log(c);
}

View File

@@ -1959,3 +1959,405 @@ issue_3493_ie8: {
}
expect_stdout: "PASS"
}
issue_3523: {
mangle = {
ie8: false,
toplevel: false,
}
input: {
var a = 0, b, c = "FAIL";
(function() {
var f, g, h, i, j, k, l, m, n, o, p, q, r, s;
})();
try {
throw 0;
} catch (t) {
(function() {
(function t() {
c = "PASS";
})();
})();
(function e() {
try {} catch (t) {}
})();
}
console.log(c);
}
expect: {
var a = 0, b, c = "FAIL";
(function() {
var c, n, t, o, a, r, f, i, u, h, l, v, y, A;
})();
try {
throw 0;
} catch (n) {
(function() {
(function n() {
c = "PASS";
})();
})();
(function c() {
try {} catch (c) {}
})();
}
console.log(c);
}
expect_stdout: "PASS"
}
issue_3523_ie8: {
mangle = {
ie8: true,
toplevel: false,
}
input: {
var a = 0, b, c = "FAIL";
(function() {
var f, g, h, i, j, k, l, m, n, o, p, q, r, s;
})();
try {
throw 0;
} catch (t) {
(function() {
(function t() {
c = "PASS";
})();
})();
(function e() {
try {} catch (t) {}
})();
}
console.log(c);
}
expect: {
var a = 0, b, c = "FAIL";
(function() {
var c, t, n, o, a, r, f, i, u, h, e, l, v, y;
})();
try {
throw 0;
} catch (t) {
(function() {
(function t() {
c = "PASS";
})();
})();
(function e() {
try {} catch (t) {}
})();
}
console.log(c);
}
expect_stdout: "PASS"
}
issue_3523_toplevel: {
mangle = {
ie8: false,
toplevel: true,
}
input: {
var a = 0, b, c = "FAIL";
(function() {
var f, g, h, i, j, k, l, m, n, o, p, q, r, s;
})();
try {
throw 0;
} catch (t) {
(function() {
(function t() {
c = "PASS";
})();
})();
(function e() {
try {} catch (t) {}
})();
}
console.log(c);
}
expect: {
var c = 0, n, t = "FAIL";
(function() {
var c, n, t, o, r, a, f, i, u, h, l, v, y, A;
})();
try {
throw 0;
} catch (c) {
(function() {
(function c() {
t = "PASS";
})();
})();
(function c() {
try {} catch (c) {}
})();
}
console.log(t);
}
expect_stdout: "PASS"
}
issue_3523_ie8_toplevel: {
mangle = {
ie8: true,
toplevel: true,
}
input: {
var a = 0, b, c = "FAIL";
(function() {
var f, g, h, i, j, k, l, m, n, o, p, q, r, s;
})();
try {
throw 0;
} catch (t) {
(function() {
(function t() {
c = "PASS";
})();
})();
(function e() {
try {} catch (t) {}
})();
}
console.log(c);
}
expect: {
var c = 0, n, t = "FAIL";
(function() {
var c, n, t, o, r, a, f, i, u, h, l, v, y, A;
})();
try {
throw 0;
} catch (o) {
(function() {
(function o() {
t = "PASS";
})();
})();
(function r() {
try {} catch (o) {}
})();
}
console.log(t);
}
expect_stdout: "PASS"
}
issue_3523_rename: {
rename = true
mangle = {
ie8: false,
toplevel: false,
}
input: {
var a = 0, b, c = "FAIL";
(function() {
var d, e, f, g, h, i, j, k, l, m, o, p, q, r;
})();
try {
throw 0;
} catch (e) {
(function() {
(function e() {
c = "PASS";
})();
})();
(function d() {
try {
} catch (e) {
}
})();
}
console.log(c);
}
expect: {
var a = 0, b, c = "FAIL";
(function() {
var c, n, t, o, a, r, f, i, u, h, l, v, y, A;
})();
try {
throw 0;
} catch (n) {
(function() {
(function n() {
c = "PASS";
})();
})();
(function c() {
try {} catch (c) {}
})();
}
console.log(c);
}
expect_stdout: "PASS"
}
issue_3523_rename_ie8: {
rename = true
mangle = {
ie8: true,
toplevel: false,
}
input: {
var a = 0, b, c = "FAIL";
(function() {
var d, e, f, g, h, i, j, k, l, m, o, p, q, r;
})();
try {
throw 0;
} catch (e) {
(function() {
(function e() {
c = "PASS";
})();
})();
(function d() {
try {
} catch (e) {
}
})();
}
console.log(c);
}
expect: {
var a = 0, b, c = "FAIL";
(function() {
var c, n, t, o, a, r, f, i, u, e, h, l, v, y;
})();
try {
throw 0;
} catch (e) {
(function() {
(function n() {
c = "PASS";
})();
})();
(function d() {
try {} catch (e) {}
})();
}
console.log(c);
}
expect_stdout: "PASS"
}
issue_3523_rename_toplevel: {
rename = true
mangle = {
ie8: false,
toplevel: true,
}
input: {
var a = 0, b, c = "FAIL";
(function() {
var d, e, f, g, h, i, j, k, l, m, o, p, q, r;
})();
try {
throw 0;
} catch (e) {
(function() {
(function e() {
c = "PASS";
})();
})();
(function d() {
try {
} catch (e) {
}
})();
}
console.log(c);
}
expect: {
var c = 0, n, t = "FAIL";
(function() {
var c, n, t, o, r, a, f, i, u, h, l, v, y, A;
})();
try {
throw 0;
} catch (c) {
(function() {
(function c() {
t = "PASS";
})();
})();
(function c() {
try {} catch (c) {}
})();
}
console.log(t);
}
expect_stdout: "PASS"
}
issue_3523_rename_ie8_toplevel: {
rename = true
mangle = {
ie8: true,
toplevel: true,
}
input: {
var a = 0, b, c = "FAIL";
(function() {
var d, e, f, g, h, i, j, k, l, m, o, p, q, r;
})();
try {
throw 0;
} catch (e) {
(function() {
(function e() {
c = "PASS";
})();
})();
(function d() {
try {
} catch (e) {
}
})();
}
console.log(c);
}
expect: {
var c = 0, n, t = "FAIL";
(function() {
var c, n, t, o, r, a, f, i, u, h, l, v, y, A;
})();
try {
throw 0;
} catch (o) {
(function() {
(function o() {
t = "PASS";
})();
})();
(function r() {
try {} catch (o) {}
})();
}
console.log(t);
}
expect_stdout: "PASS"
}
issue_3542: {
options = {
ie8: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = 0;
var b = a++;
var c = b && function a() {} || b;
console.log(a);
}
expect: {
var a = 0;
a++;
(function a() {});
console.log(a);
}
expect_stdout: "1"
}

View File

@@ -51,17 +51,20 @@ comparisons: {
comparisons: true,
}
input: {
var x = "42", y = "0x30";
console.log(
~x === 42,
x % n === 42
x % y === 42
);
}
expect: {
var x = "42", y = "0x30";
console.log(
42 == ~x,
x % n == 42
x % y == 42
);
}
expect_stdout: "false true"
}
evaluate_1: {
@@ -103,7 +106,7 @@ evaluate_1: {
}
}
evaluate_2: {
evaluate_1_unsafe_math: {
options = {
evaluate: true,
unsafe_math: true,
@@ -118,6 +121,8 @@ evaluate_2: {
1 + x-- + 2 + 3,
1 + (x*y + 2) + 3,
1 + (2 + x + 3),
1 + (2 + ~x + 3),
-y + (2 + ~x + 3),
1 & (2 & x & 3),
1 + (2 + (x |= 0) + 3)
);
@@ -126,18 +131,138 @@ evaluate_2: {
console.log(
x + 1 + 2,
2 * x,
3 + +x,
+x + 3,
1 + x + 2 + 3,
3 | x,
6 + x--,
6 + x*y,
x*y + 6,
1 + (2 + x + 3),
6 + ~x,
5 - y + ~x,
0 & x,
6 + (x |= 0)
);
}
}
evaluate_2: {
options = {
evaluate: true,
unsafe_math: false,
}
input: {
var x = "42", y = null;
[
x + 1 + 2,
x * 1 * 2,
+x + 1 + 2,
1 + x + 2 + 3,
1 | x | 2 | 3,
1 + x-- + 2 + 3,
1 + (x*y + 2) + 3,
1 + (2 + x + 3),
1 + (2 + ~x + 3),
-y + (2 + ~x + 3),
1 & (2 & x & 3),
1 + (2 + (x |= 0) + 3),
].forEach(function(n) {
console.log(typeof n, n);
});
}
expect: {
var x = "42", y = null;
[
x + 1 + 2,
1 * x * 2,
+x + 1 + 2,
1 + x + 2 + 3,
3 | x,
1 + x-- + 2 + 3,
x*y + 2 + 1 + 3,
1 + (2 + x + 3),
2 + ~x + 3 + 1,
2 + ~x + 3 - y,
0 & x,
2 + (x |= 0) + 3 + 1,
].forEach(function(n) {
console.log(typeof n, n);
});
}
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: {
options = {
evaluate: true,
unsafe_math: true,
}
input: {
var x = "42", y = null;
[
x + 1 + 2,
x * 1 * 2,
+x + 1 + 2,
1 + x + 2 + 3,
1 | x | 2 | 3,
1 + x-- + 2 + 3,
1 + (x*y + 2) + 3,
1 + (2 + x + 3),
1 + (2 + ~x + 3),
-y + (2 + ~x + 3),
1 & (2 & x & 3),
1 + (2 + (x |= 0) + 3),
].forEach(function(n) {
console.log(typeof n, n);
});
}
expect: {
var x = "42", y = null;
[
x + 1 + 2,
2 * x,
+x + 3,
1 + x + 2 + 3,
3 | x,
6 + x--,
x*y + 6,
1 + (2 + x + 3),
6 + ~x,
5 + ~x - y,
0 & x,
6 + (x |= 0),
].forEach(function(n) {
console.log(typeof n, n);
});
}
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: {
options = {
evaluate: true,
@@ -148,7 +273,7 @@ evaluate_3: {
console.log(1 + Number(x) + 2);
}
expect: {
console.log(3 + +x);
console.log(+x + 3);
}
}
@@ -182,6 +307,352 @@ evaluate_4: {
}
}
evaluate_5: {
options = {
evaluate: true,
unsafe_math: false,
}
input: {
var a = "1";
[
+a + 2 + 3,
+a + 2 - 3,
+a - 2 + 3,
+a - 2 - 3,
2 + +a + 3,
2 + +a - 3,
2 - +a + 3,
2 - +a - 3,
2 + 3 + +a,
2 + 3 - +a,
2 - 3 + +a,
2 - 3 - +a,
].forEach(function(n) {
console.log(typeof n, n);
});
}
expect: {
var a = "1";
[
+a + 2 + 3,
+a + 2 - 3,
a - 2 + 3,
a - 2 - 3,
+a + 2 + 3,
+a + 2 - 3,
2 - a + 3,
2 - a - 3,
+a + 5,
5 - a,
+a - 1,
-1 - a,
].forEach(function(n) {
console.log(typeof n, n);
});
}
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: {
options = {
evaluate: true,
unsafe_math: true,
}
input: {
var a = "1";
[
+a + 2 + 3,
+a + 2 - 3,
+a - 2 + 3,
+a - 2 - 3,
2 + +a + 3,
2 + +a - 3,
2 - +a + 3,
2 - +a - 3,
2 + 3 + +a,
2 + 3 - +a,
2 - 3 + +a,
2 - 3 - +a,
].forEach(function(n) {
console.log(typeof n, n);
});
}
expect: {
var a = "1";
[
+a + 5,
+a + -1,
a - -1,
a - 5,
+a + 5,
+a + -1,
5 - a,
-1 - a,
+a + 5,
5 - a,
+a - 1,
-1 - a,
].forEach(function(n) {
console.log(typeof n, n);
});
}
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: {
options = {
evaluate: true,
unsafe_math: false,
}
input: {
var a = "1";
[
-a + 2 + 3,
-a + 2 - 3,
-a - 2 + 3,
-a - 2 - 3,
2 + -a + 3,
2 + -a - 3,
2 - -a + 3,
2 - -a - 3,
2 + 3 + -a,
2 + 3 - -a,
2 - 3 + -a,
2 - 3 - -a,
].forEach(function(n) {
console.log(typeof n, n);
});
}
expect: {
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,
5 - a,
5 - -a,
-1 - a,
-1 - -a,
].forEach(function(n) {
console.log(typeof n, n);
});
}
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: {
options = {
evaluate: true,
unsafe_math: true,
}
input: {
var a = "1";
[
-a + 2 + 3,
-a + 2 - 3,
-a - 2 + 3,
-a - 2 - 3,
2 + -a + 3,
2 + -a - 3,
2 - -a + 3,
2 - -a - 3,
2 + 3 + -a,
2 + 3 - -a,
2 - 3 + -a,
2 - 3 - -a,
].forEach(function(n) {
console.log(typeof n, n);
});
}
expect: {
var a = "1";
[
5 - a,
-1 - a,
-a - -1,
-a - 5,
5 - a,
-1 - a,
5 - -a,
-1 - -a,
5 - a,
5 - -a,
-1 - a,
-1 - -a,
].forEach(function(n) {
console.log(typeof n, n);
});
}
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: {
options = {
evaluate: true,
unsafe_math: false,
}
input: {
var x = "42", 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),
+x - 2 - (3 - !y),
].forEach(function(n) {
console.log(typeof n, n);
});
}
expect: {
var x = "42", 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),
x - 2 - (3 - !y),
].forEach(function(n) {
console.log(typeof n, n);
});
}
expect_stdout: [
"number 48",
"number 46",
"number 40",
"number 42",
"number 44",
"number 42",
"number 36",
"number 38",
]
}
evaluate_7_unsafe_math: {
options = {
evaluate: true,
unsafe_math: true,
}
input: {
var x = "42", 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),
+x - 2 - (3 - !y),
].forEach(function(n) {
console.log(typeof n, n);
});
}
expect: {
var x = "42", y;
[
+x + 5 + !y,
+x + 5 - !y,
+x + -1 - !y,
+x + -1 + !y,
x - -1 + !y,
x - -1 - !y,
x - 5 - !y,
x - 5 + !y,
].forEach(function(n) {
console.log(typeof n, n);
});
}
expect_stdout: [
"number 48",
"number 46",
"number 40",
"number 42",
"number 44",
"number 42",
"number 36",
"number 38",
]
}
NaN_redefined: {
options = {
evaluate: true,
unsafe_math: true,
}
input: {
var NaN;
console.log(1 / (0 / 0));
}
expect: {
var NaN;
console.log(0 / 0);
}
expect_stdout: "NaN"
}
issue_1710: {
options = {
evaluate: true,
@@ -230,3 +701,83 @@ unary_binary_parenthesis: {
}
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 - .3));
}
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"
}
issue_3536: {
options = {
evaluate: true,
unsafe_math: true,
}
input: {
var a = 100, b = 10;
var c = --a + ("23" - (b++, 1));
console.log(typeof c, a, b, c);
}
expect: {
var a = 100, b = 10;
var c = --a + ("23" - (b++, 1));
console.log(typeof c, a, b, c);
}
expect_stdout: "number 99 11 121"
}
issue_3539: {
options = {
evaluate: true,
unsafe_math: true,
}
input: {
var a = -0 + -"";
console.log(0/a, 1/a, -1/a);
}
expect: {
var a = -0;
console.log(0/a, 1/a, -1/a);
}
expect_stdout: "NaN -Infinity Infinity"
}

View File

@@ -1,3 +1,6 @@
setInterval(function() {
process.stderr.write("\0");
}, 8 * 60 * 1000).unref();
require("./run")([
"-b",
"-b braces",

File diff suppressed because it is too large Load Diff