blob: 5ce4e89473b52ae3826943c0515e9119e2694cc0 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// 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
28var s = "test";
29
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010030function getTwoByteString() { return "\u1234t"; }
31function getCons() { return "testtesttesttest" + getTwoByteString() }
Steve Blocka7e24c12009-10-30 11:49:00 +000032
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010033var slowIndex1 = { valueOf: function() { return 1; } };
34var slowIndex2 = { toString: function() { return "2"; } };
35var slowIndexOutOfRange = { valueOf: function() { return -1; } };
36
37function basicTest(s, len) {
38 assertEquals("t", s().charAt());
39 assertEquals("t", s().charAt("string"));
40 assertEquals("t", s().charAt(null));
41 assertEquals("t", s().charAt(void 0));
42 assertEquals("t", s().charAt(false));
43 assertEquals("e", s().charAt(true));
44 assertEquals("", s().charAt(-1));
45 assertEquals("", s().charAt(len));
46 assertEquals("", s().charAt(slowIndexOutOfRange));
47 assertEquals("", s().charAt(1/0));
48 assertEquals("", s().charAt(-1/0));
49 assertEquals("t", s().charAt(0));
50 assertEquals("t", s().charAt(-0.0));
51 assertEquals("t", s().charAt(-0.1));
52 assertEquals("t", s().charAt(0.4));
53 assertEquals("e", s().charAt(slowIndex1));
54 assertEquals("s", s().charAt(slowIndex2));
55 assertEquals("t", s().charAt(3));
56 assertEquals("t", s().charAt(3.4));
57 assertEquals("t", s().charAt(NaN));
58
59 assertEquals(116, s().charCodeAt());
60 assertEquals(116, s().charCodeAt("string"));
61 assertEquals(116, s().charCodeAt(null));
62 assertEquals(116, s().charCodeAt(void 0));
63 assertEquals(116, s().charCodeAt(false));
64 assertEquals(101, s().charCodeAt(true));
65 assertEquals(116, s().charCodeAt(0));
66 assertEquals(116, s().charCodeAt(-0.0));
67 assertEquals(116, s().charCodeAt(-0.1));
68 assertEquals(116, s().charCodeAt(0.4));
69 assertEquals(101, s().charCodeAt(slowIndex1));
70 assertEquals(115, s().charCodeAt(slowIndex2));
71 assertEquals(116, s().charCodeAt(3));
72 assertEquals(116, s().charCodeAt(3.4));
73 assertEquals(116, s().charCodeAt(NaN));
74 assertTrue(isNaN(s().charCodeAt(-1)));
75 assertTrue(isNaN(s().charCodeAt(len)));
76 assertTrue(isNaN(s().charCodeAt(slowIndexOutOfRange)));
77 assertTrue(isNaN(s().charCodeAt(1/0)));
78 assertTrue(isNaN(s().charCodeAt(-1/0)));
79}
80basicTest(function() { return s; }, s.length);
81basicTest(getCons, getCons().length);
Steve Blocka7e24c12009-10-30 11:49:00 +000082
Steve Block6ded16b2010-05-10 14:33:55 +010083// Make sure enough of the one-char string cache is filled.
84var alpha = ['@'];
85for (var i = 1; i < 128; i++) {
86 var c = String.fromCharCode(i);
87 alpha[i] = c.charAt(0);
88}
89var alphaStr = alpha.join("");
90
91// Now test chars.
92for (var i = 1; i < 128; i++) {
93 assertEquals(alpha[i], alphaStr.charAt(i));
94 assertEquals(String.fromCharCode(i), alphaStr.charAt(i));
95}
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010096
97// Test stealing String.prototype.{charAt,charCodeAt}.
98var o = {
99 charAt: String.prototype.charAt,
100 charCodeAt: String.prototype.charCodeAt,
101 toString: function() { return "012"; },
102 valueOf: function() { return "should not be called"; }
103};
104
105function stealTest() {
106 assertEquals("0", o.charAt(0));
107 assertEquals("1", o.charAt(1));
108 assertEquals("1", o.charAt(1.4));
109 assertEquals("1", o.charAt(slowIndex1));
110 assertEquals("2", o.charAt(2));
111 assertEquals("2", o.charAt(slowIndex2));
112 assertEquals(48, o.charCodeAt(0));
113 assertEquals(49, o.charCodeAt(1));
114 assertEquals(49, o.charCodeAt(1.4));
115 assertEquals(49, o.charCodeAt(slowIndex1));
116 assertEquals(50, o.charCodeAt(2));
117 assertEquals(50, o.charCodeAt(slowIndex2));
118 assertEquals("", o.charAt(-1));
119 assertEquals("", o.charAt(-1.4));
120 assertEquals("", o.charAt(10));
121 assertEquals("", o.charAt(slowIndexOutOfRange));
122 assertTrue(isNaN(o.charCodeAt(-1)));
123 assertTrue(isNaN(o.charCodeAt(-1.4)));
124 assertTrue(isNaN(o.charCodeAt(10)));
125 assertTrue(isNaN(o.charCodeAt(slowIndexOutOfRange)));
126}
127stealTest();
128
129// Test custom string IC-s.
130for (var i = 0; i < 20; i++) {
131 basicTest(function() { return s; }, s.length);
132 basicTest(getCons, getCons().length);
133 stealTest();
134}
135
136var badToString = function() { return []; };
137
138function testBadToString_charAt() {
139 var goodToString = o.toString;
140 var hasCaught = false;
141 var numCalls = 0;
142 var result;
143 try {
144 for (var i = 0; i < 20; i++) {
145 if (i == 10) o.toString = o.valueOf = badToString;
146 result = o.charAt(1);
147 numCalls++;
148 }
149 } catch (e) {
150 hasCaught = true;
151 } finally {
152 o.toString = goodToString;
153 }
154 assertTrue(hasCaught);
155 assertEquals("1", result);
156 assertEquals(10, numCalls);
157}
158testBadToString_charAt();
159
160function testBadToString_charCodeAt() {
161 var goodToString = o.toString;
162 var hasCaught = false;
163 var numCalls = 0;
164 var result;
165 try {
166 for (var i = 0; i < 20; i++) {
167 if (i == 10) o.toString = o.valueOf = badToString;
168 result = o.charCodeAt(1);
169 numCalls++;
170 }
171 } catch (e) {
172 hasCaught = true;
173 } finally {
174 o.toString = goodToString;
175 }
176 assertTrue(hasCaught);
177 assertEquals(49, result);
178 assertEquals(10, numCalls);
179}
180testBadToString_charCodeAt();
181
182var badIndex = {
183 toString: badToString,
184 valueOf: badToString
185};
186
187function testBadIndex_charAt() {
188 var index = 1;
189 var hasCaught = false;
190 var numCalls = 0;
191 var result;
192 try {
193 for (var i = 0; i < 20; i++) {
194 if (i == 10) index = badIndex;
195 result = o.charAt(index);
196 numCalls++;
197 }
198 } catch (e) {
199 hasCaught = true;
200 }
201 assertTrue(hasCaught);
202 assertEquals("1", result);
203 assertEquals(10, numCalls);
204}
205testBadIndex_charAt();
206
207function testBadIndex_charCodeAt() {
208 var index = 1;
209 var hasCaught = false;
210 var numCalls = 0;
211 var result;
212 try {
213 for (var i = 0; i < 20; i++) {
214 if (i == 10) index = badIndex;
215 result = o.charCodeAt(index);
216 numCalls++;
217 }
218 } catch (e) {
219 hasCaught = true;
220 }
221 assertTrue(hasCaught);
222 assertEquals(49, result);
223 assertEquals(10, numCalls);
224}
225testBadIndex_charCodeAt();
226
227function testPrototypeChange_charAt() {
228 var result, oldResult;
229 for (var i = 0; i < 20; i++) {
230 if (i == 10) {
231 oldResult = result;
232 String.prototype.charAt = function() { return "%"; };
233 }
234 result = s.charAt(1);
235 }
236 assertEquals("%", result);
237 assertEquals("e", oldResult);
238 delete String.prototype.charAt; // Restore the default.
239}
240testPrototypeChange_charAt();
241
242function testPrototypeChange_charCodeAt() {
243 var result, oldResult;
244 for (var i = 0; i < 20; i++) {
245 if (i == 10) {
246 oldResult = result;
247 String.prototype.charCodeAt = function() { return 42; };
248 }
249 result = s.charCodeAt(1);
250 }
251 assertEquals(42, result);
252 assertEquals(101, oldResult);
253 delete String.prototype.charCodeAt; // Restore the default.
254}
255testPrototypeChange_charCodeAt();