1 // Copyright 2008 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 // Flags: --harmony-simd 29 30 /** 31 * This test uses assert{True,False}(... == ...) instead of 32 * assertEquals(..., ...) to not rely on the details of the 33 * implementation of assertEquals. 34 */ 35 36 function testEqual(a, b) { 37 assertTrue(a == b); 38 assertTrue(b == a); 39 assertFalse(a != b); 40 assertFalse(b != a); 41 } 42 43 function testNotEqual(a, b) { 44 assertFalse(a == b); 45 assertFalse(b == a); 46 assertTrue(a != b); 47 assertTrue(b != a); 48 } 49 50 // Object where ToPrimitive returns value. 51 function Wrapper(value) { 52 this.value = value; 53 this.valueOf = function () { return this.value; }; 54 } 55 56 // Object where ToPrimitive returns value by failover to toString when 57 // valueOf isn't a function. 58 function Wrapper2(value) { 59 this.value = value; 60 this.valueOf = null; 61 this.toString = function () { return this.value; }; 62 } 63 64 65 // Compare values of same type. 66 67 // Numbers are equal if same, unless NaN, which isn't equal to anything, and 68 // +/-0 being equal. 69 70 testNotEqual(NaN, NaN); 71 testNotEqual(NaN, 0); 72 testNotEqual(NaN, Infinity); 73 74 testEqual(Number.MAX_VALUE, Number.MAX_VALUE); 75 testEqual(Number.MIN_VALUE, Number.MIN_VALUE); 76 testEqual(Infinity, Infinity); 77 testEqual(-Infinity, -Infinity); 78 79 testEqual(0, 0); 80 testEqual(0, -0); 81 testEqual(-0, -0); 82 83 testNotEqual(0.9, 1); 84 testNotEqual(0.999999, 1); 85 testNotEqual(0.9999999999, 1); 86 testNotEqual(0.9999999999999, 1); 87 88 // Strings are equal if containing the same code points. 89 90 testEqual('hello', 'hello'); 91 testEqual('hello', 'hel' + 'lo'); 92 testEqual('', ''); 93 testEqual('\u0020\x20', ' '); // Escapes are not part of the value. 94 95 // Booleans are equal if they are the same. 96 97 testEqual(true, true); 98 testEqual(false, false); 99 testNotEqual(true, false); 100 101 // Null and undefined are equal to themselves. 102 103 testEqual(null, null); 104 testEqual(undefined, undefined); 105 106 // Objects are equal if they are the same object only. 107 108 testEqual(Math, Math); 109 testEqual(Object.prototype, Object.prototype); 110 111 112 (function () { 113 var x = new Wrapper(null); 114 var y = x, z = x; 115 testEqual(y, x); 116 })(); 117 118 (function () { 119 var x = new Boolean(true); 120 var y = x, z = x; 121 testEqual(y, x); 122 })(); 123 124 (function () { 125 var x = new Boolean(false); 126 var y = x, z = x; 127 testEqual(y, x); 128 })(); 129 130 // Test comparing values of different types. 131 132 // Null and undefined are equal to each-other, and to nothing else. 133 testEqual(null, undefined); 134 testEqual(undefined, null); 135 136 testNotEqual(null, new Wrapper(null)); 137 testNotEqual(null, 0); 138 testNotEqual(null, false); 139 testNotEqual(null, ""); 140 testNotEqual(null, new Object()); 141 testNotEqual(undefined, new Wrapper(undefined)); 142 testNotEqual(undefined, 0); 143 testNotEqual(undefined, false); 144 testNotEqual(undefined, ""); 145 testNotEqual(undefined, new Object()); 146 147 // Numbers compared to Strings will convert the string to a number using 148 // the internal ToNumber conversion. 149 150 testEqual(1, '1'); 151 testEqual(255, '0xff'); 152 testEqual(0, '\r'); // ToNumber ignores tailing and trailing whitespace. 153 testEqual(1e19, '1e19'); 154 testEqual(Infinity, "Infinity"); 155 156 // Booleans compared to anything else will be converted to numbers. 157 testEqual(false, 0); 158 testEqual(true, 1); 159 testEqual(false, "0"); // String also converted to number. 160 testEqual(true, "1"); 161 162 // Objects compared to Number or String (or Boolean, since that's converted 163 // to Number too) is converted to primitive using ToPrimitive with NO HINT. 164 // Having no hint means Date gets a string hint, and everything else gets 165 // a number hint. 166 167 testEqual(new Boolean(true), true); 168 testEqual(new Boolean(true), 1); // First to primtive boolean, then to number. 169 testEqual(new Boolean(false), false); 170 testEqual(new Boolean(false), 0); 171 172 testEqual(new Wrapper(true), true); 173 testEqual(new Wrapper(true), 1); 174 testEqual(new Wrapper(false), false); 175 testEqual(new Wrapper(false), 0); 176 177 testEqual(new Wrapper2(true), true); 178 testEqual(new Wrapper2(true), 1); 179 testEqual(new Wrapper2(false), false); 180 testEqual(new Wrapper2(false), 0); 181 182 testEqual(new Number(1), true); 183 testEqual(new Number(1), 1); 184 testEqual(new Number(0), false); 185 testEqual(new Number(0), 0); 186 187 // Date objects convert to string, not number (and the string does not 188 // convert to the number). 189 testEqual(new Date(42), String(new Date(42))); 190 testNotEqual(new Date(42), Number(new Date(42))); 191 var dnow = new Date(); 192 testEqual(dnow, dnow); 193 testEqual(dnow, String(dnow)); 194 testNotEqual(dnow, Number(dnow)); 195 196 // Doesn't just call toString, but uses ToPrimitive which tries toString first 197 // and valueOf second. 198 dnow.toString = null; 199 testEqual(dnow, Number(dnow)); 200 dnow.valueOf = function () { return "42"; }; 201 testEqual(dnow, 42); 202 dnow.toString = function () { return "1"; }; 203 testEqual(dnow, true); 204 205 206 // Objects compared to other objects, or to null and undefined, are not 207 // converted to primitive. 208 testNotEqual(new Wrapper(null), new Wrapper(null)); 209 testNotEqual(new Boolean(true), new Boolean(true)); 210 testNotEqual(new Boolean(false), new Boolean(false)); 211 testNotEqual(new String("a"), new String("a")); 212 testNotEqual(new Number(42), new Number(42)); 213 testNotEqual(new Date(42), new Date(42)); 214 testNotEqual(new Array(42), new Array(42)); 215 testNotEqual(new Object(), new Object()); 216 217 // Object that can't be converted to primitive. 218 var badObject = { 219 valueOf: null, 220 toString: function() { 221 return this; // Not primitive. 222 } 223 }; 224 225 testEqual(badObject, badObject); 226 testNotEqual(badObject, {}); 227 testNotEqual(badObject, null); 228 testNotEqual(badObject, undefined); 229 // Forcing conversion will throw. 230 function testBadConversion(value) { 231 assertThrows(function() { return badObject == value; }); 232 assertThrows(function() { return badObject != value; }); 233 assertThrows(function() { return value == badObject; }); 234 assertThrows(function() { return value != badObject; }); 235 } 236 testBadConversion(0); 237 testBadConversion("string"); 238 testBadConversion(true); 239 240 var s = Symbol(); 241 testEqual(s, s); 242 testEqual(Object(s), s); 243 testEqual(new Wrapper(s), s); 244 testNotEqual(Object(s), Object(s)); 245 246 var simd = SIMD.Float32x4(1, 2, 3, 4); 247 testEqual(simd, simd); 248 testEqual(Object(simd), simd); 249 testEqual(new Wrapper(simd), simd); 250 testNotEqual(Object(simd), Object(simd)); 251