1// Copyright 2013 the V8 project authors. All rights reserved. 2// Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions 6// are met: 7// 1. Redistributions of source code must retain the above copyright 8// notice, this list of conditions and the following disclaimer. 9// 2. Redistributions in binary form must reproduce the above copyright 10// notice, this list of conditions and the following disclaimer in the 11// documentation and/or other materials provided with the distribution. 12// 13// THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16// DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 24description( 25"Test some array functions on non-array objects." 26); 27 28function properties(object, extraName1, extraName2, extraName3) 29{ 30 var string = ""; 31 32 // destructive, lists properties 33 var names = []; 34 var enumerables = {}; 35 for (propertyName in object) { 36 names.push(propertyName); 37 enumerables[propertyName] = 1; 38 } 39 names.push("length"); 40 names.push(extraName1); 41 names.push(extraName2); 42 names.push(extraName3); 43 names.sort(); 44 45 var propertyStrings = []; 46 for (i = 0; i < names.length; ++i) { 47 var name = names[i]; 48 if (name == names[i - 1]) 49 continue; 50 if (!(name in object)) 51 continue; 52 53 var propertyString = name + ":" + object[name]; 54 55 var flags = []; 56 if (!object.hasOwnProperty(name)) 57 flags.push("FromPrototype"); 58 if (!enumerables[name]) 59 flags.push("DontEnum"); 60 if (name != "length") { 61 try { 62 object[name] = "ReadOnlyTestValue"; 63 } catch (e) { 64 } 65 if (object[name] != "ReadOnlyTestValue") 66 flags.push("ReadOnly"); 67 } 68 delete object[name]; 69 if (object.hasOwnProperty(name)) 70 flags.push("DontDelete"); 71 72 flags.sort(); 73 74 if (flags.length) 75 propertyString += "(" + flags.join(", ") + ")"; 76 77 propertyStrings.push(propertyString); 78 } 79 return propertyStrings.join(", "); 80} 81 82var x; 83 84var oneItemPrototype = { length:1, 0:'a' }; 85function OneItemConstructor() 86{ 87} 88OneItemConstructor.prototype = oneItemPrototype; 89 90var twoItemPrototype = { length:2, 0:'b', 1:'a' }; 91function TwoItemConstructor() 92{ 93} 94TwoItemConstructor.prototype = twoItemPrototype; 95 96shouldBe("properties(['b', 'a'])", "'0:b, 1:a, length:2(DontDelete, DontEnum)'"); 97shouldBe("properties({ length:2, 0:'b', 1:'a' })", "'0:b, 1:a, length:2'"); 98 99shouldBe("properties(new OneItemConstructor)", "'0:a(FromPrototype), length:1(FromPrototype)'"); 100shouldBe("properties(new TwoItemConstructor)", "'0:b(FromPrototype), 1:a(FromPrototype), length:2(FromPrototype)'"); 101 102shouldBe("Array.prototype.toString.call({})", '"' + ({}).toString() + '"'); 103shouldBe("Array.prototype.toString.call(new Date)", '"' + Object.prototype.toString.call(new Date) + '"'); 104shouldBe("Array.prototype.toString.call({sort: function() { return 'sort' }})", '"' + Object.prototype.toString.call({}) + '"'); 105shouldBe("Array.prototype.toString.call({join: function() { return 'join' }})", '"join"'); 106shouldBe("Array.prototype.toString.call({__proto__: Array.prototype, 0: 'a', 1: 'b', 2: 'c', length: 3})", '"a,b,c"'); 107shouldBe("({__proto__: Array.prototype, 0: 'a', 1: 'b', 2: 'c', length: 3}).toString()", '"a,b,c"'); 108shouldBe("Array.prototype.toString.call({__proto__: Array.prototype, 0: 'a', 1: 'b', 2: 'c', length: 3, join: function() { return 'join' }})", '"join"'); 109shouldBe("({__proto__: Array.prototype, 0: 'a', 1: 'b', 2: 'c', length: 3, join: function() { return 'join' }}).toString()", '"join"'); 110Number.prototype.join = function() { return "Number.prototype.join:" + this; } 111shouldBe("Array.prototype.toString.call(42)", '"Number.prototype.join:42"'); 112var arrayJoin = Array.prototype.join; 113Array.prototype.join = function() { return 'array-join' }; 114shouldBe("[0, 1, 2].toString()", '"array-join"'); 115Array.prototype.join = arrayJoin; 116 117shouldThrow("Array.prototype.toLocaleString.call({})"); 118 119shouldBe("Array.prototype.concat.call(x = { length:2, 0:'b', 1:'a' })", "[x]"); 120 121shouldBe("Array.prototype.join.call({})", "''"); 122shouldBe("Array.prototype.join.call(['b', 'a'])", "'b,a'"); 123shouldBe("Array.prototype.join.call({ length:2, 0:'b', 1:'a' })", "'b,a'"); 124shouldBe("Array.prototype.join.call(new TwoItemConstructor)", "'b,a'"); 125 126shouldBe("Array.prototype.pop.call({})", "undefined"); 127shouldBe("Array.prototype.pop.call({ length:2, 0:'b', 1:'a' })", "'a'"); 128shouldBe("Array.prototype.pop.call({ length:2, 0:'b', 1:'a' })", "'a'"); 129shouldBe("Array.prototype.pop.call(new TwoItemConstructor)", "'a'"); 130shouldBe("Array.prototype.pop.call(x = {}); properties(x)", "'length:0'"); 131shouldBe("Array.prototype.pop.call(x = ['b', 'a']); properties(x)", "'0:b, length:1(DontDelete, DontEnum)'"); 132shouldBe("Array.prototype.pop.call(x = { length:2, 0:'b', 1:'a' }); properties(x)", "'0:b, length:1'"); 133shouldBe("Array.prototype.pop.call(x = new TwoItemConstructor); properties(x)", "'0:b(FromPrototype), 1:a(FromPrototype), length:1'"); 134 135shouldBe("Array.prototype.push.call({})", "0"); 136shouldBe("Array.prototype.push.call(['b', 'a'])", "2"); 137shouldBe("Array.prototype.push.call({ length:2, 0:'b', 1:'a' })", "2"); 138shouldBe("Array.prototype.push.call(new TwoItemConstructor)", "2"); 139shouldBe("Array.prototype.push.call(x = {}); properties(x)", "'length:0'"); 140shouldBe("Array.prototype.push.call(x = ['b', 'a']); properties(x)", "'0:b, 1:a, length:2(DontDelete, DontEnum)'"); 141shouldBe("Array.prototype.push.call(x = { length:2, 0:'b', 1:'a' }); properties(x)", "'0:b, 1:a, length:2'"); 142shouldBe("Array.prototype.push.call(x = new TwoItemConstructor); properties(x)", "'0:b(FromPrototype), 1:a(FromPrototype), length:2'"); 143shouldBe("Array.prototype.push.call({}, 'c')", "1"); 144shouldBe("Array.prototype.push.call(['b', 'a'], 'c')", "3"); 145shouldBe("Array.prototype.push.call({ length:2, 0:'b', 1:'a' }, 'c')", "3"); 146shouldBe("Array.prototype.push.call(new TwoItemConstructor, 'c')", "3"); 147shouldBe("Array.prototype.push.call(x = {}, 'c'); properties(x)", "'0:c, length:1'"); 148shouldBe("Array.prototype.push.call(x = ['b', 'a'], 'c'); properties(x)", "'0:b, 1:a, 2:c, length:3(DontDelete, DontEnum)'"); 149shouldBe("Array.prototype.push.call(x = { length:2, 0:'b', 1:'a' }, 'c'); properties(x)", "'0:b, 1:a, 2:c, length:3'"); 150shouldBe("Array.prototype.push.call(x = new TwoItemConstructor, 'c'); properties(x)", "'0:b(FromPrototype), 1:a(FromPrototype), 2:c, length:3'"); 151 152shouldBe("properties(Array.prototype.reverse.call({}))", "''"); 153shouldBe("properties(Array.prototype.reverse.call(['b', 'a']))", "'0:a, 1:b, length:2(DontDelete, DontEnum)'"); 154shouldBe("properties(Array.prototype.reverse.call({ length:2, 0:'b', 1:'a' }))", "'0:a, 1:b, length:2'"); 155shouldBe("properties(Array.prototype.reverse.call(new OneItemConstructor))", "'0:a(FromPrototype), length:1(FromPrototype)'"); 156shouldBe("properties(Array.prototype.reverse.call(new TwoItemConstructor))", "'0:a, 1:b, length:2(FromPrototype)'"); 157 158shouldBe("Array.prototype.shift.call({})", "undefined"); 159shouldBe("Array.prototype.shift.call(['b', 'a'])", "'b'"); 160shouldBe("Array.prototype.shift.call({ length:2, 0:'b', 1:'a' })", "'b'"); 161shouldBe("Array.prototype.shift.call(new TwoItemConstructor)", "'b'"); 162shouldBe("Array.prototype.shift.call(x = {}); properties(x)", "'length:0'"); 163shouldBe("Array.prototype.shift.call(x = ['b', 'a']); properties(x)", "'0:a, length:1(DontDelete, DontEnum)'"); 164shouldBe("Array.prototype.shift.call(x = { length:2, 0:'b', 1:'a' }); properties(x)", "'0:a, length:1'"); 165shouldBe("Array.prototype.shift.call(x = new TwoItemConstructor); properties(x)", "'0:a, 1:a(FromPrototype), length:1'"); 166 167shouldBe("Array.prototype.slice.call({}, 0, 1)", "[]"); 168shouldBe("Array.prototype.slice.call(['b', 'a'], 0, 1)", "['b']"); 169shouldBe("Array.prototype.slice.call({ length:2, 0:'b', 1:'a' }, 0, 1)", "['b']"); 170shouldBe("Array.prototype.slice.call(new TwoItemConstructor, 0, 1)", "['b']"); 171 172shouldBe("properties(Array.prototype.sort.call({}))", "''"); 173shouldBe("properties(Array.prototype.sort.call(['b', 'a']))", "'0:a, 1:b, length:2(DontDelete, DontEnum)'"); 174shouldBe("properties(Array.prototype.sort.call({ length:2, 0:'b', 1:'a' }))", "'0:a, 1:b, length:2'"); 175shouldBe("properties(Array.prototype.sort.call(new OneItemConstructor))", "'0:a(FromPrototype), length:1(FromPrototype)'"); 176shouldBe("properties(Array.prototype.sort.call(new TwoItemConstructor))", "'0:a, 1:b, length:2(FromPrototype)'"); 177 178shouldBe("Array.prototype.splice.call({}, 0, 1)", "[]"); 179shouldBe("Array.prototype.splice.call(['b', 'a'], 0, 1)", "['b']"); 180shouldBe("Array.prototype.splice.call({ length:2, 0:'b', 1:'a' }, 0, 1)", "['b']"); 181shouldBe("Array.prototype.splice.call(new TwoItemConstructor, 0, 1)", "['b']"); 182shouldBe("Array.prototype.splice.call(x = {}, 0, 1); properties(x)", "'length:0'"); 183shouldBe("Array.prototype.splice.call(x = ['b', 'a'], 0, 1); properties(x)", "'0:a, length:1(DontDelete, DontEnum)'"); 184shouldBe("Array.prototype.splice.call(x = { length:2, 0:'b', 1:'a' }, 0, 1); properties(x)", "'0:a, length:1'"); 185shouldBe("Array.prototype.splice.call(x = new TwoItemConstructor, 0, 1); properties(x)", "'0:a, 1:a(FromPrototype), length:1'"); 186 187shouldBe("Array.prototype.unshift.call({})", "0"); 188shouldBe("Array.prototype.unshift.call(['b', 'a'])", "2"); 189shouldBe("Array.prototype.unshift.call({ length:2, 0:'b', 1:'a' })", "2"); 190shouldBe("Array.prototype.unshift.call(new TwoItemConstructor)", "2"); 191shouldBe("Array.prototype.unshift.call(x = {}); properties(x)", "'length:0'"); 192shouldBe("Array.prototype.unshift.call(x = ['b', 'a']); properties(x)", "'0:b, 1:a, length:2(DontDelete, DontEnum)'"); 193shouldBe("Array.prototype.unshift.call(x = { length:2, 0:'b', 1:'a' }); properties(x)", "'0:b, 1:a, length:2'"); 194shouldBe("Array.prototype.unshift.call(x = new TwoItemConstructor); properties(x)", "'0:b(FromPrototype), 1:a(FromPrototype), length:2'"); 195shouldBe("Array.prototype.unshift.call({}, 'c')", "1"); 196shouldBe("Array.prototype.unshift.call(['b', 'a'], 'c')", "3"); 197shouldBe("Array.prototype.unshift.call({ length:2, 0:'b', 1:'a' }, 'c')", "3"); 198shouldBe("Array.prototype.unshift.call(new TwoItemConstructor, 'c')", "3"); 199shouldBe("Array.prototype.unshift.call(x = {}, 'c'); properties(x)", "'0:c, length:1'"); 200shouldBe("Array.prototype.unshift.call(x = ['b', 'a'], 'c'); properties(x)", "'0:c, 1:b, 2:a, length:3(DontDelete, DontEnum)'"); 201shouldBe("Array.prototype.unshift.call(x = { length:2, 0:'b', 1:'a' }, 'c'); properties(x)", "'0:c, 1:b, 2:a, length:3'"); 202shouldBe("Array.prototype.unshift.call(x = new TwoItemConstructor, 'c'); properties(x)", "'0:c, 1:b, 2:a, length:3'"); 203 204// FIXME: Add tests for every, forEach, some, indexOf, lastIndexOf, filter, and map 205