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 need to pass a dummy object argument ({}) to these functions because 166 // of Object.prototype.isPrototypeOf's special behavior, see issue 3483 167 // for more details. 168 should_throw_on_null_and_undefined[i].call(null, {}); 169 } catch (e) { 170 exception = true; 171 checkExpectedMessage(e); 172 } 173 assertTrue(exception); 174 175 exception = false; 176 try { 177 should_throw_on_null_and_undefined[i].call(undefined, {}); 178 } catch (e) { 179 exception = true; 180 checkExpectedMessage(e); 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 checkExpectedMessage(e); 190 } 191 assertTrue(exception); 192 193 exception = false; 194 try { 195 should_throw_on_null_and_undefined[i].apply(undefined, [{}]); 196 } catch (e) { 197 exception = true; 198 checkExpectedMessage(e); 199 } 200 assertTrue(exception); 201} 202 203// Test that all natives that are non generic throw on null and undefined. 204for (var i = 0; i < non_generic.length; i++) { 205 // Sanity check that all functions are correct 206 assertEquals(typeof(non_generic[i]), "function"); 207 208 exception = false; 209 try { 210 non_generic[i].call(null); 211 } catch (e) { 212 exception = true; 213 assertTrue(e instanceof TypeError); 214 } 215 assertTrue(exception); 216 217 exception = false; 218 try { 219 non_generic[i].call(null); 220 } catch (e) { 221 exception = true; 222 assertTrue(e instanceof TypeError); 223 } 224 assertTrue(exception); 225 226 exception = false; 227 try { 228 non_generic[i].apply(null); 229 } catch (e) { 230 exception = true; 231 assertTrue(e instanceof TypeError); 232 } 233 assertTrue(exception); 234 235 exception = false; 236 try { 237 non_generic[i].apply(null); 238 } catch (e) { 239 exception = true; 240 assertTrue(e instanceof TypeError); 241 } 242 assertTrue(exception); 243} 244 245 246// Test that we still throw when calling with thisArg null or undefined 247// through an array mapping function. 248// We need to make sure that the elements of `array` are all object values, 249// see issue 3483 for more details. 250var array = [{}, [], new Number, new Map, new WeakSet]; 251for (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 checkExpectedMessage(e); 261 } 262 assertTrue(exception); 263 264 exception = false; 265 try { 266 mapping_functions[j].call(array, 267 should_throw_on_null_and_undefined[i], 268 undefined); 269 } catch (e) { 270 exception = true; 271 checkExpectedMessage(e); 272 } 273 assertTrue(exception); 274 } 275} 276 277for (var j = 0; j < mapping_functions.length; j++) { 278 for (var i = 0; i < non_generic.length; i++) { 279 exception = false; 280 try { 281 mapping_functions[j].call(array, 282 non_generic[i], 283 null); 284 } catch (e) { 285 exception = true; 286 assertTrue(e instanceof TypeError); 287 } 288 assertTrue(exception); 289 290 exception = false; 291 try { 292 mapping_functions[j].call(array, 293 non_generic[i], 294 undefined); 295 } catch (e) { 296 exception = true; 297 assertTrue(e instanceof TypeError); 298 } 299 assertTrue(exception); 300 } 301} 302 303 304// Reduce functions do a call with null as this argument. 305for (var j = 0; j < reducing_functions.length; j++) { 306 for (var i = 0; i < should_throw_on_null_and_undefined.length; i++) { 307 exception = false; 308 try { 309 reducing_functions[j].call(array, should_throw_on_null_and_undefined[i]); 310 } catch (e) { 311 exception = true; 312 checkExpectedMessage(e); 313 } 314 assertTrue(exception); 315 316 exception = false; 317 try { 318 reducing_functions[j].call(array, should_throw_on_null_and_undefined[i]); 319 } catch (e) { 320 exception = true; 321 checkExpectedMessage(e); 322 } 323 assertTrue(exception); 324 } 325} 326 327for (var j = 0; j < reducing_functions.length; j++) { 328 for (var i = 0; i < non_generic.length; i++) { 329 exception = false; 330 try { 331 reducing_functions[j].call(array, non_generic[i]); 332 } catch (e) { 333 exception = true; 334 assertTrue(e instanceof TypeError); 335 } 336 assertTrue(exception); 337 338 exception = false; 339 try { 340 reducing_functions[j].call(array, non_generic[i]); 341 } catch (e) { 342 exception = true; 343 assertTrue(e instanceof TypeError); 344 } 345 assertTrue(exception); 346 } 347} 348 349 350// Object.prototype.toString() 351assertEquals(Object.prototype.toString.call(null), 352 '[object Null]') 353 354assertEquals(Object.prototype.toString.call(undefined), 355 '[object Undefined]') 356