|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 /* |
|
3 * Any copyright is dedicated to the Public Domain. |
|
4 * http://creativecommons.org/licenses/publicdomain/ |
|
5 */ |
|
6 |
|
7 var v="global"; |
|
8 function f(a) { |
|
9 // This eval could extend f's call object. However, the call object has |
|
10 // not yet been marked as a delegate at this point, so no scope chain |
|
11 // purge takes place when it is extended. |
|
12 eval(a); |
|
13 let (b=3) { |
|
14 // This eval causes the cloned block object to be added to the |
|
15 // scope chain. The block needs a unique shape: its parent call |
|
16 // could acquire bindings for anything without affecting the global |
|
17 // object's shape, so it's up to the block's shape to mismatch all |
|
18 // property cache entries for prior blocks. |
|
19 eval(""); |
|
20 return v; |
|
21 }; |
|
22 } |
|
23 |
|
24 // Call the function once, to cache a reference to the global v from within |
|
25 // f's lexical block. |
|
26 assertEq("global", f("")); |
|
27 |
|
28 // Call the function again, adding a binding to the call, and ensure that |
|
29 // we do not see any property cache entry created by the previous reference |
|
30 // that would direct us to the global definition. |
|
31 assertEq("local", f("var v='local'")); |
|
32 |
|
33 // Similarly,but with a doubly-nested block; make sure everyone gets marked. |
|
34 function f2(a) { |
|
35 eval(a); |
|
36 let (b=3) { |
|
37 let (c=4) { |
|
38 eval(""); |
|
39 return v; |
|
40 }; |
|
41 }; |
|
42 } |
|
43 |
|
44 assertEq("global", f2("")); |
|
45 assertEq("local", f2("var v='local'")); |
|
46 |
|
47 reportCompare(true, true); |