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 28var s = "test"; 29 30function getTwoByteString() { return "\u1234t"; } 31function getCons() { return "testtesttesttest" + getTwoByteString() } 32 33var 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); 82 83// 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} 96 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(); 256