1c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Copyright 2011 the V8 project authors. All rights reserved.
2c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Redistribution and use in source and binary forms, with or without
3c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// modification, are permitted provided that the following conditions are
4c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// met:
5c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com//
6c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com//     * Redistributions of source code must retain the above copyright
7c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com//       notice, this list of conditions and the following disclaimer.
8c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com//     * Redistributions in binary form must reproduce the above
9c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com//       copyright notice, this list of conditions and the following
10c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com//       disclaimer in the documentation and/or other materials provided
11c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com//       with the distribution.
12c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com//     * Neither the name of Google Inc. nor the names of its
13c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com//       contributors may be used to endorse or promote products derived
14c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com//       from this software without specific prior written permission.
15c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com//
16c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
28c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Array's toString should call the object's own join method, if one exists and
29c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// is callable. Otherwise, just use the original Object.toString function.
30c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
31c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvar success = "[test success]";
32c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvar expectedThis;
33c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comfunction testJoin() {
34c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  assertEquals(0, arguments.length);
35c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  assertSame(expectedThis, this);
36c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  return success;
37c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
38c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
39c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
40c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// On an Array object.
41c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
42c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Default case.
43c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvar a1 = [1, 2, 3];
44c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comassertEquals(a1.join(), a1.toString());
45c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
46c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Non-standard "join" function is called correctly.
47c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvar a2 = [1, 2, 3];
48c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.coma2.join = testJoin;
49c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comexpectedThis = a2;
50c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comassertEquals(success, a2.toString());
51c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
52c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Non-callable join function is ignored and Object.prototype.toString is
53c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// used instead.
54c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvar a3 = [1, 2, 3];
55c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.coma3.join = "not callable";
56c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comassertEquals("[object Array]", a3.toString());
57c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
58c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Non-existing join function is treated same as non-callable.
59c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvar a4 = [1, 2, 3];
60c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.coma4.__proto__ = { toString: Array.prototype.toString };
61c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// No join on Array.
62c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comassertEquals("[object Array]", a4.toString());
63c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
64c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
65c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// On a non-Array object.
66c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
67c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Default looks-like-an-array case.
68c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvar o1 = {length: 3, 0: 1, 1: 2, 2: 3,
69c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          toString: Array.prototype.toString,
70c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          join: Array.prototype.join};
71c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comassertEquals(o1.join(), o1.toString());
72c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
73c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
74c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Non-standard join is called correctly.
75c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Check that we don't read, e.g., length before calling join.
76c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvar o2 = {toString : Array.prototype.toString,
77c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          join: testJoin,
78c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          get length() { assertUnreachable(); },
79c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          get 0() { assertUnreachable(); }};
80c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comexpectedThis = o2;
81c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comassertEquals(success, o2.toString());
82c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
83c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Non-standard join is called even if it looks like an array.
84c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvar o3 = {length: 3, 0: 1, 1: 2, 2: 3,
85c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          toString: Array.prototype.toString,
86c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          join: testJoin};
87c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comexpectedThis = o3;
88c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comassertEquals(success, o3.toString());
89c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
90c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Non-callable join works same as for Array.
91c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvar o4 = {length: 3, 0: 1, 1: 2, 2: 3,
92c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          toString: Array.prototype.toString,
93c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          join: "not callable"};
94c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comassertEquals("[object Object]", o4.toString());
95c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
96c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
97c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Non-existing join works same as for Array.
98c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvar o5 = {length: 3, 0: 1, 1: 2, 2: 3,
99c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          toString: Array.prototype.toString
100c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          /* no join */};
101c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comassertEquals("[object Object]", o5.toString());
102c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
103c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
104c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Test that ToObject is called before getting "join", so the instance
105c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// that "join" is read from is the same one passed as receiver later.
106c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvar called_before = false;
107c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comexpectedThis = null;
108c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comObject.defineProperty(Number.prototype, "join", {get: function() {
109c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com            assertFalse(called_before);
110c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com            called_before = true;
111c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com            expectedThis = this;
112c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com            return testJoin;
113c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        }});
114c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comNumber.prototype.arrayToString = Array.prototype.toString;
115c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comassertEquals(success, (42).arrayToString());
116c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
117c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// ----------------------------------------------------------
118c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Testing Array.prototype.toLocaleString
119c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
120c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Ensure that it never uses Array.prototype.toString for anything.
121c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comArray.prototype.toString = function() { assertUnreachable(); };
122c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
123c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Default case.
124c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvar la1 = [1, [2, 3], 4];
125c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comassertEquals("1,2,3,4", la1.toLocaleString());
126c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
127c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Used on a string (which looks like an array of characters).
128c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comString.prototype.toLocaleString = Array.prototype.toLocaleString;
129c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comassertEquals("1,2,3,4", "1234".toLocaleString());
130c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
131c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// If toLocaleString of element is not callable, throw a TypeError.
132c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvar la2 = [1, {toLocaleString: "not callable"}, 3];
133c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comassertThrows(function() { la2.toLocaleString(); }, TypeError);
134c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
135c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// If toLocaleString of element is callable, call it.
136c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvar la3 = [1, {toLocaleString: function() { return "XX";}}, 3];
137c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comassertEquals("1,XX,3", la3.toLocaleString());
138c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
139c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Omitted elements, as well as undefined and null, become empty string.
140c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvar la4 = [1, null, 3, undefined, 5,, 7];
141c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comassertEquals("1,,3,,5,,7", la4.toLocaleString());
142c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
143c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
144c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// ToObject is called first and the same object is being used for the
145c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// rest of the operations.
146c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comObject.defineProperty(Number.prototype, "length", {
147c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    get: function() {
148c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      exptectedThis = this;
149c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      return 3;
150c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }});
151c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comfor (var i = 0; i < 3; i++) {
152c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Object.defineProperty(Number.prototype, i, {
153c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      get: function() {
154c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        assertEquals(expectedThis, this);
155c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        return +this;
156c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }});
157c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
158c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comNumber.prototype.arrayToLocaleString = Array.prototype.toLocaleString;
159f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgassertEquals("42,42,42", (42).arrayToLocaleString());
160