Index: test/mjsunit/string-charat.js |
diff --git a/test/mjsunit/string-charat.js b/test/mjsunit/string-charat.js |
index d1989dfd731177e50c4bd3dcbdd585995901b16e..a14d51aa528d5101d2a8744592add488ddae04f7 100644 |
--- a/test/mjsunit/string-charat.js |
+++ b/test/mjsunit/string-charat.js |
@@ -27,29 +27,48 @@ |
var s = "test"; |
-assertEquals("t", s.charAt()); |
-assertEquals("t", s.charAt("string")); |
-assertEquals("t", s.charAt(null)); |
-assertEquals("t", s.charAt(void 0)); |
-assertEquals("t", s.charAt(false)); |
-assertEquals("e", s.charAt(true)); |
-assertEquals("", s.charAt(-1)); |
-assertEquals("", s.charAt(4)); |
-assertEquals("t", s.charAt(0)); |
-assertEquals("t", s.charAt(3)); |
-assertEquals("t", s.charAt(NaN)); |
- |
-assertEquals(116, s.charCodeAt()); |
-assertEquals(116, s.charCodeAt("string")); |
-assertEquals(116, s.charCodeAt(null)); |
-assertEquals(116, s.charCodeAt(void 0)); |
-assertEquals(116, s.charCodeAt(false)); |
-assertEquals(101, s.charCodeAt(true)); |
-assertEquals(116, s.charCodeAt(0)); |
-assertEquals(116, s.charCodeAt(3)); |
-assertEquals(116, s.charCodeAt(NaN)); |
-assertTrue(isNaN(s.charCodeAt(-1))); |
-assertTrue(isNaN(s.charCodeAt(4))); |
+var slowIndex1 = { valueOf: function() { return 1; } }; |
+var slowIndex2 = { toString: function() { return "2"; } }; |
+var slowIndexOutOfRange = { valueOf: function() { return -1; } }; |
+ |
+function basicTest() { |
+ assertEquals("t", s.charAt()); |
+ assertEquals("t", s.charAt("string")); |
+ assertEquals("t", s.charAt(null)); |
+ assertEquals("t", s.charAt(void 0)); |
+ assertEquals("t", s.charAt(false)); |
+ assertEquals("e", s.charAt(true)); |
+ assertEquals("", s.charAt(-1)); |
+ assertEquals("", s.charAt(4)); |
+ assertEquals("", s.charAt(slowIndexOutOfRange)); |
+ assertEquals("t", s.charAt(0)); |
+ assertEquals("t", s.charAt(-0.0)); |
+ assertEquals("t", s.charAt(0.4)); |
+ assertEquals("e", s.charAt(slowIndex1)); |
+ assertEquals("s", s.charAt(slowIndex2)); |
+ assertEquals("t", s.charAt(3)); |
+ assertEquals("t", s.charAt(3.4)); |
+ assertEquals("t", s.charAt(NaN)); |
+ |
+ assertEquals(116, s.charCodeAt()); |
+ assertEquals(116, s.charCodeAt("string")); |
+ assertEquals(116, s.charCodeAt(null)); |
+ assertEquals(116, s.charCodeAt(void 0)); |
+ assertEquals(116, s.charCodeAt(false)); |
+ assertEquals(101, s.charCodeAt(true)); |
+ assertEquals(116, s.charCodeAt(0)); |
+ assertEquals(116, s.charCodeAt(-0.0)); |
+ assertEquals(116, s.charCodeAt(0.4)); |
+ assertEquals(101, s.charCodeAt(slowIndex1)); |
+ assertEquals(115, s.charCodeAt(slowIndex2)); |
+ assertEquals(116, s.charCodeAt(3)); |
+ assertEquals(116, s.charCodeAt(3.4)); |
+ assertEquals(116, s.charCodeAt(NaN)); |
+ assertTrue(isNaN(s.charCodeAt(-1))); |
+ assertTrue(isNaN(s.charCodeAt(4))); |
+ assertTrue(isNaN(s.charCodeAt(slowIndexOutOfRange))); |
+} |
+basicTest(); |
// Make sure enough of the one-char string cache is filled. |
var alpha = ['@']; |
@@ -64,3 +83,162 @@ for (var i = 1; i < 128; i++) { |
assertEquals(alpha[i], alphaStr.charAt(i)); |
assertEquals(String.fromCharCode(i), alphaStr.charAt(i)); |
} |
+ |
+// Test stealing String.prototype.{charAt,charCodeAt}. |
+var o = { |
+ charAt: String.prototype.charAt, |
+ charCodeAt: String.prototype.charCodeAt, |
+ toString: function() { return "012"; }, |
+ valueOf: function() { return "should not be called"; } |
+}; |
+ |
+function stealTest() { |
+ assertEquals("0", o.charAt(0)); |
+ assertEquals("1", o.charAt(1)); |
+ assertEquals("1", o.charAt(1.4)); |
+ assertEquals("1", o.charAt(slowIndex1)); |
+ assertEquals("2", o.charAt(2)); |
+ assertEquals("2", o.charAt(slowIndex2)); |
+ assertEquals(48, o.charCodeAt(0)); |
+ assertEquals(49, o.charCodeAt(1)); |
+ assertEquals(49, o.charCodeAt(1.4)); |
+ assertEquals(49, o.charCodeAt(slowIndex1)); |
+ assertEquals(50, o.charCodeAt(2)); |
+ assertEquals(50, o.charCodeAt(slowIndex2)); |
+ assertEquals("", o.charAt(-1)); |
+ assertEquals("", o.charAt(-1.4)); |
+ assertEquals("", o.charAt(10)); |
+ assertEquals("", o.charAt(slowIndexOutOfRange)); |
+ assertTrue(isNaN(o.charCodeAt(-1))); |
+ assertTrue(isNaN(o.charCodeAt(-1.4))); |
+ assertTrue(isNaN(o.charCodeAt(10))); |
+ assertTrue(isNaN(o.charCodeAt(slowIndexOutOfRange))); |
+} |
+stealTest(); |
+ |
+// Test custom string IC-s. |
+for (var i = 0; i < 20; i++) { |
+ basicTest(); |
+ stealTest(); |
+} |
+ |
+var badToString = function() { return []; }; |
+ |
+function testBadToString_charAt() { |
+ var goodToString = o.toString; |
+ var hasCaught = false; |
+ var numCalls = 0; |
+ var result; |
+ try { |
+ for (var i = 0; i < 20; i++) { |
+ if (i == 10) o.toString = o.valueOf = badToString; |
+ result = o.charAt(1); |
+ numCalls++; |
+ } |
+ } catch (e) { |
+ hasCaught = true; |
+ } finally { |
+ o.toString = goodToString; |
+ } |
+ assertTrue(hasCaught); |
+ assertEquals("1", result); |
+ assertEquals(10, numCalls); |
+} |
+testBadToString_charAt(); |
+ |
+function testBadToString_charCodeAt() { |
+ var goodToString = o.toString; |
+ var hasCaught = false; |
+ var numCalls = 0; |
+ var result; |
+ try { |
+ for (var i = 0; i < 20; i++) { |
+ if (i == 10) o.toString = o.valueOf = badToString; |
+ result = o.charCodeAt(1); |
+ numCalls++; |
+ } |
+ } catch (e) { |
+ hasCaught = true; |
+ } finally { |
+ o.toString = goodToString; |
+ } |
+ assertTrue(hasCaught); |
+ assertEquals(49, result); |
+ assertEquals(10, numCalls); |
+} |
+testBadToString_charCodeAt(); |
+ |
+var badIndex = { |
+ toString: badToString, |
+ valueOf: badToString |
+}; |
+ |
+function testBadIndex_charAt() { |
+ var index = 1; |
+ var hasCaught = false; |
+ var numCalls = 0; |
+ var result; |
+ try { |
+ for (var i = 0; i < 20; i++) { |
+ if (i == 10) index = badIndex; |
+ result = o.charAt(index); |
+ numCalls++; |
+ } |
+ } catch (e) { |
+ hasCaught = true; |
+ } |
+ assertTrue(hasCaught); |
+ assertEquals("1", result); |
+ assertEquals(10, numCalls); |
+} |
+testBadIndex_charAt(); |
+ |
+function testBadIndex_charCodeAt() { |
+ var index = 1; |
+ var hasCaught = false; |
+ var numCalls = 0; |
+ var result; |
+ try { |
+ for (var i = 0; i < 20; i++) { |
+ if (i == 10) index = badIndex; |
+ result = o.charCodeAt(index); |
+ numCalls++; |
+ } |
+ } catch (e) { |
+ hasCaught = true; |
+ } |
+ assertTrue(hasCaught); |
+ assertEquals(49, result); |
+ assertEquals(10, numCalls); |
+} |
+testBadIndex_charCodeAt(); |
+ |
+function testPrototypeChange_charAt() { |
+ var result, oldResult; |
+ for (var i = 0; i < 20; i++) { |
+ if (i == 10) { |
+ oldResult = result; |
+ String.prototype.charAt = function() { return "%"; }; |
+ } |
+ result = s.charAt(1); |
+ } |
+ assertEquals("%", result); |
+ assertEquals("e", oldResult); |
+ delete String.prototype.charAt; // Restore the default. |
+} |
+testPrototypeChange_charAt(); |
+ |
+function testPrototypeChange_charCodeAt() { |
+ var result, oldResult; |
+ for (var i = 0; i < 20; i++) { |
+ if (i == 10) { |
+ oldResult = result; |
+ String.prototype.charCodeAt = function() { return 42; }; |
+ } |
+ result = s.charCodeAt(1); |
+ } |
+ assertEquals(42, result); |
+ assertEquals(101, oldResult); |
+ delete String.prototype.charCodeAt; // Restore the default. |
+} |
+testPrototypeChange_charCodeAt(); |