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