OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Test Annex B 3.3 semantics for functions declared in blocks in sloppy mode. | 5 // Test Annex B 3.3 semantics for functions declared in blocks in sloppy mode. |
6 // http://www.ecma-international.org/ecma-262/6.0/#sec-block-level-function-decl
arations-web-legacy-compatibility-semantics | 6 // http://www.ecma-international.org/ecma-262/6.0/#sec-block-level-function-decl
arations-web-legacy-compatibility-semantics |
7 | 7 |
8 (function overridingLocalFunction() { | 8 (function overridingLocalFunction() { |
9 var x = []; | 9 var x = []; |
10 assertEquals('function', typeof f); | 10 assertEquals('function', typeof f); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 let y = 3; | 102 let y = 3; |
103 function f() { | 103 function f() { |
104 y = 2; | 104 y = 2; |
105 } | 105 } |
106 f(); | 106 f(); |
107 assertEquals(2, y); | 107 assertEquals(2, y); |
108 } | 108 } |
109 assertEquals('function', typeof f); | 109 assertEquals('function', typeof f); |
110 })(); | 110 })(); |
111 | 111 |
| 112 (function complexParams(a = 0) { |
| 113 { |
| 114 let y = 3; |
| 115 function f(b = 0) { |
| 116 y = 2; |
| 117 } |
| 118 f(); |
| 119 assertEquals(2, y); |
| 120 } |
| 121 assertEquals('function', typeof f); |
| 122 })(); |
| 123 |
| 124 (function complexVarParams(a = 0) { |
| 125 var f; |
| 126 { |
| 127 let y = 3; |
| 128 function f(b = 0) { |
| 129 y = 2; |
| 130 } |
| 131 f(); |
| 132 assertEquals(2, y); |
| 133 } |
| 134 assertEquals('function', typeof f); |
| 135 })(); |
| 136 |
112 (function conditional() { | 137 (function conditional() { |
113 if (true) { | 138 if (true) { |
114 function f() { return 1; } | 139 function f() { return 1; } |
115 } else { | 140 } else { |
116 function f() { return 2; } | 141 function f() { return 2; } |
117 } | 142 } |
118 assertEquals(1, f()); | 143 assertEquals(1, f()); |
119 | 144 |
120 if (false) { | 145 if (false) { |
121 function g() { return 1; } | 146 function g() { return 1; } |
(...skipping 13 matching lines...) Expand all Loading... |
135 } | 160 } |
136 assertEquals(2, f()); | 161 assertEquals(2, f()); |
137 L: { | 162 L: { |
138 assertEquals(3, f()); | 163 assertEquals(3, f()); |
139 break L; | 164 break L; |
140 function f() { return 3; } | 165 function f() { return 3; } |
141 } | 166 } |
142 assertEquals(2, f()); | 167 assertEquals(2, f()); |
143 })(); | 168 })(); |
144 | 169 |
| 170 (function executionOrder() { |
| 171 function getOuter() { |
| 172 return f; |
| 173 } |
| 174 assertEquals('undefined', typeof getOuter()); |
| 175 |
| 176 { |
| 177 assertEquals('function', typeof f); |
| 178 assertEquals('undefined', typeof getOuter()); |
| 179 function f () {} |
| 180 assertEquals('function', typeof f); |
| 181 assertEquals('function', typeof getOuter()); |
| 182 } |
| 183 |
| 184 assertEquals('function', typeof getOuter()); |
| 185 })(); |
| 186 |
| 187 (function reassignBindings() { |
| 188 function getOuter() { |
| 189 return f; |
| 190 } |
| 191 assertEquals('undefined', typeof getOuter()); |
| 192 |
| 193 { |
| 194 assertEquals('function', typeof f); |
| 195 assertEquals('undefined', typeof getOuter()); |
| 196 f = 1; |
| 197 assertEquals('number', typeof f); |
| 198 assertEquals('undefined', typeof getOuter()); |
| 199 function f () {} |
| 200 assertEquals('number', typeof f); |
| 201 assertEquals('number', typeof getOuter()); |
| 202 f = ''; |
| 203 assertEquals('string', typeof f); |
| 204 assertEquals('number', typeof getOuter()); |
| 205 } |
| 206 |
| 207 assertEquals('number', typeof getOuter()); |
| 208 })(); |
| 209 |
145 // Test that shadowing arguments is fine | 210 // Test that shadowing arguments is fine |
146 (function shadowArguments(x) { | 211 (function shadowArguments(x) { |
147 assertArrayEquals([1], arguments); | 212 assertArrayEquals([1], arguments); |
148 { | 213 { |
149 assertEquals('function', typeof arguments); | 214 assertEquals('function', typeof arguments); |
150 function arguments() {} | 215 function arguments() {} |
151 assertEquals('function', typeof arguments); | 216 assertEquals('function', typeof arguments); |
152 } | 217 } |
153 assertEquals('function', typeof arguments); | 218 assertEquals('function', typeof arguments); |
154 })(1); | 219 })(1); |
155 | 220 |
156 // Shadow function parameter | 221 |
157 (function shadowParameter(x) { | 222 // Don't shadow simple parameter |
158 assertEquals(1, x); | 223 (function shadowingParameterDoesntBind(x) { |
159 { | 224 assertEquals(1, x); |
160 function x() {} | 225 { |
161 } | 226 function x() {} |
162 assertEquals('function', typeof x); | 227 } |
163 })(1); | 228 assertEquals(1, x); |
164 | 229 })(1); |
165 // Shadow function parameter | 230 |
166 (function shadowDefaultParameter(x = 0) { | 231 // Don't shadow complex parameter |
167 assertEquals(1, x); | 232 (function shadowingDefaultParameterDoesntBind(x = 0) { |
168 { | 233 assertEquals(1, x); |
169 function x() {} | 234 { |
170 } | 235 function x() {} |
171 // TODO(littledan): Once destructured parameters are no longer | 236 } |
172 // let-bound, enable this assertion. This is the core of the test. | 237 assertEquals(1, x); |
173 // assertEquals('function', typeof x); | 238 })(1); |
174 })(1); | 239 |
175 | 240 // Don't shadow nested complex parameter |
176 (function shadowRestParameter(...x) { | 241 (function shadowingNestedParameterDoesntBind([[x]]) { |
177 assertArrayEquals([1], x); | 242 assertEquals(1, x); |
178 { | 243 { |
179 function x() {} | 244 function x() {} |
180 } | 245 } |
181 // TODO(littledan): Once destructured parameters are no longer | 246 assertEquals(1, x); |
182 // let-bound, enable this assertion. This is the core of the test. | 247 })([[1]]); |
183 // assertEquals('function', typeof x); | 248 |
184 })(1); | 249 // Don't shadow rest parameter |
185 | 250 (function shadowingRestParameterDoesntBind(...x) { |
186 assertThrows(function notInDefaultScope(x = y) { | 251 assertArrayEquals([1], x); |
187 { | 252 { |
188 function y() {} | 253 function x() {} |
189 } | 254 } |
190 assertEquals('function', typeof y); | 255 assertArrayEquals([1], x); |
191 assertEquals(x, undefined); | 256 })(1); |
192 }, ReferenceError); | 257 |
| 258 // Don't shadow complex rest parameter |
| 259 (function shadowingComplexRestParameterDoesntBind(...[x]) { |
| 260 assertArrayEquals(1, x); |
| 261 { |
| 262 function x() {} |
| 263 } |
| 264 assertArrayEquals(1, x); |
| 265 })(1); |
| 266 |
| 267 // Previous tests with a var declaration thrown in. |
| 268 // Don't shadow simple parameter |
| 269 (function shadowingVarParameterDoesntBind(x) { |
| 270 var x; |
| 271 assertEquals(1, x); |
| 272 { |
| 273 function x() {} |
| 274 } |
| 275 assertEquals(1, x); |
| 276 })(1); |
| 277 |
| 278 // Don't shadow complex parameter |
| 279 (function shadowingVarDefaultParameterDoesntBind(x = 0) { |
| 280 var x; |
| 281 assertEquals(1, x); |
| 282 { |
| 283 function x() {} |
| 284 } |
| 285 assertEquals(1, x); |
| 286 })(1); |
| 287 |
| 288 // Don't shadow nested complex parameter |
| 289 (function shadowingVarNestedParameterDoesntBind([[x]]) { |
| 290 var x; |
| 291 assertEquals(1, x); |
| 292 { |
| 293 function x() {} |
| 294 } |
| 295 assertEquals(1, x); |
| 296 })([[1]]); |
| 297 |
| 298 // Don't shadow rest parameter |
| 299 (function shadowingVarRestParameterDoesntBind(...x) { |
| 300 var x; |
| 301 assertArrayEquals([1], x); |
| 302 { |
| 303 function x() {} |
| 304 } |
| 305 assertArrayEquals([1], x); |
| 306 })(1); |
| 307 |
| 308 // Don't shadow complex rest parameter |
| 309 (function shadowingVarComplexRestParameterDoesntBind(...[x]) { |
| 310 var x; |
| 311 assertArrayEquals(1, x); |
| 312 { |
| 313 function x() {} |
| 314 } |
| 315 assertArrayEquals(1, x); |
| 316 })(1); |
| 317 |
| 318 |
| 319 // Hoisting is not affected by other simple parameters |
| 320 (function irrelevantParameterBinds(y, z) { |
| 321 assertEquals(undefined, x); |
| 322 { |
| 323 function x() {} |
| 324 } |
| 325 assertEquals('function', typeof x); |
| 326 })(1); |
| 327 |
| 328 // Hoisting is not affected by other complex parameters |
| 329 (function irrelevantComplexParameterBinds([y] = [], z) { |
| 330 assertEquals(undefined, x); |
| 331 { |
| 332 function x() {} |
| 333 } |
| 334 assertEquals('function', typeof x); |
| 335 })(); |
| 336 |
| 337 // Hoisting is not affected by rest parameters |
| 338 (function irrelevantRestParameterBinds(y, ...z) { |
| 339 assertEquals(undefined, x); |
| 340 { |
| 341 function x() {} |
| 342 } |
| 343 assertEquals('function', typeof x); |
| 344 })(); |
| 345 |
| 346 // Hoisting is not affected by complex rest parameters |
| 347 (function irrelevantRestParameterBinds(y, ...[z]) { |
| 348 assertEquals(undefined, x); |
| 349 { |
| 350 function x() {} |
| 351 } |
| 352 assertEquals('function', typeof x); |
| 353 })(); |
| 354 |
| 355 |
| 356 // Test that shadowing function name is fine |
| 357 { |
| 358 let called = false; |
| 359 (function shadowFunctionName() { |
| 360 if (called) assertUnreachable(); |
| 361 called = true; |
| 362 { |
| 363 function shadowFunctionName() { |
| 364 return 0; |
| 365 } |
| 366 assertEquals(0, shadowFunctionName()); |
| 367 } |
| 368 assertEquals(0, shadowFunctionName()); |
| 369 })(); |
| 370 } |
| 371 |
| 372 { |
| 373 let called = false; |
| 374 (function shadowFunctionNameWithComplexParameter(...r) { |
| 375 if (called) assertUnreachable(); |
| 376 called = true; |
| 377 { |
| 378 function shadowFunctionNameWithComplexParameter() { |
| 379 return 0; |
| 380 } |
| 381 assertEquals(0, shadowFunctionNameWithComplexParameter()); |
| 382 } |
| 383 assertEquals(0, shadowFunctionNameWithComplexParameter()); |
| 384 })(); |
| 385 } |
| 386 |
| 387 (function shadowOuterVariable() { |
| 388 { |
| 389 let f = 0; |
| 390 (function () { |
| 391 assertEquals(undefined, f); |
| 392 { |
| 393 assertEquals(1, f()); |
| 394 function f() { return 1; } |
| 395 assertEquals(1, f()); |
| 396 } |
| 397 assertEquals(1, f()); |
| 398 })(); |
| 399 assertEquals(0, f); |
| 400 } |
| 401 })(); |
| 402 |
| 403 (function notInDefaultScope() { |
| 404 var y = 1; |
| 405 (function innerNotInDefaultScope(x = y) { |
| 406 assertEquals('undefined', typeof y); |
| 407 { |
| 408 function y() {} |
| 409 } |
| 410 assertEquals('function', typeof y); |
| 411 assertEquals(1, x); |
| 412 })(); |
| 413 })(); |
| 414 |
| 415 (function noHoistingThroughNestedLexical() { |
| 416 { |
| 417 let f = 2; |
| 418 { |
| 419 let y = 3; |
| 420 function f() { |
| 421 y = 2; |
| 422 } |
| 423 f(); |
| 424 assertEquals(2, y); |
| 425 } |
| 426 assertEquals(2, f); |
| 427 } |
| 428 assertThrows(()=>f, ReferenceError); |
| 429 })(); |
| 430 |
| 431 // Only the first function is hoisted; the second is blocked by the first. |
| 432 // Contrast overridingLocalFunction, in which the outer function declaration |
| 433 // is not lexical and so the inner declaration is hoisted. |
| 434 (function noHoistingThroughNestedFunctions() { |
| 435 assertEquals(undefined, f); // Also checks that the var-binding exists |
| 436 |
| 437 { |
| 438 assertEquals(4, f()); |
| 439 |
| 440 function f() { |
| 441 return 4; |
| 442 } |
| 443 |
| 444 { |
| 445 assertEquals(5, f()); |
| 446 function f() { |
| 447 return 5; |
| 448 } |
| 449 assertEquals(5, f()); |
| 450 } |
| 451 |
| 452 assertEquals(4, f()); |
| 453 } |
| 454 |
| 455 assertEquals(4, f()); |
| 456 })(); |
193 | 457 |
194 // Test that hoisting from blocks does happen in global scope | 458 // Test that hoisting from blocks does happen in global scope |
195 function globalHoisted() { return 0; } | 459 function globalHoisted() { return 0; } |
196 { | 460 { |
197 function globalHoisted() { return 1; } | 461 function globalHoisted() { return 1; } |
198 } | 462 } |
199 assertEquals(1, globalHoisted()); | 463 assertEquals(1, globalHoisted()); |
200 | 464 |
201 // Also happens when not previously defined | 465 // Also happens when not previously defined |
202 assertEquals(undefined, globalUndefinedHoisted); | 466 assertEquals(undefined, globalUndefinedHoisted); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 throws = false; | 553 throws = false; |
290 try { | 554 try { |
291 eval('{ function hoistWhenFrozen() {} }'); | 555 eval('{ function hoistWhenFrozen() {} }'); |
292 } catch (e) { | 556 } catch (e) { |
293 throws = true; | 557 throws = true; |
294 } | 558 } |
295 assertFalse(this.hasOwnProperty("hoistWhenFrozen")); | 559 assertFalse(this.hasOwnProperty("hoistWhenFrozen")); |
296 assertThrows(() => hoistWhenFrozen, ReferenceError); | 560 assertThrows(() => hoistWhenFrozen, ReferenceError); |
297 // Should be assertFalse BUG(v8:4452) | 561 // Should be assertFalse BUG(v8:4452) |
298 assertTrue(throws); | 562 assertTrue(throws); |
OLD | NEW |