indirect eval spec too severe?

Brendan Eich brendan at
Sun Jan 18 20:47:14 PST 2009

On Jan 18, 2009, at 6:03 PM, Mark S. Miller wrote:

> A related difficulty, not addressed by the above spec, is shadowing.  
> Does the following program contain a direct call to eval (i.e., a  
> use of the "eval operator")?
>   function foo(eval, str) {
>     return eval(str);
>   }

I realize the spec may have challenges for want of "compile time" vs.  
"runtime" separation, but it's important to avoid overspecifying  
direct eval. Here's why.

Implementations should not have to analyze name bindings and flow- 
sensitive assignments. The standard approach is to check for a callee  
named 'eval' and emit a distinguished instruction which acts like the  
generic call instruction. The eval implementation can then interrogate  
the current instruction (if any) to see whether it was called via the  
"operator" form.

Since the implementation can tell when it has been called directly,  
the compiler can cooperate with the eval implementation and optimize  
aggressively any function body that does not contain such an 'eval'  
callee in a call expression, without having to do analysis beyond  
checking for a known identifer when parsing call expressions, and  
conditionally setting a flag inspected by a later pass (or doing fixup  
if one-pass and earlier assumptions were invalidated).

So the above eval call would be "apparently-direct", but at runtime,  
if foo is called with a funarg other than the global eva function as  
its first argument, then the call would be to some other function (or  
callable -- or an error for non-callabl first arg, of course).

Note that there's no way at runtime to change an apparently-direct  
eval into an indirect eval call. But an apparently-direct eval can  
turn into a plain old call.

> The eval variable being called here is not an alias for the "eval"  
> property of the global object, though it may or may not have the  
> same value. If the answer is that this is not a direct call,

That's the wrong answer -- it should be direct purely because the  
callee name is 'eval'.

> since the defining occurrence is local, then what about the second  
> "eval" in the following code?
>   function foo(str1, str2) {
>     eval(str1);
>     eval(str2);
>   }

Same answer -- these are two "direct" eval calls by the compiler's  

> Since foo may be called as foo('var eval = f', ..), the second eval  
> may refer to a local or to a global eval. These ambiguities defeat  
> the goal of distinguishing direct from indirect calls.

Not in practical implementations that nevertheless do no expensive  
analyasis, as sketched above.

> Though the above specific problem cannot occur if foo is strict, I  
> propose that, for all code, one may not define a local variable  
> named "eval".

This is unnecessary, and I'm not sure it's sufficient given your  
assumptions. But we shouldn't have to worry about any shadowing or  
rebinding issues if we can specify what popular implementations do.


More information about the Es-discuss mailing list