Strict mode eval

Mark S. Miller erights at google.com
Thu May 12 16:50:06 PDT 2011


On Thu, May 12, 2011 at 2:08 AM, Andreas Rossberg <rossberg at google.com>wrote:
[...]

>
> Assume that
>
> - we distinguish two variants of the eval function, strict and
> non-strict -- let's call these values EVAL_s and EVAL_ns.
> - initially (in global scope), the identifier `eval' is bound to EVAL_ns.
> - in a strict mode scope it will be considered rebound to EVAL_s
> instead (unless it has already been shadowed by user code anyway).
>
> (In addition, at least in strict mode, the only calls to `eval' that
> are considered _direct_ calls would be those where `eval' statically
> refers to the initial binding or one of the implicit strict-mode
> rebindings -- i.e., where it has not been shadowed by the user.)
>

I think the core insight here is good, and had it been made in time, could
have led to a better semantics than what we adopted into ES5. I like the
idea that ' "use strict";' effectively inserts a
DeclarativeEnvironmentRecord binding 'eval' to EVAL_s, though I'd put this
record on the stack at the strict/non-strict boundary rather than just above
the global object. IIRC, no one has previous suggested anything remotely
like this. Of course, it's too late to fix ES5, but perhaps we can still
apply your insights to improve the eval situation in ES-next and SES.

This should be doable because both ES-next and SES effectively remove the
global object from the bottom of the scope chain and prevent local rebinding
of 'eval'. Thus the outer binding for eval in scope for ES-next and SES code
can differ from window.eval. SES-on-ES5 does this already, but at the cost
of breaking direct eval inside SES code, since 'eval' in that code no longer
has its original binding to EVAL_ns.

The key to preserving direct eval is your next insight above: that the set
of such built-in eval variants form some kind of equivalence class, so that
an apparent direct eval call is actually a direct eval call if its binding
for 'eval' is any of the eval functions in that equivalence class.

Even better, since 'eval' cannot be rebound by ES5/strict, ES-next, or SES
code, and since "eval(str)" is effectively a special form anyway, why not
remove the dynamic "and if 'eval' is bound to the original global eval
function" condition from direct eval? Why not just treat "eval(str)" as a
direct eval special form independent of what 'eval' is bound to in that
scope? Then, module loaders could be used to introduce different top level
bindings for 'eval', as used for indirect eval calls, without breaking the
direct eval special form.

The one downside is an extra burden on source-to-source rewriters: they
would also need to rewrite the direct eval call 'eval(str)' into
approximately 'eval(rewrite(str))', which requires that the rewriter itself
be written in JavaScript and downloaded to the client. Given how large a
parser needs to be to accurately parse JavaScript, this is an unfortunate
burden. Despite this burden, I think we should consider removing this
dynamic condition from the ES-next direct eval special form.


> In your example, the `eval' identifier is already shadowed by the
> function parameter, so the inner "use strict" would have no effect on
> it -- in that scope `eval' is just an ordinary identifier.
> Consequently, all 3 examples would behave alike and are non-direct
> calls. Whether strict or not solely depends on what you pass in to f:
>
>  // non-strict scope
>  f(eval)   // EVAL_ns
>  (function() { "use strict"; f(eval) })()  // EVAL_s
>  f((function() { "use strict"; return eval })())  // EVAL_s
>
> Does that make sense? The idea is that strict/non-strict is resolved
> w.r.t. the static scope where the identifier `eval' occurs. With this
> semantics, there would be no way in strict mode to access non-strict
> eval, unless it is explicitly provided by someone. With the current
> rules that is not the case, because you can easily defeat strict mode
> by a random indirection, e.g.:
>
>  "use strict";
>  var e = eval
>  e("var oops = 666")  // pollutes the global object, although the
> whole program is in strict mode
>
> I'm not sure whether that was intentional or not, but it feels strange.
>
> /Andreas
>



-- 
    Cheers,
    --MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110512/1b03be24/attachment.html>


More information about the es-discuss mailing list