fix LHS cases for NaN & friends (#1804)

`Infinity = beyond` should not become `1/0 = beyond`
This commit is contained in:
Alex Lam S.L
2017-04-09 03:18:14 +08:00
committed by GitHub
parent 9a978843f5
commit d6fbc365e2
2 changed files with 47 additions and 20 deletions

View File

@@ -404,7 +404,7 @@ merge(Compressor.prototype, {
function is_modified(node, level, func) { function is_modified(node, level, func) {
var parent = tw.parent(level); var parent = tw.parent(level);
if (isLHS(node, parent) if (is_lhs(node, parent)
|| !func && parent instanceof AST_Call && parent.expression === node) { || !func && parent instanceof AST_Call && parent.expression === node) {
return true; return true;
} else if (parent instanceof AST_PropAccess && parent.expression === node) { } else if (parent instanceof AST_PropAccess && parent.expression === node) {
@@ -697,7 +697,7 @@ merge(Compressor.prototype, {
return statements; return statements;
function is_lvalue(node, parent) { function is_lvalue(node, parent) {
return node instanceof AST_SymbolRef && isLHS(node, parent); return node instanceof AST_SymbolRef && is_lhs(node, parent);
} }
function replace_var(node, parent, is_constant) { function replace_var(node, parent, is_constant) {
if (is_lvalue(node, parent)) return node; if (is_lvalue(node, parent)) return node;
@@ -1299,9 +1299,9 @@ merge(Compressor.prototype, {
var unary_side_effects = makePredicate("delete ++ --"); var unary_side_effects = makePredicate("delete ++ --");
function isLHS(node, parent) { function is_lhs(node, parent) {
return parent instanceof AST_Unary && unary_side_effects(parent.operator) if (parent instanceof AST_Unary && unary_side_effects(parent.operator)) return parent.expression;
|| parent instanceof AST_Assign && parent.left === node; if (parent instanceof AST_Assign && parent.left === node) return node;
} }
(function (def){ (function (def){
@@ -1314,7 +1314,7 @@ merge(Compressor.prototype, {
node = parent; node = parent;
parent = compressor.parent(level++); parent = compressor.parent(level++);
} while (parent instanceof AST_PropAccess && parent.expression === node); } while (parent instanceof AST_PropAccess && parent.expression === node);
if (isLHS(node, parent)) { if (is_lhs(node, parent)) {
compressor.warn('global_defs ' + this.print_to_string() + ' redefined [{file}:{line},{col}]', this.start); compressor.warn('global_defs ' + this.print_to_string() + ' redefined [{file}:{line},{col}]', this.start);
} else { } else {
return def; return def;
@@ -3620,12 +3620,8 @@ merge(Compressor.prototype, {
return self; return self;
}); });
function in_delete(parent) { function is_atomic(lhs, self) {
return parent instanceof AST_UnaryPrefix && parent.operator == "delete"; return lhs instanceof AST_SymbolRef || lhs.TYPE === self.TYPE;
}
function is_atomic(parent, self) {
return parent.expression instanceof AST_SymbolRef || parent.expression.TYPE === self.TYPE;
} }
OPT(AST_Undefined, function(self, compressor){ OPT(AST_Undefined, function(self, compressor){
@@ -3641,8 +3637,8 @@ merge(Compressor.prototype, {
return ref; return ref;
} }
} }
var parent = compressor.parent(); var lhs = is_lhs(compressor.self(), compressor.parent());
if (in_delete(parent) && is_atomic(parent, self)) return self; if (lhs && is_atomic(lhs, self)) return self;
return make_node(AST_UnaryPrefix, self, { return make_node(AST_UnaryPrefix, self, {
operator: "void", operator: "void",
expression: make_node(AST_Number, self, { expression: make_node(AST_Number, self, {
@@ -3652,11 +3648,10 @@ merge(Compressor.prototype, {
}); });
OPT(AST_Infinity, function(self, compressor){ OPT(AST_Infinity, function(self, compressor){
var parent = compressor.parent(); var lhs = is_lhs(compressor.self(), compressor.parent());
var del = in_delete(parent); if (lhs && is_atomic(lhs, self)) return self;
if (del && is_atomic(parent, self)) return self;
if (compressor.option("keep_infinity") if (compressor.option("keep_infinity")
&& !(del && !is_atomic(parent, self)) && !(lhs && !is_atomic(lhs, self))
&& !find_variable(compressor, "Infinity")) && !find_variable(compressor, "Infinity"))
return self; return self;
return make_node(AST_Binary, self, { return make_node(AST_Binary, self, {
@@ -3671,8 +3666,8 @@ merge(Compressor.prototype, {
}); });
OPT(AST_NaN, function(self, compressor){ OPT(AST_NaN, function(self, compressor){
var parent = compressor.parent(); var lhs = is_lhs(compressor.self(), compressor.parent());
if (in_delete(parent) && !is_atomic(parent, self) if (lhs && !is_atomic(lhs, self)
|| find_variable(compressor, "NaN")) { || find_variable(compressor, "NaN")) {
return make_node(AST_Binary, self, { return make_node(AST_Binary, self, {
operator: "/", operator: "/",

View File

@@ -957,3 +957,35 @@ delete_binary_2: {
} }
expect_stdout: true expect_stdout: true
} }
Infinity_NaN_undefined_LHS: {
beautify = {
beautify: true,
}
input: {
function f() {
Infinity = Infinity;
++Infinity;
Infinity--;
NaN *= NaN;
++NaN;
NaN--;
undefined |= undefined;
++undefined;
undefined--;
}
}
expect_exact: [
"function f() {",
" Infinity = 1 / 0;",
" ++Infinity;",
" Infinity--;",
" NaN *= NaN;",
" ++NaN;",
" NaN--;",
" undefined |= void 0;",
" ++undefined;",
" undefined--;",
"}",
]
}