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);
})();
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
[email protected] <mailto:[email protected]>
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss