From 0c003c92a85bd845dec8a10ee567c46b696c1403 Mon Sep 17 00:00:00 2001 From: kzc Date: Sat, 18 Jun 2016 23:06:59 -0400 Subject: [PATCH] Don't replace undefined, NaN and Infinity within with scope --- lib/compress.js | 71 +++++++++++++++------------ test/compress/issue-1105.js | 95 ++++++++++++++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 32 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 3200a66f..db6a26d6 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1056,31 +1056,37 @@ merge(Compressor.prototype, { throw def; }); def(AST_Binary, function(c){ - var left = this.left, right = this.right; + var left = this.left, right = this.right, result; switch (this.operator) { - 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 "&" : return ev(left, c) & ev(right, c); - 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 "/" : return ev(left, c) / ev(right, c); - 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 ">>" : return ev(left, c) >> ev(right, c); - 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 "!=" : return ev(left, c) != ev(right, c); - 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 ">" : return ev(left, c) > ev(right, c); - case ">=" : return ev(left, c) >= ev(right, c); - } - throw def; + case "&&" : result = ev(left, c) && ev(right, c); break; + case "||" : result = ev(left, c) || ev(right, c); break; + case "|" : result = ev(left, c) | ev(right, c); break; + case "&" : result = ev(left, c) & ev(right, c); break; + case "^" : result = ev(left, c) ^ ev(right, c); break; + case "+" : result = ev(left, c) + ev(right, c); break; + case "*" : result = ev(left, c) * ev(right, c); break; + case "/" : result = ev(left, c) / ev(right, c); break; + case "%" : result = ev(left, c) % ev(right, c); break; + case "-" : result = ev(left, c) - ev(right, c); break; + case "<<" : result = ev(left, c) << ev(right, c); break; + case ">>" : result = ev(left, c) >> ev(right, c); break; + case ">>>" : result = ev(left, c) >>> ev(right, c); break; + case "==" : result = ev(left, c) == ev(right, c); break; + case "===" : result = ev(left, c) === ev(right, c); break; + case "!=" : result = ev(left, c) != ev(right, c); break; + case "!==" : result = ev(left, c) !== ev(right, c); break; + case "<" : result = ev(left, c) < ev(right, c); break; + case "<=" : result = ev(left, c) <= ev(right, c); break; + case ">" : result = ev(left, c) > ev(right, c); break; + case ">=" : result = ev(left, c) >= ev(right, c); break; + default: + throw def; + } + if (isNaN(result) && c.find_parent(AST_With)) { + // leave original expression as is + throw def; + } + return result; }); def(AST_Conditional, function(compressor){ return ev(this.condition, compressor) @@ -2599,13 +2605,16 @@ merge(Compressor.prototype, { if (defines && HOP(defines, self.name)) { return make_node_from_constant(compressor, defines[self.name], self); } - switch (self.name) { - case "undefined": - return make_node(AST_Undefined, self); - case "NaN": - return make_node(AST_NaN, self).transform(compressor); - case "Infinity": - return make_node(AST_Infinity, self).transform(compressor); + // testing against !self.scope.uses_with first is an optimization + if (!self.scope.uses_with || !compressor.find_parent(AST_With)) { + switch (self.name) { + case "undefined": + return make_node(AST_Undefined, self); + case "NaN": + return make_node(AST_NaN, self).transform(compressor); + case "Infinity": + return make_node(AST_Infinity, self).transform(compressor); + } } } return self; diff --git a/test/compress/issue-1105.js b/test/compress/issue-1105.js index 4205fdf5..28f1557a 100644 --- a/test/compress/issue-1105.js +++ b/test/compress/issue-1105.js @@ -144,4 +144,97 @@ check_drop_unused_in_peer_function: { bar(); } } -} \ No newline at end of file +} + +Infinity_not_in_with_scope: { + options = { + unused: true + } + input: { + var o = { Infinity: 'oInfinity' }; + var vInfinity = "Infinity"; + vInfinity = Infinity; + } + expect: { + var o = { Infinity: 'oInfinity' } + var vInfinity = "Infinity" + vInfinity = 1/0 + } +} + +Infinity_in_with_scope: { + options = { + unused: true + } + input: { + var o = { Infinity: 'oInfinity' }; + var vInfinity = "Infinity"; + with (o) { vInfinity = Infinity; } + } + expect: { + var o = { Infinity: 'oInfinity' } + var vInfinity = "Infinity" + with (o) vInfinity = Infinity + } +} + +assorted_Infinity_NaN_undefined_in_with_scope: { + options = { + unused: true, + evaluate: true, + dead_code: true, + conditionals: true, + comparisons: true, + booleans: true, + hoist_funs: true, + keep_fargs: true, + if_return: true, + join_vars: true, + cascade: true, + side_effects: true, + sequences: false, + } + input: { + var o = { + undefined : 3, + NaN : 4, + Infinity : 5, + } + if (o) { + f(undefined, void 0); + f(NaN, 0/0); + f(Infinity, 1/0); + f(-Infinity, -(1/0)); + f(2 + 7 + undefined, 2 + 7 + void 0); + } + with (o) { + f(undefined, void 0); + f(NaN, 0/0); + f(Infinity, 1/0); + f(-Infinity, -(1/0)); + f(2 + 7 + undefined, 2 + 7 + void 0); + } + } + expect: { + var o = { + undefined : 3, + NaN : 4, + Infinity : 5 + } + if (o) { + f(void 0, void 0); + f(NaN, NaN); + f(1/0, 1/0); + f(-(1/0), -(1/0)); + f(NaN, NaN); + } + with (o) { + f(undefined, void 0); + f(NaN, 0/0); + f(Infinity, 1/0); + f(-Infinity, -(1/0)); + f(9 + undefined, 9 + void 0); + } + } +} + -- 2.34.1