1// Copyright 2008 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28// Flags: --allow-natives-syntax 29 30/** 31 * @fileoverview Test indexing on strings with []. 32 */ 33 34var foo = "Foo"; 35assertEquals("Foo", foo); 36assertEquals("F", foo[0]); 37assertEquals("o", foo[1]); 38assertEquals("o", foo[2]); 39 40// Test string keyed load IC. 41for (var i = 0; i < 10; i++) { 42 assertEquals("F", foo[0]); 43 assertEquals("o", foo[1]); 44 assertEquals("o", foo[2]); 45 assertEquals("F", (foo[0] + "BarBazQuuxFooBarQuux")[0]); 46} 47 48assertEquals("F", foo["0" + ""], "string index"); 49assertEquals("o", foo["1"], "string index"); 50assertEquals("o", foo["2"], "string index"); 51 52assertEquals("undefined", typeof(foo[3]), "out of range"); 53// SpiderMonkey 1.5 fails this next one. So does FF 2.0.6. 54assertEquals("undefined", typeof(foo[-1]), "known failure in SpiderMonkey 1.5"); 55assertEquals("undefined", typeof(foo[-2]), "negative index"); 56 57foo[0] = "f"; 58assertEquals("Foo", foo); 59 60foo[3] = "t"; 61assertEquals("Foo", foo); 62assertEquals("undefined", typeof(foo[3]), "out of range"); 63assertEquals("undefined", typeof(foo[-2]), "negative index"); 64 65var S = new String("foo"); 66assertEquals(Object("foo"), S); 67assertEquals("f", S[0], "string object"); 68assertEquals("f", S["0"], "string object"); 69S[0] = 'bente'; 70assertEquals("f", S[0], "string object"); 71assertEquals("f", S["0"], "string object"); 72S[-2] = 'spider'; 73assertEquals('spider', S[-2]); 74S[3] = 'monkey'; 75assertEquals('monkey', S[3]); 76S['foo'] = 'Fu'; 77assertEquals("Fu", S.foo); 78 79// In FF this is ignored I think. In V8 it puts a property on the String object 80// but you won't ever see it because it is hidden by the 0th character in the 81// string. The net effect is pretty much the same. 82S["0"] = 'bente'; 83assertEquals("f", S[0], "string object"); 84assertEquals("f", S["0"], "string object"); 85 86assertEquals(true, 0 in S, "0 in"); 87assertEquals(false, -1 in S, "-1 in"); 88assertEquals(true, 2 in S, "2 in"); 89assertEquals(true, 3 in S, "3 in"); 90assertEquals(false, 4 in S, "3 in"); 91 92assertEquals(true, "0" in S, '"0" in'); 93assertEquals(false, "-1" in S, '"-1" in'); 94assertEquals(true, "2" in S, '"2" in'); 95assertEquals(true, "3" in S, '"3" in'); 96assertEquals(false, "4" in S, '"3" in'); 97 98assertEquals(true, S.hasOwnProperty(0), "0 hasOwnProperty"); 99assertEquals(false, S.hasOwnProperty(-1), "-1 hasOwnProperty"); 100assertEquals(true, S.hasOwnProperty(2), "2 hasOwnProperty"); 101assertEquals(true, S.hasOwnProperty(3), "3 hasOwnProperty"); 102assertEquals(false, S.hasOwnProperty(4), "3 hasOwnProperty"); 103 104assertEquals(true, S.hasOwnProperty("0"), '"0" hasOwnProperty'); 105assertEquals(false, S.hasOwnProperty("-1"), '"-1" hasOwnProperty'); 106assertEquals(true, S.hasOwnProperty("2"), '"2" hasOwnProperty'); 107assertEquals(true, S.hasOwnProperty("3"), '"3" hasOwnProperty'); 108assertEquals(false, S.hasOwnProperty("4"), '"3" hasOwnProperty'); 109 110assertEquals(true, "foo".hasOwnProperty(0), "foo 0 hasOwnProperty"); 111assertEquals(false, "foo".hasOwnProperty(-1), "foo -1 hasOwnProperty"); 112assertEquals(true, "foo".hasOwnProperty(2), "foo 2 hasOwnProperty"); 113assertEquals(false, "foo".hasOwnProperty(4), "foo 3 hasOwnProperty"); 114 115assertEquals(true, "foo".hasOwnProperty("0"), 'foo "0" hasOwnProperty'); 116assertEquals(false, "foo".hasOwnProperty("-1"), 'foo "-1" hasOwnProperty'); 117assertEquals(true, "foo".hasOwnProperty("2"), 'foo "2" hasOwnProperty'); 118assertEquals(false, "foo".hasOwnProperty("4"), 'foo "3" hasOwnProperty'); 119 120//assertEquals(true, 0 in "foo", "0 in"); 121//assertEquals(false, -1 in "foo", "-1 in"); 122//assertEquals(true, 2 in "foo", "2 in"); 123//assertEquals(false, 3 in "foo", "3 in"); 124// 125//assertEquals(true, "0" in "foo", '"0" in'); 126//assertEquals(false, "-1" in "foo", '"-1" in'); 127//assertEquals(true, "2" in "foo", '"2" in'); 128//assertEquals(false, "3" in "foo", '"3" in'); 129 130delete S[3]; 131assertEquals("undefined", typeof(S[3])); 132assertEquals(false, 3 in S); 133assertEquals(false, "3" in S); 134 135var N = new Number(43); 136assertEquals(Object(43), N); 137N[-2] = "Alpha"; 138assertEquals("Alpha", N[-2]); 139N[0] = "Zappa"; 140assertEquals("Zappa", N[0]); 141assertEquals("Zappa", N["0"]); 142 143var A = ["V", "e", "t", "t", "e", "r"]; 144var A2 = (A[0] = "v"); 145assertEquals('v', A[0]); 146assertEquals('v', A2); 147 148var S = new String("Onkel"); 149var S2 = (S[0] = 'o'); 150assertEquals('O', S[0]); 151assertEquals('o', S2); 152 153var s = "Tante"; 154var s2 = (s[0] = 't'); 155assertEquals('T', s[0]); 156assertEquals('t', s2); 157 158var S2 = (S[-2] = 'o'); 159assertEquals('o', S[-2]); 160assertEquals('o', S2); 161 162var s2 = (s[-2] = 't'); 163assertEquals('undefined', typeof(s[-2])); 164assertEquals('t', s2); 165 166// Make sure enough of the one-char string cache is filled. 167var alpha = ['@']; 168for (var i = 1; i < 128; i++) { 169 var c = String.fromCharCode(i); 170 alpha[i] = c[0]; 171} 172var alphaStr = alpha.join(""); 173 174// Now test chars. 175for (var i = 1; i < 128; i++) { 176 assertEquals(alpha[i], alphaStr[i]); 177 assertEquals(String.fromCharCode(i), alphaStr[i]); 178} 179 180// Test for keyed ic. 181var foo = ['a12', ['a', 2, 'c'], 'a31', 42]; 182var results = [1, 2, 3, NaN]; 183for (var i = 0; i < 200; ++i) { 184 var index = Math.floor(i / 50); 185 var receiver = foo[index]; 186 var expected = results[index]; 187 var actual = +(receiver[1]); 188 assertEquals(expected, actual); 189} 190 191var keys = [0, '1', 2, 3.0, -1, 10]; 192var str = 'abcd', arr = ['a', 'b', 'c', 'd', undefined, undefined]; 193for (var i = 0; i < 300; ++i) { 194 var index = Math.floor(i / 50); 195 var key = keys[index]; 196 var expected = arr[index]; 197 var actual = str[key]; 198 assertEquals(expected, actual); 199} 200 201// Test heap number case. 202var keys = [0, Math.floor(2) * 0.5]; 203var str = 'ab', arr = ['a', 'b']; 204for (var i = 0; i < 100; ++i) { 205 var index = Math.floor(i / 50); 206 var key = keys[index]; 207 var expected = arr[index]; 208 var actual = str[key]; 209 assertEquals(expected, actual); 210} 211 212// Test negative zero case. 213var keys = [0, -0.0]; 214var str = 'ab', arr = ['a', 'a']; 215for (var i = 0; i < 100; ++i) { 216 var index = Math.floor(i / 50); 217 var key = keys[index]; 218 var expected = arr[index]; 219 var actual = str[key]; 220 assertEquals(expected, actual); 221} 222 223// Test "not-an-array-index" case. 224var keys = [0, 0.5]; 225var str = 'ab', arr = ['a', undefined]; 226for (var i = 0; i < 100; ++i) { 227 var index = Math.floor(i / 50); 228 var key = keys[index]; 229 var expected = arr[index]; 230 var actual = str[key]; 231 assertEquals(expected, actual); 232} 233 234// Test out of range case. 235var keys = [0, -1]; 236var str = 'ab', arr = ['a', undefined]; 237for (var i = 0; i < 100; ++i) { 238 var index = Math.floor(i / 50); 239 var key = keys[index]; 240 var expected = arr[index]; 241 var actual = str[key]; 242 assertEquals(expected, actual); 243} 244 245var keys = [0, 10]; 246var str = 'ab', arr = ['a', undefined]; 247for (var i = 0; i < 100; ++i) { 248 var index = Math.floor(i / 50); 249 var key = keys[index]; 250 var expected = arr[index]; 251 var actual = str[key]; 252 assertEquals(expected, actual); 253} 254 255// Test out of range with a heap number case. 256var num = Math.floor(4) * 0.5; 257// TODO(mvstanton): figure out a reliable way to get a heap number every time. 258// assertFalse(!%_IsSmi(num)); 259var keys = [0, num]; 260var str = 'ab', arr = ['a', undefined]; 261for (var i = 0; i < 100; ++i) { 262 var index = Math.floor(i / 50); 263 var key = keys[index]; 264 var expected = arr[index]; 265 var actual = str[key]; 266 assertEquals(expected, actual); 267} 268 269// Test two byte string. 270var str = '\u0427', arr = ['\u0427']; 271for (var i = 0; i < 50; ++i) { 272 var expected = arr[0]; 273 var actual = str[0]; 274 assertEquals(expected, actual); 275} 276