Why does EcmaScript 5 strict mode go to such great lengths to restrict the identifier `eval`

According to the spec (Annex C), strict-mode code can't do pretty much anything that might assign any identifier with the name eval. I can understand that one might want to restrict use of the actual eval function, but I don't see what purpose is served by restricting use of the name?

Answers:

Answer

I can only speculate, but it seems to me that ES5-strict is saying that eval and arguments should be considered as raw syntax, not identifiers. It is reasonable that these two features should be implemented at the syntactical level, because they have Amazing Funky Magic behaviours that cannot be reproduced by a normal function.

(In particular eval may write to local variables in the function that calls it, and writing to arguments bizarrely changes the values of local variables corresponding to the arguments. Though this behaviour seems to be going away in strict mode, thankfully.)

For compatibility reasons, ES5 can't actually make eval and arguments syntactical. So they do the nearest they can, which is to say that the identifier arguments always refers to arguments magic and the identifier eval always exclusively refers to eval magic.

It could also improve the possibilities for optimisation, if JS engines can be sure whether a function contains magic.

Answer

bobince is basically correct. (I work on SpiderMonkey, Mozilla's JS engine, have implemented various parts of ES5 in it, and follow ECMAScript discussions as time permits.) You (implementers and readers both) really do want eval to be the canonical eval, and you want arguments to be the canonical arguments. Using strict mode you can mostly get this.

But I will point out that ES5's restrictions here are not as much as would be desirable. First, and to correct bobince slightly, even with strict mode you can't be sure eval is the original eval function:

"use strict";
this.eval = function() { return "ohai"; };
eval("7 + 10"); // "ohai"

This is the well-known (among JS aficionados) global object mistake: that scripts use a global object, shared across scripts, nameable and modifiable, to resolve names. If you couldn't refer to the object where global variables are bound, you wouldn't have this problem. It's likely ES6 will fix this through another opt-in system (possibly out-of-band like a MIME type, but that's unclear yet) always scoped to entire scripts.

But even without the nameable, mutable global object, you still have problems because strict mode can be scoped to functions:

function outer()
{
  var eval = function() { return "kthxbai"; };
  function inner()
  {
    "use strict";
    return eval("2 + 5");
  }
  return inner();
}
outer(); // "kthxbai"

These problems exist even in the presence of strict mode, and they won't go away until ES6 at the earliest, as it will probably remove the global object and unconditionally enforce strict mode restrictions.

So eval in strict mode is still a little weird in that it can refer to not-eval. But handling that is no big deal -- at runtime the implementation can check for the real eval and if that fails just do what it'd do if the syntax happened to use a name other than eval. This requires that an expression like eval(...) be handled specially. But any good implementation did that anyway, because of eval's non-statically-observable behavior (mutating local variables and arguments, introducing new variables [now de-fanged in strict mode -- variable declarations in strict mode eval code are local to the eval code], and so on), so it's no real burden.

It's worth noting none of this applies to arguments as a fake special form. Either you have strict mode by way of a function scope, in which case you'd see that function's arguments rather than arguments assigned in an outer scope, or you have it by way of a global scope, in which case arguments has no special behavior. (Why forbid mutation of arguments in global strict mode code? Probably simplicity, plus forcing developers to treat them as more of a special form everywhere, but I'm not certain.)

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.