| <p> | |
| This page verifies that eval has two meanings: | |
| <ol> | |
| <li>An operator: executes a script in local scope with the local scope's variable object and "this" object.</li> | |
| <li>A global function: executes a script in global scope with the global scope's variable object and "this" object.</li> | |
| </ol> | |
| Meaning #2 should remain constant even if the global eval function is copied | |
| into a global variable ("globalEval") or a local variable ("localEval"). | |
| </p> | |
| <p>If the test passes, you'll see a series of pass messages below.</p> | |
| <hr> | |
| <pre id="console"></pre> | |
| <script> | |
| if (window.testRunner) | |
| testRunner.dumpAsText(); | |
| var globalEval = eval; | |
| function log(s) | |
| { | |
| document.getElementById("console").appendChild(document.createTextNode(s + "\n")); | |
| } | |
| function shouldBe(aDescription, a, b) | |
| { | |
| if (a === b) { | |
| log("PASS: " + aDescription + " should be " + b + " and is."); | |
| } else { | |
| log("FAIL: " + aDescription + " should be " + b + " but instead is " + a + "."); | |
| } | |
| } | |
| function testGetX() | |
| { | |
| var x = 1; | |
| var localEval = window.eval; | |
| window.x = 0; | |
| shouldBe('eval("x")', eval("x"), 1); | |
| shouldBe('window.eval("x")', window.eval("x"), 0); | |
| shouldBe('globalEval("x")', globalEval("x"), 0); | |
| shouldBe('localEval("x")', localEval("x"), 0); | |
| // Per ES5 15.1.2.11 & 10.2.2.1 any reference that hits an enviromment record (i.e. does not have a base) | |
| // and has a reference name of "eval" is treated as a direct eval - the assignment to a var makes no difference. | |
| shouldBe('(function() { var eval = window.eval; return eval("x"); })()', (function() { var eval = window.eval; return eval("x"); })(), 1); | |
| } | |
| function testVarY() | |
| { | |
| var localEval = window.eval; | |
| shouldBe('eval("var y; \"y\" in window")', eval("var y; \"y\" in window"), false); | |
| delete window.y; | |
| shouldBe('window.eval("var y; \"y\" in window")', window.eval("var y; \"y\" in window"), true); | |
| delete window.y; | |
| shouldBe('globalEval("var y; \"y\" in window")', globalEval("var y; \"y\" in window"), true); | |
| delete window.y; | |
| shouldBe('localEval("var y; \"y\" in window")', localEval("var y; \"y\" in window"), true); | |
| delete window.y; | |
| // Per ES5 15.1.2.11 & 10.2.2.1 any reference that hits an enviromment record (i.e. does not have a base) | |
| // and has a reference name of "eval" is treated as a direct eval - the assignment to a var makes no difference. | |
| shouldBe('(function() { var eval = window.eval; return eval("var y; \"y\" in window"); })()', (function() { var eval = window.eval; return eval("var y; \"y\" in window"); })(), false); | |
| } | |
| function testSetZ() | |
| { | |
| var z = 0; | |
| window.z = 0; | |
| var localEval = window.eval; | |
| shouldBe('eval("z = 1; window.z")', eval("z = 1; window.z"), 0); | |
| shouldBe('window.eval("z = 2; window.z")', window.eval("z = 2; window.z"), 2); | |
| shouldBe('globalEval("z = 3; window.z")', globalEval("z = 3; window.z"), 3); | |
| shouldBe('localEval("z = 4; window.z")', localEval("z = 4; window.z"), 4); | |
| // Per ES5 15.1.2.11 & 10.2.2.1 any reference that hits an enviromment record (i.e. does not have a base) | |
| // and has a reference name of "eval" is treated as a direct eval - the assignment to a var makes no difference. | |
| shouldBe('(function() { var eval = window.eval; return eval("z = 5; window.z"); })()', (function() { var eval = window.eval; return eval("z = 5; window.z"); })(), 4); | |
| } | |
| function testThis() | |
| { | |
| var localEval = window.eval; | |
| shouldBe('eval("this")', eval("this"), this); | |
| shouldBe('window.eval("this")', window.eval("this"), window); | |
| shouldBe('globalEval("this")', globalEval("this"), window); | |
| shouldBe('localEval("this")', localEval("this"), window); | |
| shouldBe('(function() { var eval = window.eval; return eval("this"); })()', (function() { var eval = window.eval; return eval("this"); })(), window); | |
| } | |
| log("\n----- Scope Chain for Getters: -----\n"); | |
| testGetX(); | |
| log("\n----- Variable Object: -----\n"); | |
| testVarY(); | |
| log("\n----- Scope Chain for Setters: -----\n"); | |
| testSetZ(); | |
| log("\n----- This Object: -----\n"); | |
| testThis.call({ toString: function() { return "[\"this\" object passed to .call()]"; } }); | |
| </script> |