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