block scope + direct non-strict eval
Brendan Eich
brendan at mozilla.org
Tue Jan 31 11:20:39 PST 2012
Allen Wirfs-Brock wrote:
> To further clarify, consider this valid ES5 code that must continue to produce the same result in ES6 :
>
> function f(condition,body1,body2) {
> if (condition) {
> var code = "function f() {+body1+"}";
> eval(code);
> } else {
> var code = "function f() {+body2+"}";
> eval(code);
> }
> f();
> }
We are talking about taking the variant of this code that removes the
eval calls by declaring functions in blocks, and breaking it. True, the
two are different cases. But the reason we hope we can break
function f(condition,val1,val2) {
if (condition) {
function f() { return val1; }
} else {
function f() { return val2; }
}
f();
}
is because it does not have interoperable semantics across major
browsers. When we banned function-in-block in ES5 strict, we did find
code that had "use strict"; prematurely applied before ES5-strict
implementations were available for testing, or applied via concatenation
of scripts. All such function in block cases were sane:
function f(condition,val1,val2) {
if (condition) {
function f() { return val1; }
val2 = f();
}
return val2;
}
or similar. The function-in-block not only dominates all its uses, all
uses are contained by the block in which the function is declared.
> If eval was scoped exactly like a block, then this would fail because each function declarations would be block scoped to a new block scope that was inaccessible at the actual call site. To get the necessary compatible behavior we have to hoist the function out of the block scope created for the eval all the way up to the body scope (the Variable Environment) of the function, just like var.
You're right, and this is what the SpiderMonkey function-in-substatement
provided (limited conditional compilation without eval). Crazy as people
say, and we want to remove it. Is it unthinkable to break compatibility
for the eval expansion?
> This is will be an additional, scoping variation for function declarations that only comes into play for non-strict evals.
If we have to keep compatibility, then we have 'function' requiring a
special case compared to 'let' with your option 2. Or we take option 1
and have all the forms, new (let and const) and old (var and function)
pollute non-strict direct eval's dynamic scope. Gah.
/be
More information about the es-discuss
mailing list