In what ways does the following "eval" regularity break?

Brendan Eich brendan at mozilla.com
Thu Oct 30 12:24:17 PDT 2008


On Oct 30, 2008, at 10:20 AM, Mark S. Miller wrote:

> On Thu, Oct 30, 2008 at 8:35 AM, Brendan Eich <brendan at mozilla.com>  
> wrote:
>> [...] Browser intersection semantics make indirect eval global, [...]
>
> I had hoped so. This came up at Redmond, and unfortunately, without
> either you or Lars there, I was unable to reconstruct why we thought
> it would be upwards compatible to make indirect eval global.

Probably when we started, we had the Firefox 1.0-1.5 behavior  
(JS1.5-1.6) in mind. Since then, elves "fixed" bugs. :-/

Still I do not know of web content that calls indirect eval and  
expects local eval. Gmail did (and may still) due to its cruncher do  
something like

var Ae = eval;... Ae(s)

but the program in string s wanted only global scope.


> The
> specification of indirect eval was also discussed in this morning's
> ES3.1 phone call. Based on the ES3 spec and a quick testing of the
> browsers, as well as the memory of those who had an opinion about this
> in Redmond, we've been proceeding with the assumption that the ES3
> spec should be read as:
>
> An implementation may implement an indirect eval either by throwing an
> EvalError or by treating it as equivalent to the eval operator.

This is not what we want, either as implementors or JS users.  
Implementors in particular have to deoptimize at runtime based on the  
eval built-in being invoked by some random name, in an environment  
that the compiler optimized assuming no eval call. Users cannot easily  
reason about hidden eval calls.


> Testing on FF3.0.3 and FF3.1Beta, with and without TraceMonkey
> enabled, seemed to bear this out:
>
>    function foo(a, b, c) { return b(c); }
>    foo(3, eval, 'a'); // yields 3
>    foo(3, window.eval, 'a'); // yields 3

Try Firefox 1 or 1.5. (Damn elves.... :-)

BTW, did you test V8?


> However, a bit more testing reveals something truly bizarre:
>
>    window.a = 'x';
>    foo(3, window.eval, 'a') // yields 'x'
>    foo(3, eval, 'a'); // yields 'x'
>
> I can't think of any semantics that would account for both behaviors.
> Is this a bug?

No, it is ancient pre-ECMA magic. The indirect case where eval was  
referenced from the global (window) object adds an implicit with  
(window). So

   return b(c);

becomes

   with (window) return eval('a');

We've kept compatibility here for over a decade, but we're more than  
willing to break it for a standard that says how indirect eval should  
work.

/be


More information about the Es-discuss mailing list