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
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.
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.
30 function getTwoByteString() { return "\u1234t"; }
31 function getCons() { return "testtesttesttest" + getTwoByteString() }
33 var slowIndex1 = { valueOf: function() { return 1; } };
34 var slowIndex2 = { toString: function() { return "2"; } };
35 var slowIndexOutOfRange = { valueOf: function() { return -1; } };
37 function 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));
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)));
80 basicTest(function() { return s; }, s.length);
81 basicTest(getCons, getCons().length);
83 // Make sure enough of the one-char string cache is filled.
85 for (var i = 1; i < 128; i++) {
86 var c = String.fromCharCode(i);
87 alpha[i] = c.charAt(0);
89 var alphaStr = alpha.join("");
92 for (var i = 1; i < 128; i++) {
93 assertEquals(alpha[i], alphaStr.charAt(i));
94 assertEquals(String.fromCharCode(i), alphaStr.charAt(i));
97 // Test stealing String.prototype.{charAt,charCodeAt}.
99 charAt: String.prototype.charAt,
100 charCodeAt: String.prototype.charCodeAt,
101 toString: function() { return "012"; },
102 valueOf: function() { return "should not be called"; }
105 function 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)));
129 // Test custom string IC-s.
130 for (var i = 0; i < 20; i++) {
131 basicTest(function() { return s; }, s.length);
132 basicTest(getCons, getCons().length);
136 var badToString = function() { return []; };
138 function testBadToString_charAt() {
139 var goodToString = o.toString;
140 var hasCaught = false;
144 for (var i = 0; i < 20; i++) {
145 if (i == 10) o.toString = o.valueOf = badToString;
146 result = o.charAt(1);
152 o.toString = goodToString;
154 assertTrue(hasCaught);
155 assertEquals("1", result);
156 assertEquals(10, numCalls);
158 testBadToString_charAt();
160 function testBadToString_charCodeAt() {
161 var goodToString = o.toString;
162 var hasCaught = false;
166 for (var i = 0; i < 20; i++) {
167 if (i == 10) o.toString = o.valueOf = badToString;
168 result = o.charCodeAt(1);
174 o.toString = goodToString;
176 assertTrue(hasCaught);
177 assertEquals(49, result);
178 assertEquals(10, numCalls);
180 testBadToString_charCodeAt();
183 toString: badToString,
187 function testBadIndex_charAt() {
189 var hasCaught = false;
193 for (var i = 0; i < 20; i++) {
194 if (i == 10) index = badIndex;
195 result = o.charAt(index);
201 assertTrue(hasCaught);
202 assertEquals("1", result);
203 assertEquals(10, numCalls);
205 testBadIndex_charAt();
207 function testBadIndex_charCodeAt() {
209 var hasCaught = false;
213 for (var i = 0; i < 20; i++) {
214 if (i == 10) index = badIndex;
215 result = o.charCodeAt(index);
221 assertTrue(hasCaught);
222 assertEquals(49, result);
223 assertEquals(10, numCalls);
225 testBadIndex_charCodeAt();
227 function testPrototypeChange_charAt() {
228 var result, oldResult;
229 for (var i = 0; i < 20; i++) {
232 String.prototype.charAt = function() { return "%"; };
234 result = s.charAt(1);
236 assertEquals("%", result);
237 assertEquals("e", oldResult);
238 delete String.prototype.charAt; // Restore the default.
240 testPrototypeChange_charAt();
242 function testPrototypeChange_charCodeAt() {
243 var result, oldResult;
244 for (var i = 0; i < 20; i++) {
247 String.prototype.charCodeAt = function() { return 42; };
249 result = s.charCodeAt(1);
251 assertEquals(42, result);
252 assertEquals(101, oldResult);
253 delete String.prototype.charCodeAt; // Restore the default.
255 testPrototypeChange_charCodeAt();