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 29var 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. 75var 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. 140var 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. 148var reducing_functions = 149 [Array.prototype.reduce, 150 Array.prototype.reduceRight]; 151 152function 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. 159for (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. 207for (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. 251var array = [1,2,3,4,5]; 252for (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 278for (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. 306for (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 328for (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() 352assertEquals(Object.prototype.toString.call(null), 353 '[object Null]') 354 355assertEquals(Object.prototype.toString.call(undefined), 356 '[object Undefined]') 357