From: Anthony Van de Gejuchte Date: Mon, 13 Jun 2016 16:19:06 +0000 (+0200) Subject: Fix test262 failures related to <, <=, in and instanceof X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=d7971ba0e439eb042fd880762bc7fa77ce1f3e73;p=UglifyJS.git Fix test262 failures related to <, <=, in and instanceof Fixed-by: @kzc --- diff --git a/README.md b/README.md index 041a0709..b0ac7121 100644 --- a/README.md +++ b/README.md @@ -291,12 +291,19 @@ to set `true`; it's effectively a shortcut for `foo=true`). - `unsafe` (default: false) -- apply "unsafe" transformations (discussion below) +- `unsafe_comps` (default: false) -- Reverse `<` and `<=` to `>` and `>=` to + allow improved compression. This might be unsafe when an at least one of two + operands is an object with computed values due the use of methods like `get`, + or `valueOf`. This could cause change in execution order after operands in the + comparison are switching. Compression only works if both `comparisons` and + `unsafe_comps` are both set to true. + - `conditionals` -- apply optimizations for `if`-s and conditional expressions - `comparisons` -- apply certain optimizations to binary nodes, for example: - `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes, - e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc. + `!(a <= b) → a > b` (only when `unsafe_comps`), attempts to negate binary + nodes, e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc. - `evaluate` -- attempt to evaluate constant expressions @@ -415,7 +422,7 @@ them. If you are targeting < ES6 environments, use `/** @const */ var`. #### Conditional compilation, API -You can also use conditional compilation via the programmatic API. With the difference that the +You can also use conditional compilation via the programmatic API. With the difference that the property name is `global_defs` and is a compressor property: ```js diff --git a/lib/compress.js b/lib/compress.js index 4e04e961..3200a66f 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1079,8 +1079,6 @@ merge(Compressor.prototype, { case "<=" : return ev(left, c) <= ev(right, c); case ">" : return ev(left, c) > ev(right, c); case ">=" : return ev(left, c) >= ev(right, c); - case "in" : return ev(left, c) in ev(right, c); - case "instanceof" : return ev(left, c) instanceof ev(right, c); } throw def; }); @@ -2502,9 +2500,11 @@ merge(Compressor.prototype, { }); self = best_of(self, negated); } - switch (self.operator) { - case "<": reverse(">"); break; - case "<=": reverse(">="); break; + if (compressor.option("unsafe_comps")) { + switch (self.operator) { + case "<": reverse(">"); break; + case "<=": reverse(">="); break; + } } } if (self.operator == "+" && self.right instanceof AST_String diff --git a/test/compress/asm.js b/test/compress/asm.js index c3018485..f392e78e 100644 --- a/test/compress/asm.js +++ b/test/compress/asm.js @@ -92,7 +92,7 @@ asm_mixed: { function logSum(start, end) { start = 0 | start, end = 0 | end; var sum = 0, p = 0, q = 0; - for (p = start << 3, q = end << 3; (0 | q) > (0 | p); p = p + 8 | 0) sum += +log(values[p >> 3]); + for (p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]); return +sum; } function geometricMean(start, end) { diff --git a/test/compress/comparing.js b/test/compress/comparing.js new file mode 100644 index 00000000..c51fac31 --- /dev/null +++ b/test/compress/comparing.js @@ -0,0 +1,76 @@ +keep_comparisons: { + options = { + comparisons: true, + unsafe_comps: false + } + input: { + var obj1 = { + valueOf: function() {triggeredFirst();} + } + var obj2 = { + valueOf: function() {triggeredSecond();} + } + var result1 = obj1 <= obj2; + var result2 = obj1 < obj2; + var result3 = obj1 >= obj2; + var result4 = obj1 > obj2; + } + expect: { + var obj1 = { + valueOf: function() {triggeredFirst();} + } + var obj2 = { + valueOf: function() {triggeredSecond();} + } + var result1 = obj1 <= obj2; + var result2 = obj1 < obj2; + var result3 = obj1 >= obj2; + var result4 = obj1 > obj2; + } +} + +keep_comparisons_with_unsafe_comps: { + options = { + comparisons: true, + unsafe_comps: true + } + input: { + var obj1 = { + valueOf: function() {triggeredFirst();} + } + var obj2 = { + valueOf: function() {triggeredSecond();} + } + var result1 = obj1 <= obj2; + var result2 = obj1 < obj2; + var result3 = obj1 >= obj2; + var result4 = obj1 > obj2; + } + expect: { + var obj1 = { + valueOf: function() {triggeredFirst();} + } + var obj2 = { + valueOf: function() {triggeredSecond();} + } + var result1 = obj2 >= obj1; + var result2 = obj2 > obj1; + var result3 = obj1 >= obj2; + var result4 = obj1 > obj2; + } +} + +dont_change_in_or_instanceof_expressions: { + input: { + 1 in 1; + null in null; + 1 instanceof 1; + null instanceof null; + } + expect: { + 1 in 1; + null in null; + 1 instanceof 1; + null instanceof null; + } +} \ No newline at end of file