Home | History | Annotate | Download | only in mjsunit
      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 var s = "test";
     29 
     30 function getTwoByteString() { return "\u1234t"; }
     31 function getCons() { return "testtesttesttest" + getTwoByteString() }
     32 
     33 var slowIndex1 = { valueOf: function() { return 1; } };
     34 var slowIndex2 = { toString: function() { return "2"; } };
     35 var slowIndexOutOfRange = { valueOf: function() { return -1; } };
     36 
     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));
     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 }
     80 basicTest(function() { return s; }, s.length);
     81 basicTest(getCons, getCons().length);
     82 
     83 // Make sure enough of the one-char string cache is filled.
     84 var alpha = ['@'];
     85 for (var i = 1; i < 128; i++) {
     86   var c = String.fromCharCode(i);
     87   alpha[i] = c.charAt(0);
     88 }
     89 var alphaStr = alpha.join("");
     90 
     91 // Now test chars.
     92 for (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}.
     98 var 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 
    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)));
    126 }
    127 stealTest();
    128 
    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);
    133   stealTest();
    134 }
    135 
    136 var badToString = function() { return []; };
    137 
    138 function 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 }
    158 testBadToString_charAt();
    159 
    160 function 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 }
    180 testBadToString_charCodeAt();
    181 
    182 var badIndex = {
    183   toString: badToString,
    184   valueOf: badToString
    185 };
    186 
    187 function 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 }
    205 testBadIndex_charAt();
    206 
    207 function 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 }
    225 testBadIndex_charCodeAt();
    226 
    227 function 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 }
    240 testPrototypeChange_charAt();
    241 
    242 function 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 }
    255 testPrototypeChange_charCodeAt();
    256