1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Flags: --strong-mode --harmony-reflect 6 // Flags: --allow-natives-syntax 7 8 'use strict'; 9 10 11 function generateArguments(n, prefix) { 12 let a = []; 13 if (prefix) { 14 a.push(prefix); 15 } 16 for (let i = 0; i < n; i++) { 17 a.push(String(i)); 18 } 19 20 return a.join(', '); 21 } 22 23 24 function generateParams(n, directive_in_body) { 25 let a = []; 26 for (let i = 0; i < n; i++) { 27 a[i] = `p${i}`; 28 } 29 return a.join(', '); 30 } 31 32 function generateParamsWithRest(n, directive_in_body) { 33 let a = []; 34 let i = 0; 35 for (; i < n; i++) { 36 a[i] = `p${i}`; 37 } 38 if (!directive_in_body) { 39 // If language mode directive occurs in body, rest parameters will trigger 40 // an early error regardless of language mode. 41 a.push(`...p${i}`); 42 } 43 return a.join(', '); 44 } 45 46 47 function generateSpread(n) { 48 return `...[${generateArguments(n)}]`; 49 } 50 51 52 (function FunctionCall() { 53 for (let parameterCount = 0; parameterCount < 3; parameterCount++) { 54 let defs = [ 55 `'use strong'; function f(${generateParams(parameterCount)}) {}`, 56 `'use strong'; function f(${generateParamsWithRest(parameterCount)}) {}`, 57 `'use strong'; function* f(${generateParams(parameterCount)}) {}`, 58 `'use strong'; function* f(${generateParamsWithRest(parameterCount)}) {}`, 59 `'use strong'; let f = (${generateParams(parameterCount)}) => {}`, 60 `function f(${generateParams(parameterCount)}) { 'use strong'; }`, 61 `function* f(${generateParams(parameterCount)}) { 'use strong'; }`, 62 `let f = (${generateParams(parameterCount)}) => { 'use strong'; }`, 63 ]; 64 for (let def of defs) { 65 for (let argumentCount = 0; argumentCount < 3; argumentCount++) { 66 let calls = [ 67 `f(${generateArguments(argumentCount)})`, 68 `f(${generateSpread(argumentCount)})`, 69 `f.call(${generateArguments(argumentCount, 'undefined')})`, 70 `f.call(undefined, ${generateSpread(argumentCount)})`, 71 `f.apply(undefined, [${generateArguments(argumentCount)}])`, 72 `f.bind(undefined)(${generateArguments(argumentCount)})`, 73 `%_Call(f, ${generateArguments(argumentCount, 'undefined')})`, 74 `%Call(f, ${generateArguments(argumentCount, 'undefined')})`, 75 `%Apply(f, undefined, [${generateArguments(argumentCount)}], 0, 76 ${argumentCount})`, 77 ]; 78 79 for (let call of calls) { 80 let code = `'use strict'; ${def}; ${call};`; 81 if (argumentCount < parameterCount) { 82 print(code); 83 assertThrows(code, TypeError); 84 } else { 85 assertDoesNotThrow(code); 86 } 87 } 88 } 89 90 let calls = [ 91 `f.call()`, 92 `f.apply()`, 93 `f.apply(undefined)`, 94 ]; 95 for (let call of calls) { 96 let code = `'use strict'; ${def}; ${call};`; 97 if (parameterCount > 0) { 98 assertThrows(code, TypeError); 99 } else { 100 assertDoesNotThrow(code); 101 } 102 } 103 } 104 } 105 })(); 106 107 108 (function MethodCall() { 109 for (let genParams of [generateParams, generateParamsWithRest]) { 110 for (let parameterCount = 0; parameterCount < 3; parameterCount++) { 111 let defs = [ 112 `let o = new class { 113 m(${genParams(parameterCount, true)}) { 'use strong'; } 114 }`, 115 `let o = new class { 116 *m(${genParams(parameterCount, true)}) { 'use strong'; } 117 }`, 118 `let o = { m(${genParams(parameterCount, true)}) { 'use strong'; } }`, 119 `let o = { *m(${genParams(parameterCount, true)}) { 'use strong'; } }`, 120 `'use strong'; 121 let o = new class { m(${genParams(parameterCount)}) {} }`, 122 `'use strong'; 123 let o = new class { *m(${genParams(parameterCount)}) {} }`, 124 `'use strong'; let o = { m(${genParams(parameterCount)}) {} }`, 125 `'use strong'; let o = { *m(${genParams(parameterCount)}) {} }`, 126 ]; 127 for (let def of defs) { 128 for (let argumentCount = 0; argumentCount < 3; argumentCount++) { 129 let calls = [ 130 `o.m(${generateArguments(argumentCount)})`, 131 `o.m(${generateSpread(argumentCount)})`, 132 `o.m.call(${generateArguments(argumentCount, 'o')})`, 133 `o.m.call(o, ${generateSpread(argumentCount)})`, 134 `o.m.apply(o, [${generateArguments(argumentCount)}])`, 135 `o.m.bind(o)(${generateArguments(argumentCount)})`, 136 `%_Call(o.m, ${generateArguments(argumentCount, 'o')})`, 137 `%Call(o.m, ${generateArguments(argumentCount, 'o')})`, 138 `%Apply(o.m, o, [${generateArguments(argumentCount)}], 0, 139 ${argumentCount})`, 140 ]; 141 142 for (let call of calls) { 143 let code = `'use strict'; ${def}; ${call};`; 144 if (argumentCount < parameterCount) { 145 assertThrows(code, TypeError); 146 } else { 147 assertDoesNotThrow(code); 148 } 149 } 150 } 151 152 let calls = [ 153 `o.m.call()`, 154 `o.m.apply()`, 155 `o.m.apply(o)`, 156 ]; 157 for (let call of calls) { 158 let code = `'use strict'; ${def}; ${call};`; 159 if (parameterCount > 0) { 160 assertThrows(code, TypeError); 161 } else { 162 assertDoesNotThrow(code); 163 } 164 } 165 } 166 } 167 } 168 })(); 169 170 171 (function Constructor() { 172 for (let genParams of [generateParams, generateParamsWithRest]) { 173 for (let argumentCount = 0; argumentCount < 3; argumentCount++) { 174 for (let parameterCount = 0; parameterCount < 3; parameterCount++) { 175 let defs = [ 176 `'use strong'; 177 class C { constructor(${genParams(parameterCount)}) {} }`, 178 ]; 179 for (let def of defs) { 180 let calls = [ 181 `new C(${generateArguments(argumentCount)})`, 182 `new C(${generateSpread(argumentCount)})`, 183 `Reflect.construct(C, [${generateArguments(argumentCount)}])`, 184 ]; 185 for (let call of calls) { 186 let code = `${def}; ${call};`; 187 if (argumentCount < parameterCount) { 188 assertThrows(code, TypeError); 189 } else { 190 assertDoesNotThrow(code); 191 } 192 } 193 } 194 } 195 } 196 } 197 })(); 198 199 200 (function DerivedConstructor() { 201 for (let genParams of [generateParams, generateParamsWithRest]) { 202 for (let genArgs of [generateArguments, generateSpread]) { 203 for (let argumentCount = 0; argumentCount < 3; argumentCount++) { 204 for (let parameterCount = 0; parameterCount < 3; parameterCount++) { 205 let defs = [ 206 `'use strong'; 207 class B { 208 constructor(${genParams(parameterCount)}) {} 209 } 210 class C extends B { 211 constructor() { 212 super(${genArgs(argumentCount)}); 213 } 214 }`, 215 ]; 216 for (let def of defs) { 217 let code = `${def}; new C();`; 218 if (argumentCount < parameterCount) { 219 assertThrows(code, TypeError); 220 } else { 221 assertDoesNotThrow(code); 222 } 223 } 224 } 225 } 226 } 227 } 228 })(); 229 230 231 (function DerivedConstructorDefaultConstructorInDerivedClass() { 232 for (let genParams of [generateParams, generateParamsWithRest]) { 233 for (let genArgs of [generateArguments, generateSpread]) { 234 for (let argumentCount = 0; argumentCount < 3; argumentCount++) { 235 for (let parameterCount = 0; parameterCount < 3; parameterCount++) { 236 let defs = [ 237 `'use strong'; 238 class B { 239 constructor(${genParams(parameterCount)}) {} 240 } 241 class C extends B {}`, 242 ]; 243 for (let def of defs) { 244 let code = `${def}; new C(${genArgs(argumentCount)})`; 245 if (argumentCount < parameterCount) { 246 assertThrows(code, TypeError); 247 } else { 248 assertDoesNotThrow(code); 249 } 250 } 251 } 252 } 253 } 254 } 255 })(); 256 257 258 (function TestOptimized() { 259 function f(x, y) { 'use strong'; } 260 261 assertThrows(f, TypeError); 262 %OptimizeFunctionOnNextCall(f); 263 assertThrows(f, TypeError); 264 265 function g() { 266 f(1); 267 } 268 assertThrows(g, TypeError); 269 %OptimizeFunctionOnNextCall(g); 270 assertThrows(g, TypeError); 271 272 f(1, 2); 273 %OptimizeFunctionOnNextCall(f); 274 f(1, 2); 275 })(); 276 277 278 (function TestOptimized2() { 279 'use strong'; 280 function f(x, y) {} 281 282 assertThrows(f, TypeError); 283 %OptimizeFunctionOnNextCall(f); 284 assertThrows(f, TypeError); 285 286 function g() { 287 f(1); 288 } 289 assertThrows(g, TypeError); 290 %OptimizeFunctionOnNextCall(g); 291 assertThrows(g, TypeError); 292 293 f(1, 2); 294 %OptimizeFunctionOnNextCall(f); 295 f(1, 2); 296 })(); 297 298 299 (function TestOptimized3() { 300 function f(x, y) {} 301 function g() { 302 'use strong'; 303 f(1); 304 } 305 306 g(); 307 %OptimizeFunctionOnNextCall(f); 308 g(); 309 })(); 310 311 312 (function ParametersSuper() { 313 for (let genArgs of [generateArguments, generateSpread]) { 314 for (let argumentCount = 0; argumentCount < 3; argumentCount++) { 315 for (let parameterCount = 0; parameterCount < 3; parameterCount++) { 316 let defs = [ 317 `'use strict'; 318 class B { 319 m(${generateParams(parameterCount)} ){ 'use strong' } 320 }`, 321 `'use strong'; class B { m(${generateParams(parameterCount)}) {} }`, 322 ]; 323 for (let def of defs) { 324 let code = `${def}; 325 class D extends B { 326 m() { 327 super.m(${genArgs(argumentCount)}); 328 } 329 } 330 new D().m()`; 331 print('\n\n' + code); 332 if (argumentCount < parameterCount) { 333 assertThrows(code, TypeError); 334 } else { 335 assertDoesNotThrow(code); 336 } 337 } 338 } 339 } 340 } 341 })(); 342