object-class-tostring.js (1852B)
1 function testCongruent(i) { 2 var p = {}; 3 var o = { 4 // Add toString as an own property, so it'll be always found on this object, 5 // even when properties are changed on the prototype. 6 toString: Object.prototype.toString, 7 8 // Add a custom prototype, so we can add @@toStringTag without modifying the 9 // shape of this object. 10 __proto__: p, 11 }; 12 var xs = [{}, p]; 13 var ys = ["[object Object]", "[object Test]"]; 14 15 for (var j = 0; j <= 100; ++j) { 16 // Don't use if-statements to avoid cold code bailouts 17 var x = xs[(i === 1 && j === 100)|0]; 18 var y = ys[(i === 1 && j === 100)|0]; 19 20 // |o.toString()| must be executed twice, because |x[Symbol.toStringTag]| may 21 // have modified |o|. 22 var r = o.toString(); 23 x[Symbol.toStringTag] = "Test"; 24 var e = o.toString(); 25 26 assertEq(r, "[object Object]"); 27 assertEq(e, y); 28 } 29 } 30 for (var i = 0; i < 2; ++i) testCongruent(i); 31 32 function testUnobserved(i) { 33 var p = {}; 34 var o = { 35 // Add toString as an own property, so it'll be always found on this object, 36 // even when properties are changed on the prototype. 37 toString: Object.prototype.toString, 38 39 // Add a custom prototype, so we can add @@toStringTag without modifying the 40 // shape of this object. 41 __proto__: p, 42 }; 43 var xs = [{}, p]; 44 var ys = [false, true]; 45 46 for (var j = 0; j <= 100; ++j) { 47 // Don't use if-statements to avoid cold code bailouts 48 var x = xs[(i === 1 && j === 100)|0]; 49 var y = ys[(i === 1 && j === 100)|0]; 50 51 var executed = false; 52 Object.defineProperty(x, Symbol.toStringTag, { 53 configurable: true, 54 get() { 55 executed = true; 56 } 57 }); 58 59 // |o.toString()| must be executed even when the result isn't observed. 60 o.toString(); 61 62 assertEq(executed, y); 63 } 64 } 65 for (var i = 0; i < 2; ++i) testUnobserved(i);