Rationale of indirect eval and its subtle features

Dmitry A. Soshnikov dmitry.soshnikov at gmail.com
Sat Feb 19 06:29:25 PST 2011


On 19.02.2011 3:13, Dmitry A. Soshnikov wrote:
> On 18.02.2011 20:04, Allen Wirfs-Brock wrote:
>> Here is another way to think about it.
>>
>> The built-in function object that is the initial value of the global 
>>  "eval"  (defined in 15.1.2.1) is a non-strict function. Hence 
>> anything it does defaults to "non-strict" and it uses the global 
>> environment as the VariableEnvironment for the code it evaluates. 
>>  However, if the argument code contains an use strict directive, then 
>> it uses a new child environment of the global environment as the 
>> VariableEnvironment.   This is all specific defined behavior of the 
>> built-in eval function object and is completely independent of who 
>> calls the function or how the caller accessed the function.
>>
>
> Yes, it's clear how it looks/implemented _technically_, however 
> doesn't explain a practical rationale. So at the moment I have the 
> following conclusion and understanding (please correct me if I'm 
> mistaken):
>
> An indirect `eval` introduced into ES spec not because of some/any 
> security reason (what I mentioned earlier in my explanations), and 
> even not because of some _practical_ reasons, but just because of 
> _complexity of the implementation_. I.e. _initially_ indirect `eval` 
> is related with the implementation level only (only after that JS devs 
> adapted this _technique_ for already mentioned getting of the global 
> object in strict mode).
>
> Is this explanation correct?
>
>> An "indirect eval" is any invocation of the above function.
>>
>
> This is a subtle case, thanks (taking into account your following 
> explanation of with the inlining the code to the call site). So, 
> _abstractly_ (? -- I can't say precisely whether it's _technically_ 
> though, since I'm not the implementer), if _syntactically_ we use this 
> form:
>
> eval(...)
>
> it isn't even an `eval` call, but just an inlining. I can imagine it 
> abstractly as (with providing a "sandbox" environment):
>
> (function foo() {
>   eval("var x = 10;")
> })();
>
> is _abstractly_ desugars (inline) into:
>
> (function foo() {
>   (function __directEval(configurableBindings?) {
>     var x = 10;
>   })(true);
> })();
>

Note: this abstract representation doesn't explain also dynamic eval's 
string. i.e. when some variable should be determined at runtime, when 
the environment is formed:

(function foo(x) {
   eval("var x = " + x + ";")
})(10);

How here the inlining can work?

> From this position it looks just an optimization technique. And if we 
> do this:
>
> var myEval = eval;
> myEval("var x = 10;");
>
> we already can't inline the `eval` at parsing stage (?), right? And if 
> we'd to pass the information about strictness of the surrounding 
> context, we just should pass additional argument the `myEval`, yep? 
> Though, I don't see which issue this passing of this additional 
> argument can lead (which by the way?).
>
>> A "direct eval" is essentially a special syntactic from in the ES5 
>> language with its own specific semantics. Some people have talked 
>> about it as the "eval" operator.  A direct eval does not call the 
>> built-in eval function object.  Instead, it has its own slightly 
>> different semantics that can be directly implemented at the call site.
>
> Yes, it was new for me (and for any JS dev I guess). And how it looks 
> I tried to describe above (is that understanding is correct?).
>
>>  These semantics include access to the immediately surrounding 
>> LexicalEnvironment and the propagation of strictness into the eval code.
>>
>
> Yep, if to accept the inheriting of the strictness by the inner 
> functions (with which I desugared the eval inlining).
>
> Thanks again, Allen, it seems clear now. But the main thing which I 
> found out from it, is that _initially_ it's _not about 
> JS-programming_, it's just an _optimization technique_ for the 
> _implementers_.
>
> Dmitry.
>
>> Allen
>>
>>
>> On Feb 18, 2011, at 4:52 AM, Dmitry A. Soshnikov wrote:
>>
>>> Have no idea what with mail sever again, there is no this message 
>>> there (links in message?). The original question is below:
>>>
>>> On 18.02.2011 11:51, Dmitry A. Soshnikov wrote:
>>>> Hello,
>>>>
>>>> As is known, indirect `eval` evaluates in the global context (this 
>>>> note is not for the TC-39 group of course, but for all other who 
>>>> read this list). But what is the big rationale of that indirect 
>>>> eval is allowed to create a global binding even _regardless_ the 
>>>> fact that the global code is _strict_?
>>>>
>>>> I.e.:
>>>>
>>>> "use strict";
>>>>
>>>> eval("var x = 10;"); // direct
>>>> this.eval("var y = 20;"); // indirect
>>>>
>>>> console.log(typeof x, typeof y); // "undefined", "number"
>>>>
>>>> The only _practical_ rationale of the indirect `eval` regarding the 
>>>> strict mode is that via its call it's possible to get the global 
>>>> object via `this` value from any place (since just returning `this` 
>>>> won't work as it's set to `undefined` in a simple function call):
>>>>
>>>> var global = (function () { return this; })(); // ES3, non-strict 
>>>> ES5 way
>>>>
>>>> var global = ("indirect", eval)("this"); // strict ES5
>>>>
>>>> Which else practical/theoretical/academical rationales of the 
>>>> indirect eval are? And what again the rationale that it's allowed 
>>>> to create the global binding (i.e. not in the "sandbox" 
>>>> environment, but reusing `VariableEnvironment` of the "caller" -- 
>>>> not a direct caller though, but the adjusted -- the global scope)? 
>>>> Could you clarify this, I want to give a more concrete explanations 
>>>> for my readers.
>>>>
>>>> P.S.:
>>>>
>>>> Just recently Allen brought a good addition (well, a reminder even 
>>>> better to say, since I also wanted to add it ;) to mention this 
>>>> subtle case with indirect eval and it's ability to affect the 
>>>> global environment regardless the strict mode: 
>>>> http://dmitrysoshnikov.com/ecmascript/es5-chapter-2-strict-mode/#comment-5831
>>>>
>>>> It's without doubts a very needed addition and as is said -- a 
>>>> subtle case, but still -- what are the exact rationales for that? I 
>>>> mentioned this case in Allen's blog before, and though that this is 
>>>> a bug of the spec -- 
>>>> http://www.wirfs-brock.com/allen/posts/39#comment-46
>>>>
>>>> Allen answered that this is related with complexity of 
>>>> implementation, here:
>>>>
>>>> "An /indirect/ eval called from strict code is strict only if the 
>>>> eval code explicit contains an “use strict;” directive. It does not 
>>>> “inherit” the strictness of its caller.
>>>>
>>>> Every call is potentially an indirect eval call. If the strictness 
>>>> of indirect evals depended upon the strictness of the caller then 
>>>> we would have to pass the strictness of the caller through every 
>>>> call. That would require either an extra implicit parameter on 
>>>> every call or the ability to a callee to examine the call stack to 
>>>> to determine the strictness of its caller. We don’t want to force 
>>>> this on implementations."
>>>>
>>>> The basic idea is seems clear -- we need to pass a flag that the 
>>>> code of an inner function (from which indirect `eval` was called) 
>>>> is strict, but if the _global_ code is strict -- and indirect 
>>>> `eval` always evaluates in the global context, and moreover, if the 
>>>> global code is strict that means _any_ inner function (except those 
>>>> which are created via `Function` constructor and have no own 
>>>> strictness) is automatically also strict:
>>>>
>>>> "use strict";
>>>>
>>>> (function foo() {
>>>>   // this code is also strict
>>>>   ("indirect", eval)("var x = 10;");
>>>> })();
>>>>
>>>> console.log(x); // 10
>>>>
>>>> is it also required to pass special flags to handle this case?
>>>>
>>>> Thanks,
>>>> Dmitry.
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org <mailto:es-discuss at mozilla.org>
>>> https://mail.mozilla.org/listinfo/es-discuss
>>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110219/a4690b19/attachment-0001.html>


More information about the es-discuss mailing list