Home | History | Annotate | Download | only in mjsunit
      1 // Copyright 2011 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 
     29 var should_throw_on_null_and_undefined =
     30     [Object.prototype.toLocaleString,
     31      Object.prototype.valueOf,
     32      Object.prototype.hasOwnProperty,
     33      Object.prototype.isPrototypeOf,
     34      Object.prototype.propertyIsEnumerable,
     35      Array.prototype.concat,
     36      Array.prototype.join,
     37      Array.prototype.pop,
     38      Array.prototype.push,
     39      Array.prototype.reverse,
     40      Array.prototype.shift,
     41      Array.prototype.slice,
     42      Array.prototype.sort,
     43      Array.prototype.splice,
     44      Array.prototype.unshift,
     45      Array.prototype.indexOf,
     46      Array.prototype.lastIndexOf,
     47      Array.prototype.every,
     48      Array.prototype.some,
     49      Array.prototype.forEach,
     50      Array.prototype.map,
     51      Array.prototype.filter,
     52      Array.prototype.reduce,
     53      Array.prototype.reduceRight,
     54      String.prototype.charAt,
     55      String.prototype.charCodeAt,
     56      String.prototype.concat,
     57      String.prototype.indexOf,
     58      String.prototype.lastIndexOf,
     59      String.prototype.localeCompare,
     60      String.prototype.match,
     61      String.prototype.replace,
     62      String.prototype.search,
     63      String.prototype.slice,
     64      String.prototype.split,
     65      String.prototype.substring,
     66      String.prototype.toLowerCase,
     67      String.prototype.toLocaleLowerCase,
     68      String.prototype.toUpperCase,
     69      String.prototype.toLocaleUpperCase,
     70      String.prototype.trim,
     71      Number.prototype.toLocaleString];
     72 
     73 // Non generic natives do not work on any input other than the specific
     74 // type, but since this change will allow call to be invoked with undefined
     75 // or null as this we still explicitly test that we throw on these here.
     76 var non_generic =
     77     [Array.prototype.toString,
     78      Array.prototype.toLocaleString,
     79      Function.prototype.toString,
     80      Function.prototype.call,
     81      Function.prototype.apply,
     82      String.prototype.toString,
     83      String.prototype.valueOf,
     84      Boolean.prototype.toString,
     85      Boolean.prototype.valueOf,
     86      Number.prototype.toString,
     87      Number.prototype.valueOf,
     88      Number.prototype.toFixed,
     89      Number.prototype.toExponential,
     90      Number.prototype.toPrecision,
     91      Date.prototype.toString,
     92      Date.prototype.toDateString,
     93      Date.prototype.toTimeString,
     94      Date.prototype.toLocaleString,
     95      Date.prototype.toLocaleDateString,
     96      Date.prototype.toLocaleTimeString,
     97      Date.prototype.valueOf,
     98      Date.prototype.getTime,
     99      Date.prototype.getFullYear,
    100      Date.prototype.getUTCFullYear,
    101      Date.prototype.getMonth,
    102      Date.prototype.getUTCMonth,
    103      Date.prototype.getDate,
    104      Date.prototype.getUTCDate,
    105      Date.prototype.getDay,
    106      Date.prototype.getUTCDay,
    107      Date.prototype.getHours,
    108      Date.prototype.getUTCHours,
    109      Date.prototype.getMinutes,
    110      Date.prototype.getUTCMinutes,
    111      Date.prototype.getSeconds,
    112      Date.prototype.getUTCSeconds,
    113      Date.prototype.getMilliseconds,
    114      Date.prototype.getUTCMilliseconds,
    115      Date.prototype.getTimezoneOffset,
    116      Date.prototype.setTime,
    117      Date.prototype.setMilliseconds,
    118      Date.prototype.setUTCMilliseconds,
    119      Date.prototype.setSeconds,
    120      Date.prototype.setUTCSeconds,
    121      Date.prototype.setMinutes,
    122      Date.prototype.setUTCMinutes,
    123      Date.prototype.setHours,
    124      Date.prototype.setUTCHours,
    125      Date.prototype.setDate,
    126      Date.prototype.setUTCDate,
    127      Date.prototype.setMonth,
    128      Date.prototype.setUTCMonth,
    129      Date.prototype.setFullYear,
    130      Date.prototype.setUTCFullYear,
    131      Date.prototype.toUTCString,
    132      Date.prototype.toISOString,
    133      Date.prototype.toJSON,
    134      RegExp.prototype.exec,
    135      RegExp.prototype.test,
    136      RegExp.prototype.toString,
    137      Error.prototype.toString];
    138 
    139 
    140 // Mapping functions.
    141 var mapping_functions =
    142     [Array.prototype.every,
    143      Array.prototype.some,
    144      Array.prototype.forEach,
    145      Array.prototype.map,
    146      Array.prototype.filter];
    147 
    148 // Reduce functions.
    149 var reducing_functions =
    150     [Array.prototype.reduce,
    151      Array.prototype.reduceRight];
    152 
    153 // Test that all natives using the ToObject call throw the right exception.
    154 for (var i = 0; i < should_throw_on_null_and_undefined.length; i++) {
    155   // Sanity check that all functions are correct
    156   assertEquals(typeof(should_throw_on_null_and_undefined[i]), "function");
    157 
    158   var exception = false;
    159   try {
    160     // We call all functions with no parameters, which means that essential
    161     // parameters will have the undefined value.
    162     // The test for whether the "this" value is null or undefined is always
    163     // performed before access to the other parameters, so even if the
    164     // undefined value is an invalid argument value, it mustn't change
    165     // the result of the test.
    166     should_throw_on_null_and_undefined[i].call(null);
    167   } catch (e) {
    168     exception = true;
    169     assertTrue("called_on_null_or_undefined" == e.type ||
    170                "null_to_object" == e.type);
    171   }
    172   assertTrue(exception);
    173 
    174   exception = false;
    175   try {
    176     should_throw_on_null_and_undefined[i].call(undefined);
    177   } catch (e) {
    178     exception = true;
    179     assertTrue("called_on_null_or_undefined" == e.type ||
    180                "null_to_object" == e.type);
    181   }
    182   assertTrue(exception);
    183 
    184   exception = false;
    185   try {
    186     should_throw_on_null_and_undefined[i].apply(null);
    187   } catch (e) {
    188     exception = true;
    189     assertTrue("called_on_null_or_undefined" == e.type ||
    190                "null_to_object" == e.type);
    191   }
    192   assertTrue(exception);
    193 
    194   exception = false;
    195   try {
    196     should_throw_on_null_and_undefined[i].apply(undefined);
    197   } catch (e) {
    198     exception = true;
    199     assertTrue("called_on_null_or_undefined" == e.type ||
    200                "null_to_object" == e.type);
    201   }
    202   assertTrue(exception);
    203 }
    204 
    205 // Test that all natives that are non generic throw on null and undefined.
    206 for (var i = 0; i < non_generic.length; i++) {
    207   // Sanity check that all functions are correct
    208   assertEquals(typeof(non_generic[i]), "function");
    209 
    210   exception = false;
    211   try {
    212     non_generic[i].call(null);
    213   } catch (e) {
    214     exception = true;
    215     assertTrue(e instanceof TypeError);
    216   }
    217   assertTrue(exception);
    218 
    219   exception = false;
    220   try {
    221     non_generic[i].call(null);
    222   } catch (e) {
    223     exception = true;
    224     assertTrue(e instanceof TypeError);
    225   }
    226   assertTrue(exception);
    227 
    228   exception = false;
    229   try {
    230     non_generic[i].apply(null);
    231   } catch (e) {
    232     exception = true;
    233     assertTrue(e instanceof TypeError);
    234   }
    235   assertTrue(exception);
    236 
    237   exception = false;
    238   try {
    239     non_generic[i].apply(null);
    240   } catch (e) {
    241     exception = true;
    242     assertTrue(e instanceof TypeError);
    243   }
    244   assertTrue(exception);
    245 }
    246 
    247 
    248 // Test that we still throw when calling with thisArg null or undefined
    249 // through an array mapping function.
    250 var array = [1,2,3,4,5];
    251 for (var j = 0; j < mapping_functions.length; j++) {
    252   for (var i = 0; i < should_throw_on_null_and_undefined.length; i++) {
    253     exception = false;
    254     try {
    255       mapping_functions[j].call(array,
    256                                 should_throw_on_null_and_undefined[i],
    257                                 null);
    258     } catch (e) {
    259       exception = true;
    260       assertTrue("called_on_null_or_undefined" == e.type ||
    261                  "null_to_object" == e.type);
    262     }
    263     assertTrue(exception);
    264 
    265     exception = false;
    266     try {
    267       mapping_functions[j].call(array,
    268                                 should_throw_on_null_and_undefined[i],
    269                                 undefined);
    270     } catch (e) {
    271       exception = true;
    272       assertTrue("called_on_null_or_undefined" == e.type ||
    273                  "null_to_object" == e.type);
    274     }
    275     assertTrue(exception);
    276   }
    277 }
    278 
    279 for (var j = 0; j < mapping_functions.length; j++) {
    280   for (var i = 0; i < non_generic.length; i++) {
    281     exception = false;
    282     try {
    283       mapping_functions[j].call(array,
    284                                 non_generic[i],
    285                                 null);
    286     } catch (e) {
    287       exception = true;
    288       assertTrue(e instanceof TypeError);
    289     }
    290     assertTrue(exception);
    291 
    292     exception = false;
    293     try {
    294       mapping_functions[j].call(array,
    295                                 non_generic[i],
    296                                 undefined);
    297     } catch (e) {
    298       exception = true;
    299       assertTrue(e instanceof TypeError);
    300     }
    301     assertTrue(exception);
    302   }
    303 }
    304 
    305 
    306 // Reduce functions do a call with null as this argument.
    307 for (var j = 0; j < reducing_functions.length; j++) {
    308   for (var i = 0; i < should_throw_on_null_and_undefined.length; i++) {
    309     exception = false;
    310     try {
    311       reducing_functions[j].call(array, should_throw_on_null_and_undefined[i]);
    312     } catch (e) {
    313       exception = true;
    314       assertTrue("called_on_null_or_undefined" == e.type ||
    315                  "null_to_object" == e.type);
    316     }
    317     assertTrue(exception);
    318 
    319     exception = false;
    320     try {
    321       reducing_functions[j].call(array, should_throw_on_null_and_undefined[i]);
    322     } catch (e) {
    323       exception = true;
    324       assertTrue("called_on_null_or_undefined" == e.type ||
    325                  "null_to_object" == e.type);
    326     }
    327     assertTrue(exception);
    328   }
    329 }
    330 
    331 for (var j = 0; j < reducing_functions.length; j++) {
    332   for (var i = 0; i < non_generic.length; i++) {
    333     exception = false;
    334     try {
    335       reducing_functions[j].call(array, non_generic[i]);
    336     } catch (e) {
    337       exception = true;
    338       assertTrue(e instanceof TypeError);
    339     }
    340     assertTrue(exception);
    341 
    342     exception = false;
    343     try {
    344       reducing_functions[j].call(array, non_generic[i]);
    345     } catch (e) {
    346       exception = true;
    347       assertTrue(e instanceof TypeError);
    348     }
    349     assertTrue(exception);
    350   }
    351 }
    352 
    353 
    354 // Object.prototype.toString()
    355 assertEquals(Object.prototype.toString.call(null),
    356              '[object Null]')
    357 
    358 assertEquals(Object.prototype.toString.call(undefined),
    359              '[object Undefined]')
    360