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; 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochassertEquals("42,42,42", (42).arrayToLocaleString()); 160