indirect eval spec too severe?

Mark S. Miller erights at google.com
Sun Jan 18 12:47:43 PST 2009


The Mountain View draft says:


> 15.1.2    Function Properties of the Global Object
> 15.1.2.1    eval (x)
> When the eval function is called with one argument x, the following steps
> are taken:
> [...]
> If the value of the eval property is used in any way other than a direct
> call (that is, other than by the explicit use of its name as an Identifier
> which is the MemberExpression in a CallExpression), or if the eval property
> is assigned to, an EvalError exception may be thrown.
>
> 15.1.2.1.1    Strict Mode Restrictions
> If strict mode code uses the value of the eval property any way other than
> as a direct call (that is, other than by the explicit use of its name as an
> Identifier which is the MemberExpression in a CallExpression), or if the
> eval property is assigned to, an EvalError exception is thrown.
>


I believe this spec is too severe, both for nonstrict and strict code. My
sense of the committee consensus is that an indirect eval call should be
unconditionally allowed, in which case the execution context should be the
global execution context, as already adequately specified in 10.4.2. (In the
committee's conversations, we've referred to the "direct calls" of the spec
language as the "eval operator", and the spec's "indirect calls" as the
"eval function". I'm happy with either terminology.)

As for restrictions on assignment to "eval", so long as the global "eval"
might be assigned by nonstrict code, it doesn't help much to prevent it's
assignment by strict code. Rather, in a "frame" (global object context) in
which we wish to prevent assignment of global "eval", one can
Object.defineProperty(window,
"eval", {writable: false, configurable: false}), preventing anyone from
assigning it.

Given

    var x = 5;
    function foo(str) {
      var x = 8;
      function bar() {
        eval(str);
        x = x*x;
      }
      bar();
      return x;
    }

and that eval has it's original value, then

    foo('');                        // returns 16
    foo('var x = 7');               // returns 8, since 14 is assigned to
bar's x
    foo('"use strict; var x = 7;'); // returns 16
    foo('x = 7;');                  // returns 14
    foo('"use strict"; x = 7;');    // returns 14
    // in all cases, global x is unaffected

whereas

    var x = 5;
    function foo(str) {
      var x = 8;
      function bar() {
        "use strict";
        eval(str);
        x = x*x;
      }
      bar();
      return x;
    }

    foo('');                        // returns 16
    foo('var x = 7');               // returns 16
    foo('"use strict; var x = 7;'); // returns 16
    foo('x = 7;');                  // returns 14
    foo('"use strict"; x = 7;');    // returns 14
    // in all cases, global x is unaffected

and

    var x = 5;
    function foo(str) {
      var x = 8;
      function bar() {
        (true && eval)(str);
        x = x*x;
      }
      bar();
      return x;
    }

    foo('');                        // global x in unaffected
    foo('var x = 7');               // sets global x to 7
    foo('"use strict; var x = 7;'); // sets global x to 7
    foo('x = 7;');                  // sets global x to 7
    foo('"use strict"; x = 7;');    // sets global x to 7
    // in all cases, return 16

For these latter cases, it should make no difference whether bar() is
strict.

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


More information about the Es-discuss mailing list