michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* michael@0: * Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/licenses/publicdomain/ michael@0: */ michael@0: michael@0: var v="global"; michael@0: function f(a) { michael@0: // This eval could extend f's call object. However, the call object has michael@0: // not yet been marked as a delegate at this point, so no scope chain michael@0: // purge takes place when it is extended. michael@0: eval(a); michael@0: let (b=3) { michael@0: // This eval causes the cloned block object to be added to the michael@0: // scope chain. The block needs a unique shape: its parent call michael@0: // could acquire bindings for anything without affecting the global michael@0: // object's shape, so it's up to the block's shape to mismatch all michael@0: // property cache entries for prior blocks. michael@0: eval(""); michael@0: return v; michael@0: }; michael@0: } michael@0: michael@0: // Call the function once, to cache a reference to the global v from within michael@0: // f's lexical block. michael@0: assertEq("global", f("")); michael@0: michael@0: // Call the function again, adding a binding to the call, and ensure that michael@0: // we do not see any property cache entry created by the previous reference michael@0: // that would direct us to the global definition. michael@0: assertEq("local", f("var v='local'")); michael@0: michael@0: // Similarly,but with a doubly-nested block; make sure everyone gets marked. michael@0: function f2(a) { michael@0: eval(a); michael@0: let (b=3) { michael@0: let (c=4) { michael@0: eval(""); michael@0: return v; michael@0: }; michael@0: }; michael@0: } michael@0: michael@0: assertEq("global", f2("")); michael@0: assertEq("local", f2("var v='local'")); michael@0: michael@0: reportCompare(true, true);