1// Copyright 2015 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// Flags: --harmony-tostring --harmony-proxies 6 7var global = this; 8 9var funs = { 10 Object: [ Object ], 11 Function: [ Function ], 12 Array: [ Array ], 13 String: [ String ], 14 Boolean: [ Boolean ], 15 Number: [ Number ], 16 Date: [ Date ], 17 RegExp: [ RegExp ], 18 Error: [ Error, TypeError, RangeError, SyntaxError, ReferenceError, 19 EvalError, URIError ] 20} 21for (f in funs) { 22 for (i in funs[f]) { 23 assertEquals("[object " + f + "]", 24 Object.prototype.toString.call(new funs[f][i]), 25 funs[f][i]); 26 assertEquals("[object Function]", 27 Object.prototype.toString.call(funs[f][i]), 28 funs[f][i]); 29 } 30} 31 32function testToStringTag(className) { 33 // Using builtin toStringTags 34 var obj = {}; 35 obj[Symbol.toStringTag] = className; 36 assertEquals("[object " + className + "]", 37 Object.prototype.toString.call(obj)); 38 39 // Getter throws 40 obj = {}; 41 Object.defineProperty(obj, Symbol.toStringTag, { 42 get: function() { throw className; } 43 }); 44 assertThrowsEquals(function() { 45 Object.prototype.toString.call(obj); 46 }, className); 47 48 // Getter does not throw 49 obj = {}; 50 Object.defineProperty(obj, Symbol.toStringTag, { 51 get: function() { return className; } 52 }); 53 assertEquals("[object " + className + "]", 54 Object.prototype.toString.call(obj)); 55 56 // Custom, non-builtin toStringTags 57 obj = {}; 58 obj[Symbol.toStringTag] = "X" + className; 59 assertEquals("[object X" + className + "]", 60 Object.prototype.toString.call(obj)); 61 62 // With getter 63 obj = {}; 64 Object.defineProperty(obj, Symbol.toStringTag, { 65 get: function() { return "X" + className; } 66 }); 67 assertEquals("[object X" + className + "]", 68 Object.prototype.toString.call(obj)); 69 70 // Undefined toStringTag should return [object className] 71 var obj = className === "Arguments" ? 72 (function() { return arguments; })() : new global[className]; 73 obj[Symbol.toStringTag] = undefined; 74 assertEquals("[object " + className + "]", 75 Object.prototype.toString.call(obj)); 76 77 // With getter 78 var obj = className === "Arguments" ? 79 (function() { return arguments; })() : new global[className]; 80 Object.defineProperty(obj, Symbol.toStringTag, { 81 get: function() { return undefined; } 82 }); 83 assertEquals("[object " + className + "]", 84 Object.prototype.toString.call(obj)); 85} 86 87[ 88 "Arguments", 89 "Array", 90 "Boolean", 91 "Date", 92 "Error", 93 "Function", 94 "Number", 95 "RegExp", 96 "String" 97].forEach(testToStringTag); 98 99function testToStringTagNonString(value) { 100 var obj = {}; 101 obj[Symbol.toStringTag] = value; 102 assertEquals("[object Object]", Object.prototype.toString.call(obj)); 103 104 // With getter 105 obj = {}; 106 Object.defineProperty(obj, Symbol.toStringTag, { 107 get: function() { return value; } 108 }); 109 assertEquals("[object Object]", Object.prototype.toString.call(obj)); 110} 111 112[ 113 null, 114 function() {}, 115 [], 116 {}, 117 /regexp/, 118 42, 119 Symbol("sym"), 120 new Date(), 121 (function() { return arguments; })(), 122 true, 123 new Error("oops"), 124 new String("str") 125].forEach(testToStringTagNonString); 126 127function testObjectToStringPropertyDesc() { 128 var desc = Object.getOwnPropertyDescriptor(Object.prototype, "toString"); 129 assertTrue(desc.writable); 130 assertFalse(desc.enumerable); 131 assertTrue(desc.configurable); 132} 133testObjectToStringPropertyDesc(); 134 135function testObjectToStringOwnNonStringValue() { 136 var obj = Object.defineProperty({}, Symbol.toStringTag, { value: 1 }); 137 assertEquals("[object Object]", ({}).toString.call(obj)); 138} 139testObjectToStringOwnNonStringValue(); 140 141 142// Proxies 143 144function assertTag(tag, obj) { 145 assertEquals("[object " + tag + "]", Object.prototype.toString.call(obj)); 146} 147 148assertTag("Object", new Proxy({}, {})); 149assertTag("Array", new Proxy([], {})); 150assertTag("Function", new Proxy(() => 42, {})); 151assertTag("Foo", new Proxy(() => 42, {get() {return "Foo"}})); 152assertTag("Function", new Proxy(() => 42, {get() {return 666}})); 153 154revocable = Proxy.revocable([], {}); 155revocable.revoke(); 156assertThrows(() => Object.prototype.toString.call(revocable.proxy), TypeError); 157 158handler = {}; 159revocable = Proxy.revocable([], handler); 160handler.get = () => revocable.revoke(); 161assertThrows(() => Object.prototype.toString.call(revocable.proxy), TypeError); 162