13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
23ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Redistribution and use in source and binary forms, with or without
33ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// modification, are permitted provided that the following conditions are
43ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// met:
53ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
63ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Redistributions of source code must retain the above copyright
73ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       notice, this list of conditions and the following disclaimer.
83ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Redistributions in binary form must reproduce the above
93ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       copyright notice, this list of conditions and the following
103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       disclaimer in the documentation and/or other materials provided
113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       with the distribution.
123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Neither the name of Google Inc. nor the names of its
133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       contributors may be used to endorse or promote products derived
143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       from this software without specific prior written permission.
153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Array's toString should call the object's own join method, if one exists and
293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// is callable. Otherwise, just use the original Object.toString function.
303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar success = "[test success]";
323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar expectedThis;
333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochfunction testJoin() {
343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  assertEquals(0, arguments.length);
353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  assertSame(expectedThis, this);
363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return success;
373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// On an Array object.
413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Default case.
433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar a1 = [1, 2, 3];
443ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochassertEquals(a1.join(), a1.toString());
453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Non-standard "join" function is called correctly.
473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar a2 = [1, 2, 3];
483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdocha2.join = testJoin;
493ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochexpectedThis = a2;
503ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochassertEquals(success, a2.toString());
513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Non-callable join function is ignored and Object.prototype.toString is
533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// used instead.
543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar a3 = [1, 2, 3];
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdocha3.join = "not callable";
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochassertEquals("[object Array]", a3.toString());
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Non-existing join function is treated same as non-callable.
593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar a4 = [1, 2, 3];
603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdocha4.__proto__ = { toString: Array.prototype.toString };
613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// No join on Array.
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochassertEquals("[object Array]", a4.toString());
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// On a non-Array object.
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Default looks-like-an-array case.
683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar o1 = {length: 3, 0: 1, 1: 2, 2: 3,
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          toString: Array.prototype.toString,
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          join: Array.prototype.join};
713ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochassertEquals(o1.join(), o1.toString());
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Non-standard join is called correctly.
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Check that we don't read, e.g., length before calling join.
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar o2 = {toString : Array.prototype.toString,
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          join: testJoin,
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          get length() { assertUnreachable(); },
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          get 0() { assertUnreachable(); }};
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochexpectedThis = o2;
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochassertEquals(success, o2.toString());
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Non-standard join is called even if it looks like an array.
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar o3 = {length: 3, 0: 1, 1: 2, 2: 3,
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          toString: Array.prototype.toString,
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          join: testJoin};
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochexpectedThis = o3;
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochassertEquals(success, o3.toString());
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Non-callable join works same as for Array.
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar o4 = {length: 3, 0: 1, 1: 2, 2: 3,
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          toString: Array.prototype.toString,
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          join: "not callable"};
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochassertEquals("[object Object]", o4.toString());
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Non-existing join works same as for Array.
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar o5 = {length: 3, 0: 1, 1: 2, 2: 3,
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          toString: Array.prototype.toString
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          /* no join */};
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochassertEquals("[object Object]", o5.toString());
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Test that ToObject is called before getting "join", so the instance
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// that "join" is read from is the same one passed as receiver later.
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar called_before = false;
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochexpectedThis = null;
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochObject.defineProperty(Number.prototype, "join", {get: function() {
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            assertFalse(called_before);
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            called_before = true;
1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            expectedThis = this;
1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            return testJoin;
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }});
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochNumber.prototype.arrayToString = Array.prototype.toString;
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochassertEquals(success, (42).arrayToString());
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// ----------------------------------------------------------
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Testing Array.prototype.toLocaleString
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Ensure that it never uses Array.prototype.toString for anything.
1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochArray.prototype.toString = function() { assertUnreachable(); };
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Default case.
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar la1 = [1, [2, 3], 4];
1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochassertEquals("1,2,3,4", la1.toLocaleString());
1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Used on a string (which looks like an array of characters).
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochString.prototype.toLocaleString = Array.prototype.toLocaleString;
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochassertEquals("1,2,3,4", "1234".toLocaleString());
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// If toLocaleString of element is not callable, throw a TypeError.
1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar la2 = [1, {toLocaleString: "not callable"}, 3];
1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochassertThrows(function() { la2.toLocaleString(); }, TypeError);
1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// If toLocaleString of element is callable, call it.
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar la3 = [1, {toLocaleString: function() { return "XX";}}, 3];
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochassertEquals("1,XX,3", la3.toLocaleString());
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Omitted elements, as well as undefined and null, become empty string.
1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar la4 = [1, null, 3, undefined, 5,, 7];
1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochassertEquals("1,,3,,5,,7", la4.toLocaleString());
1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// ToObject is called first and the same object is being used for the
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// rest of the operations.
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochObject.defineProperty(Number.prototype, "length", {
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    get: function() {
1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      exptectedThis = this;
1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return 3;
1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }});
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochfor (var i = 0; i < 3; i++) {
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Object.defineProperty(Number.prototype, i, {
1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      get: function() {
1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        assertEquals(expectedThis, this);
1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return +this;
1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }});
1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochNumber.prototype.arrayToLocaleString = Array.prototype.toLocaleString;
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochassertEquals("42,42,42", (42).arrayToLocaleString());