1// Copyright 2014 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
6
7var global = this;
8
9var funs = {
10  Object:   [ Object ],
11  Function: [ Function ],
12  String:   [ String ],
13  Boolean:  [ Boolean ],
14  Number:   [ Number ],
15  Date:     [ Date ],
16  RegExp:   [ RegExp ],
17  Error:    [ Error, TypeError, RangeError, SyntaxError, ReferenceError,
18              EvalError, URIError ]
19}
20for (f in funs) {
21  for (i in funs[f]) {
22    assertEquals("[object " + f + "]",
23                 Array.prototype.toString.call(new funs[f][i]),
24                 funs[f][i]);
25    assertEquals("[object Function]",
26                 Array.prototype.toString.call(funs[f][i]),
27                 funs[f][i]);
28  }
29}
30
31
32function testToStringTag(className) {
33  // Using builtin toStringTags
34  var obj = {};
35  obj[Symbol.toStringTag] = className;
36  assertEquals("[object " + className + "]",
37               Array.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    Array.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               Array.prototype.toString.call(obj));
55
56  // Custom, non-builtin toStringTags
57  obj = {};
58  obj[Symbol.toStringTag] = "X" + className;
59  assertEquals("[object X" + className + "]",
60               Array.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               Array.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               Array.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               Array.prototype.toString.call(obj));
85}
86
87
88[
89  "Arguments",
90  "Boolean",
91  "Date",
92  "Error",
93  "Function",
94  "Number",
95  "RegExp",
96  "String"
97].forEach(testToStringTag);
98
99
100function testToStringTagNonString(value) {
101  var obj = {};
102  obj[Symbol.toStringTag] = value;
103  assertEquals("[object Object]", Array.prototype.toString.call(obj));
104
105  // With getter
106  obj = {};
107  Object.defineProperty(obj, Symbol.toStringTag, {
108    get: function() { return value; }
109  });
110  assertEquals("[object Object]", Array.prototype.toString.call(obj));
111}
112
113
114[
115  null,
116  function() {},
117  [],
118  {},
119  /regexp/,
120  42,
121  Symbol("sym"),
122  new Date(),
123  (function() { return arguments; })(),
124  true,
125  new Error("oops"),
126  new String("str")
127].forEach(testToStringTagNonString);
128
129
130function testArrayToStringPropertyDesc() {
131  var desc = Object.getOwnPropertyDescriptor(Object.prototype, "toString");
132  assertTrue(desc.writable);
133  assertFalse(desc.enumerable);
134  assertTrue(desc.configurable);
135}
136testArrayToStringPropertyDesc();
137
138
139function testArrayToStringOwnNonStringValue() {
140  var obj = Object.defineProperty({}, Symbol.toStringTag, { value: 1 });
141  assertEquals("[object Object]", ([]).toString.call(obj));
142}
143testArrayToStringOwnNonStringValue();
144
145
146function testArrayToStringBasic() {
147  assertEquals("1,2,3", [1,2,3].toString());
148  assertEquals(",,3", [,,3].toString());
149}
150testArrayToStringBasic();
151
152
153function testArrayToStringObjectWithCallableJoin() {
154  var obj = { join: function() { return "CallableJoin"; } };
155  assertEquals("CallableJoin", Array.prototype.toString.call(obj));
156}
157testArrayToStringObjectWithCallableJoin();
158