if (!value && props[i].key === key) value = props[i].value;
}
}
- return value instanceof AST_SymbolRef ? value.fixed_value() : value;
+ return value instanceof AST_SymbolRef && value.fixed_value() || value;
}
function is_modified(node, value, level, immutable) {
});
var commutativeOperators = makePredicate("== === != !== * & | ^");
+ function is_object(node) {
+ return node instanceof AST_Array
+ || node instanceof AST_Lambda
+ || node instanceof AST_Object;
+ }
OPT(AST_Binary, function(self, compressor){
function reversible() {
case "!==":
if ((self.left.is_string(compressor) && self.right.is_string(compressor)) ||
(self.left.is_number(compressor) && self.right.is_number(compressor)) ||
- (self.left.is_boolean() && self.right.is_boolean())) {
+ (self.left.is_boolean() && self.right.is_boolean()) ||
+ self.left.equivalent_to(self.right)) {
self.operator = self.operator.substr(0, 2);
}
// XXX: intentionally falling down to the next case
if (self.operator.length == 2) self.operator += "=";
}
}
+ // obj !== obj => false
+ else if (self.left instanceof AST_SymbolRef
+ && self.right instanceof AST_SymbolRef
+ && self.left.definition() === self.right.definition()
+ && is_object(self.left.fixed_value())) {
+ return make_node(self.operator[0] == "=" ? AST_True : AST_False, self);
+ }
break;
}
if (compressor.option("booleans") && self.operator == "+" && compressor.in_boolean_context()) {
1 instanceof 1;
null instanceof null;
}
-}
\ No newline at end of file
+}
+
+self_comparison_1: {
+ options = {
+ comparisons: true,
+ }
+ input: {
+ a === a;
+ a !== b;
+ b.c === a.c;
+ b.c !== b.c;
+ }
+ expect: {
+ a == a;
+ a !== b;
+ b.c === a.c;
+ b.c != b.c;
+ }
+}
+
+self_comparison_2: {
+ options = {
+ comparisons: true,
+ reduce_vars: true,
+ toplevel: true,
+ }
+ input: {
+ function f() {}
+ var o = {};
+ console.log(f != f, o === o);
+ }
+ expect: {
+ function f() {}
+ var o = {};
+ console.log(false, true);
+ }
+ expect_stdout: "false true"
+}
}
expect_stdout: true
}
+
+self_comparison_1: {
+ options = {
+ evaluate: true,
+ reduce_vars: true,
+ toplevel: true,
+ unsafe: true,
+ unused: true,
+ }
+ input: {
+ var o = { n: NaN };
+ console.log(o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n, typeof o.n);
+ }
+ expect: {
+ console.log(false, false, true, true, "number");
+ }
+ expect_stdout: "false false true true 'number'"
+}
+
+self_comparison_2: {
+ options = {
+ evaluate: true,
+ hoist_props: true,
+ passes: 2,
+ reduce_vars: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ var o = { n: NaN };
+ console.log(o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n, typeof o.n);
+ }
+ expect: {
+ console.log(false, false, true, true, "number");
+ }
+ expect_stdout: "false false true true 'number'"
+}