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 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. 76var 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. 141var 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. 149var reducing_functions = 150 [Array.prototype.reduce, 151 Array.prototype.reduceRight]; 152 153// Test that all natives using the ToObject call throw the right exception. 154for (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. 206for (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. 250var array = [1,2,3,4,5]; 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 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 279for (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. 307for (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 331for (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() 355assertEquals(Object.prototype.toString.call(null), 356 '[object Null]') 357 358assertEquals(Object.prototype.toString.call(undefined), 359 '[object Undefined]') 360