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/**
29 * @fileoverview Test indexing on strings with [].
30 */
31
32var foo = "Foo";
33assertEquals("Foo", foo);
34assertEquals("F", foo[0]);
35assertEquals("o", foo[1]);
36assertEquals("o", foo[2]);
37
38// Test string keyed load IC.
39for (var i = 0; i < 10; i++) {
40  assertEquals("F", foo[0]);
41  assertEquals("o", foo[1]);
42  assertEquals("o", foo[2]);
43  assertEquals("F", (foo[0] + "BarBazQuuxFooBarQuux")[0]);
44}
45
46assertEquals("F", foo["0" + ""], "string index");
47assertEquals("o", foo["1"], "string index");
48assertEquals("o", foo["2"], "string index");
49
50assertEquals("undefined", typeof(foo[3]), "out of range");
51// SpiderMonkey 1.5 fails this next one.  So does FF 2.0.6.
52assertEquals("undefined", typeof(foo[-1]), "known failure in SpiderMonkey 1.5");
53assertEquals("undefined", typeof(foo[-2]), "negative index");
54
55foo[0] = "f";
56assertEquals("Foo", foo);
57
58foo[3] = "t";
59assertEquals("Foo", foo);
60assertEquals("undefined", typeof(foo[3]), "out of range");
61assertEquals("undefined", typeof(foo[-2]), "negative index");
62
63var S = new String("foo");
64assertEquals(Object("foo"), S);
65assertEquals("f", S[0], "string object");
66assertEquals("f", S["0"], "string object");
67S[0] = 'bente';
68assertEquals("f", S[0], "string object");
69assertEquals("f", S["0"], "string object");
70S[-2] = 'spider';
71assertEquals('spider', S[-2]);
72S[3] = 'monkey';
73assertEquals('monkey', S[3]);
74S['foo'] = 'Fu';
75assertEquals("Fu", S.foo);
76
77// In FF this is ignored I think.  In V8 it puts a property on the String object
78// but you won't ever see it because it is hidden by the 0th character in the
79// string.  The net effect is pretty much the same.
80S["0"] = 'bente';
81assertEquals("f", S[0], "string object");
82assertEquals("f", S["0"], "string object");
83
84assertEquals(true, 0 in S, "0 in");
85assertEquals(false, -1 in S, "-1 in");
86assertEquals(true, 2 in S, "2 in");
87assertEquals(true, 3 in S, "3 in");
88assertEquals(false, 4 in S, "3 in");
89
90assertEquals(true, "0" in S, '"0" in');
91assertEquals(false, "-1" in S, '"-1" in');
92assertEquals(true, "2" in S, '"2" in');
93assertEquals(true, "3" in S, '"3" in');
94assertEquals(false, "4" in S, '"3" in');
95
96assertEquals(true, S.hasOwnProperty(0), "0 hasOwnProperty");
97assertEquals(false, S.hasOwnProperty(-1), "-1 hasOwnProperty");
98assertEquals(true, S.hasOwnProperty(2), "2 hasOwnProperty");
99assertEquals(true, S.hasOwnProperty(3), "3 hasOwnProperty");
100assertEquals(false, S.hasOwnProperty(4), "3 hasOwnProperty");
101
102assertEquals(true, S.hasOwnProperty("0"), '"0" hasOwnProperty');
103assertEquals(false, S.hasOwnProperty("-1"), '"-1" hasOwnProperty');
104assertEquals(true, S.hasOwnProperty("2"), '"2" hasOwnProperty');
105assertEquals(true, S.hasOwnProperty("3"), '"3" hasOwnProperty');
106assertEquals(false, S.hasOwnProperty("4"), '"3" hasOwnProperty');
107
108assertEquals(true, "foo".hasOwnProperty(0), "foo 0 hasOwnProperty");
109assertEquals(false, "foo".hasOwnProperty(-1), "foo -1 hasOwnProperty");
110assertEquals(true, "foo".hasOwnProperty(2), "foo 2 hasOwnProperty");
111assertEquals(false, "foo".hasOwnProperty(4), "foo 3 hasOwnProperty");
112
113assertEquals(true, "foo".hasOwnProperty("0"), 'foo "0" hasOwnProperty');
114assertEquals(false, "foo".hasOwnProperty("-1"), 'foo "-1" hasOwnProperty');
115assertEquals(true, "foo".hasOwnProperty("2"), 'foo "2" hasOwnProperty');
116assertEquals(false, "foo".hasOwnProperty("4"), 'foo "3" hasOwnProperty');
117
118//assertEquals(true, 0 in "foo", "0 in");
119//assertEquals(false, -1 in "foo", "-1 in");
120//assertEquals(true, 2 in "foo", "2 in");
121//assertEquals(false, 3 in "foo", "3 in");
122//
123//assertEquals(true, "0" in "foo", '"0" in');
124//assertEquals(false, "-1" in "foo", '"-1" in');
125//assertEquals(true, "2" in "foo", '"2" in');
126//assertEquals(false, "3" in "foo", '"3" in');
127
128delete S[3];
129assertEquals("undefined", typeof(S[3]));
130assertEquals(false, 3 in S);
131assertEquals(false, "3" in S);
132
133var N = new Number(43);
134assertEquals(Object(43), N);
135N[-2] = "Alpha";
136assertEquals("Alpha", N[-2]);
137N[0] = "Zappa";
138assertEquals("Zappa", N[0]);
139assertEquals("Zappa", N["0"]);
140
141var A = ["V", "e", "t", "t", "e", "r"];
142var A2 = (A[0] = "v");
143assertEquals('v', A[0]);
144assertEquals('v', A2);
145
146var S = new String("Onkel");
147var S2 = (S[0] = 'o');
148assertEquals('O', S[0]);
149assertEquals('o', S2);
150
151var s = "Tante";
152var s2 = (s[0] = 't');
153assertEquals('T', s[0]);
154assertEquals('t', s2);
155
156var S2 = (S[-2] = 'o');
157assertEquals('o', S[-2]);
158assertEquals('o', S2);
159
160var s2 = (s[-2] = 't');
161assertEquals('undefined', typeof(s[-2]));
162assertEquals('t', s2);
163
164// Make sure enough of the one-char string cache is filled.
165var alpha = ['@'];
166for (var i = 1; i < 128; i++) {
167  var c = String.fromCharCode(i);
168  alpha[i] = c[0];
169}
170var alphaStr = alpha.join("");
171
172// Now test chars.
173for (var i = 1; i < 128; i++) {
174  assertEquals(alpha[i], alphaStr[i]);
175  assertEquals(String.fromCharCode(i), alphaStr[i]);
176}
177
178// Test for keyed ic.
179var foo = ['a12', ['a', 2, 'c'], 'a31', 42];
180var results = [1, 2, 3, NaN];
181for (var i = 0; i < 200; ++i) {
182  var index = Math.floor(i / 50);
183  var receiver = foo[index];
184  var expected = results[index];
185  var actual = +(receiver[1]);
186  assertEquals(expected, actual);
187}
188
189var keys = [0, '1', 2, 3.0, -1, 10];
190var str = 'abcd', arr = ['a', 'b', 'c', 'd', undefined, undefined];
191for (var i = 0; i < 300; ++i) {
192  var index = Math.floor(i / 50);
193  var key = keys[index];
194  var expected = arr[index];
195  var actual = str[key];
196  assertEquals(expected, actual);
197}
198
199// Test heap number case.
200var keys = [0, Math.floor(2) * 0.5];
201var str = 'ab', arr = ['a', 'b'];
202for (var i = 0; i < 100; ++i) {
203  var index = Math.floor(i / 50);
204  var key = keys[index];
205  var expected = arr[index];
206  var actual = str[key];
207  assertEquals(expected, actual);
208}
209
210// Test negative zero case.
211var keys = [0, -0.0];
212var str = 'ab', arr = ['a', 'a'];
213for (var i = 0; i < 100; ++i) {
214  var index = Math.floor(i / 50);
215  var key = keys[index];
216  var expected = arr[index];
217  var actual = str[key];
218  assertEquals(expected, actual);
219}
220
221// Test "not-an-array-index" case.
222var keys = [0, 0.5];
223var str = 'ab', arr = ['a', undefined];
224for (var i = 0; i < 100; ++i) {
225  var index = Math.floor(i / 50);
226  var key = keys[index];
227  var expected = arr[index];
228  var actual = str[key];
229  assertEquals(expected, actual);
230}
231
232// Test out of range case.
233var keys = [0, -1];
234var str = 'ab', arr = ['a', undefined];
235for (var i = 0; i < 100; ++i) {
236  var index = Math.floor(i / 50);
237  var key = keys[index];
238  var expected = arr[index];
239  var actual = str[key];
240  assertEquals(expected, actual);
241}
242
243var keys = [0, 10];
244var str = 'ab', arr = ['a', undefined];
245for (var i = 0; i < 100; ++i) {
246  var index = Math.floor(i / 50);
247  var key = keys[index];
248  var expected = arr[index];
249  var actual = str[key];
250  assertEquals(expected, actual);
251}
252
253// Test two byte string.
254var str = '\u0427', arr = ['\u0427'];
255for (var i = 0; i < 50; ++i) {
256  var expected = arr[0];
257  var actual = str[0];
258  assertEquals(expected, actual);
259}
260