block scope + direct non-strict eval

# Andy Wingo (9 years ago)

Hello ecmascriptians,

I hear that TC39 wants to allow let and const into "classic mode". This sounds like a bad idea to me, but, ok.

If so, can someone say what these expressions would evaluate to, or the errors they would raise:

(function (){eval("let x = 10"); return x;})()

(function (){var x = 20; eval("let x = 10"); return x;})()

(function (){let x = 20; eval("let x = 10"); return x;})()

(function (){let x = 20; { eval("let x = 10"); return x;}})()

(function (){let x = 20; eval("var x = 10"); return x;})()

(function (){ { let x = 20; { eval("let x = 10"); return x;}}})()

As Leibniz would have it, let us calculate.

Andy

# Sam Tobin-Hochstadt (9 years ago)

On Tue, Jan 31, 2012 at 9:30 AM, Andy Wingo <wingo at igalia.com> wrote:

Hello ecmascriptians,

I hear that TC39 wants to allow let and const into "classic mode".  This sounds like a bad idea to me, but, ok.

Instead, I would say that TC39 wants to eliminate the concept of "classic mode".

If so, can someone say what these expressions would evaluate to, or the errors they would raise:

I don't think we've talked about the behavior of direct |eval| on statements with |let|, but here's what I would hope we'd do:

(function (){eval("let x = 10"); return x;})()

ReferenceError

(function (){var x = 20; eval("let x = 10"); return x;})()  (function (){let x = 20; eval("let x = 10"); return x;})()  (function (){let x = 20; { eval("let x = 10"); return x;}})() (function (){ { let x = 20; { eval("let x = 10"); return x;}}})()

20

(function (){let x = 20; eval("var x = 10"); return x;})()

10

# Brendan Eich (9 years ago)

What Sam said. There's no need to hork 'let' just because of a lack of version or strict-mode opt-in. It's still sane, unlike 'var'. Leibniz agrees ;-).

# Andreas Rossberg (9 years ago)

On 31 January 2012 17:27, Sam Tobin-Hochstadt <samth at ccs.neu.edu> wrote:

Instead, I would say that TC39 wants to eliminate the concept of "classic mode".

What do you mean? I don't see how it can be eliminated, except by name games.

# Andy Wingo (9 years ago)

:)

On Tue, 2012-01-31 at 11:27 -0500, Sam Tobin-Hochstadt wrote:

(function (){eval("let x = 10"); return x;})()

ReferenceError

Oh good. I was thinking that the intention was that let could introduce new block-scoped bindings in the containing scope. If that is not the case, then good.

Summary: eval introduces a new block scope.

(function (){let x = 20; eval("var x = 10"); return x;})()

10

Surely a SyntaxError, as the var x conflicts with the let x at the function-level scope?

Andy

# Allen Wirfs-Brock (9 years ago)

On Jan 31, 2012, at 8:27 AM, Sam Tobin-Hochstadt wrote:

On Tue, Jan 31, 2012 at 9:30 AM, Andy Wingo <wingo at igalia.com> wrote:

Hello ecmascriptians,

I hear that TC39 wants to allow let and const into "classic mode". This sounds like a bad idea to me, but, ok.

Instead, I would say that TC39 wants to eliminate the concept of "classic mode".

If so, can someone say what these expressions would evaluate to, or the errors they would raise:

I don't think we've talked about the behavior of direct |eval| on statements with |let|, but here's what I would hope we'd do:

But it's an issue that I'ver been thinking about since the last meeting.

The basic difference between non-strict direct eval and strict direct eval is that strict creates a new nested environment contour that is used as both the VariableEnvironement and LexicalEnvironment while non-strict uses the currently active Variable/Lexical environment.

It there are two possible semantics for non-strict eval with lexical declaration that I have come up with are:

  1. same as ES5, it currents it uses/extends the current Variable and Lexical Environments function f() { // variable environment function xVarEnv() {return x} { //lexical environment print(xVarEnv()); //should be: undefined eval("var x=1"); //create in the variable environment print(xVarEnv()); //should be: 1 eval("let x=2"); //create in the lexical environment eval("print(x)") //should be: 2 print(x); //should be: 2 print(xVarEnv()); //should be: 1 } print(xVarEnv()); //should be: 1 )

(note that the most interesting example have an inner block)

  1. It creates a new nested Lexical Environment (for let and const declarations) but uses the currently active Variable environment. The lexical environment is discarded when the eval is completed.:

function f() { // variable environment function xVarEnv() {return x} { //lexical environment print(xVarEnv()); //should be: undefined eval("var x=1"); //create in the variable environment print(xVarEnv()); //should be: 1 eval("let x=2; print(x)"); //create in a new lexical environment, should print: 2 eval("print(x)"); //should be: 1 print(x); //should be: 1 print(xVarEnv()); //should be: 1 } print(xVarEnv()); //should be: 1 )

Note that the second alternative requires (for ES5 compatibility, hoisting functions at the top of the eval code to the Variable Environment. This would be different from the normal ES6 scoping rules for function declarations that are logically nested within a block.

The second alternative is basically half way between a strict and non-strict eval. By inclination is to stick with the simpler alternative 1

(function (){eval("let x = 10"); return x;})()

ReferenceError

alternative 1 would return 10, note that (function (){eval("var x = 10"); return x;})() must return 10 for compatability
alternative 2: return binding of x outside of function. It may be undefined.

(function (){var x = 20; eval("let x = 10"); return x;})() (function (){let x = 20; eval("let x = 10"); return x;})()

alternative 1: SyntaxError: duplicate declaration of x alternative 2: 20

(function (){let x = 20; { eval("let x = 10"); return x;}})()

(function (){ { let x = 20; { eval("let x = 10"); return x;}}})()

alternative 1: 10 alternative 2: 20

20

(function (){let x = 20; eval("var x = 10"); return x;})()

alternative 1: SyntaxError: duplicate declaration of x alternative 2: SyntaxError: duplicate declaration of x

# Allen Wirfs-Brock (9 years ago)

On Jan 31, 2012, at 8:44 AM, Andreas Rossberg wrote:

On 31 January 2012 17:27, Sam Tobin-Hochstadt <samth at ccs.neu.edu> wrote:

Instead, I would say that TC39 wants to eliminate the concept of "classic mode".

What do you mean? I don't see how it can be eliminated, except by name games.

What we agreed to eliminate is the concept of a"classic mode" that corresponds to unextended non-strict ES5. Both non-strict and strict code in ES6 will include support for the extended ES6 language features. In a few cases the semantics of extensions may differ slightly between strict and non-strict code and a few extensions may only be available for use by strict code

# Allen Wirfs-Brock (9 years ago)

a correction below, with that correct my alternative 2 appears to be equivalent to Sam's answers

# Brendan Eich (9 years ago)

Andy Wingo <mailto:wingo at igalia.com> January 31, 2012 9:07 AM Summary: eval introduces a new block scope.

And there's a new var scope per direct eval call in strict code, per ES5. Adding 'let' must not reintroduce the pre-strict crazy ;-).

(function (){let x = 20; eval("var x = 10"); return x;})() 10

Surely a SyntaxError, as the var x conflicts with the let x at the function-level scope?

Oops, you're right. This is non-strict direct eval, so the var hoists and collides with the 'let'.

# Andreas Rossberg (9 years ago)

On 31 January 2012 18:40, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:

On Jan 31, 2012, at 8:44 AM, Andreas Rossberg wrote:

On 31 January 2012 17:27, Sam Tobin-Hochstadt <samth at ccs.neu.edu> wrote:

Instead, I would say that TC39 wants to eliminate the concept of "classic mode".

What do you mean? I don't see how it can be eliminated, except by name games.

What we agreed to eliminate is the concept of a"classic mode" that corresponds to unextended non-strict ES5.

You mean as in: "extend" is the new "eliminate"?

I'm sorry, I couldn't resist...

# Brendan Eich (9 years ago)

Allen Wirfs-Brock <mailto:allen at wirfs-brock.com> January 31, 2012 9:20 AM

But it's an issue that I'ver been thinking about since the last meeting.

The basic difference between non-strict direct eval and strict direct eval is that strict creates a new nested environment contour that is used as both the VariableEnvironement and LexicalEnvironment while non-strict uses the currently active Variable/Lexical environment.

It there are two possible semantics for non-strict eval with lexical declaration that I have come up with are:

  1. same as ES5, it currents it uses/extends the current Variable and Lexical Environments function f() { // variable environment function xVarEnv() {return x} { //lexical environment print(xVarEnv()); //should be: undefined eval("var x=1"); //create in the variable environment print(xVarEnv()); //should be: 1 eval("let x=2"); //create in the lexical environment eval("print(x)") //should be: 2 print(x); //should be: 2 print(xVarEnv()); //should be: 1 } print(xVarEnv()); //should be: 1 )

(note that the most interesting example have an inner block)

(Indeed.)

I don't like this because we make a pre-strict variation on 'let' that perpetuates the dynamic scope injection flaw in eval, whereby it can pollute its caller's scope with fresh bindings. This is just evil and I wish we'd never standardized it in ES1 for 'var'. I see no good coming from extending it to 'let' and 'const'.

And 'function' in block? That's a different case again because it wouldn't hoist. Indeed direct eval('function f(){...}') in non-strict code is analogous to the SpiderMonkey conditionally-compiled, dynamically-bound function in sub-statement pre-ES3 extension we are trying to kill.

I think (2) is the best course. It "mixes" differently, but in a stricter direction.

# Brendan Eich (9 years ago)

I bet the "mode" was what got Sam's attention (mine too) in your "classic mode". We are not making hard mode walls or version opt-in. No engine will have a mode enum that must be advanced (implicitly or explicitly) and checked in order to tell what to do in unversioned script. Or so we think!

# Allen Wirfs-Brock (9 years ago)

On Jan 31, 2012, at 10:22 AM, Brendan Eich wrote:

Allen Wirfs-Brock <mailto:allen at wirfs-brock.com> January 31, 2012 9:20 AM

But it's an issue that I'ver been thinking about since the last meeting.

The basic difference between non-strict direct eval and strict direct eval is that strict creates a new nested environment contour that is used as both the VariableEnvironement and LexicalEnvironment while non-strict uses the currently active Variable/Lexical environment.

It there are two possible semantics for non-strict eval with lexical declaration that I have come up with are:

  1. same as ES5, it currents it uses/extends the current Variable and Lexical Environments function f() { // variable environment function xVarEnv() {return x} { //lexical environment print(xVarEnv()); //should be: undefined eval("var x=1"); //create in the variable environment print(xVarEnv()); //should be: 1 eval("let x=2"); //create in the lexical environment eval("print(x)") //should be: 2 print(x); //should be: 2 print(xVarEnv()); //should be: 1 } print(xVarEnv()); //should be: 1 )

(note that the most interesting example have an inner block)

(Indeed.)

I don't like this because we make a pre-strict variation on 'let' that perpetuates the dynamic scope injection flaw in eval, whereby it can pollute its caller's scope with fresh bindings. This is just evil and I wish we'd never standardized it in ES1 for 'var'. I see no good coming from extending it to 'let' and 'const'.

And 'function' in block? That's a different case again because it wouldn't hoist. Indeed direct eval('function f(){...}') in non-strict code is analogous to the SpiderMonkey conditionally-compiled, dynamically-bound function in sub-statement pre-ES3 extension we are trying to kill.

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(); }

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. This is will be an additional, scoping variation for function declarations that only comes into play for non-strict evals.

# Andreas Rossberg (9 years ago)

On 31 January 2012 19:23, Brendan Eich <brendan at mozilla.org> wrote:

I bet the "mode" was what got Sam's attention (mine too) in your "classic mode". We are not making hard mode walls or version opt-in. No engine will have a mode enum that must be advanced (implicitly or explicitly) and checked in order to tell what to do in unversioned script. Or so we think!

I'm afraid that I still fail to get this argument. When you compile an individual function in ES6, you will need to have a 3-valued enum around saying whether it resides "in strict scope", "in non-strict scope", or "in module scope". Similarly, if you are human and read a piece of code. No news there. Whether that is called "mode" or "context" or something else seems pretty much immaterial.

(I'm saying 3-valued, because Dave was alluding to additional static checks inside modules. It may be that 2 values keep being enough.)

# Brendan Eich (9 years ago)

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.

# Brendan Eich (9 years ago)

Andreas Rossberg wrote:

On 31 January 2012 19:23, Brendan Eich<brendan at mozilla.org> wrote:

I bet the "mode" was what got Sam's attention (mine too) in your "classic mode". We are not making hard mode walls or version opt-in. No engine will have a mode enum that must be advanced (implicitly or explicitly) and checked in order to tell what to do in unversioned script. Or so we think!

I'm afraid that I still fail to get this argument. When you compile an individual function in ES6, you will need to have a 3-valued enum around saying whether it resides "in strict scope", "in non-strict scope", or "in module scope".

But nothing about "classic mode" where new syntax with strict-ish semantics is forbidden.

Similarly, if you are human and read a piece of code.

From my experience with JS developers, I believe that many people will read unversioned non-strict code as part of "One JavaScript" (a true myth, useful as well as truthful in deep yet fuzzy ways). They won't think about strict mode (alas; this may change, but it will take time). They definitely will not think about "classic mode". They tell me they will use destructuring, spread, rest, etc.

No news there. Whether that is called "mode" or "context" or something else seems pretty much immaterial.

(I'm saying 3-valued, because Dave was alluding to additional static checks inside modules. It may be that 2 values keep being enough.)

If you count "modes" then there could be many, one per new syntax use-case in non-strict code. E.g. destructuring formal parameters vs. duplicate formals, and how arguments reflects the unnamed object actual passed for each destructuring formal pattern. Is that "classic mode"? It's not ES5 strict mode.

Modes are not helpful in my view. Teaching people about them is a losing proposition, which arguably does a disservice. We may disagree on this but I'll be over there with all the JS devs who've rallied around "One JavaScript".

# Allen Wirfs-Brock (9 years ago)

On Jan 31, 2012, at 11:20 AM, Brendan Eich wrote:

Allen Wirfs-Brock wrote: ...

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?

I think there are two differences between the eval case and the function declaration case:

  1. there is a standardize and generally correctly implemented semantics for function in eval. Hence it is more likely to be used.
  2. people whose are writing code to dynamically construct the source code of a function that will be created via eval are probably think about different issues than. I hypothesize that they are more likely to place the eval in a block that conditionalized by a if statement.

Either or both of these may make it more likely that such eval code actually exists.

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.

Exactly, compatibility via option 2 requires treating function like var instead of like let.

# Andy Wingo (9 years ago)

On Tue, 2012-01-31 at 10:13 -0800, Brendan Eich wrote:

(function (){let x = 20; eval("var x = 10"); return x;})() 10

Surely a SyntaxError, as the var x conflicts with the let x at the function-level scope?

Oops, you're right. This is non-strict direct eval, so the var hoists and collides with the 'let'. Thanks!

Relatedly:

(function (){ { let x = 20; eval ("var x = 10"); } return x;})()

SyntaxError because the "var x" gets hoisted past the "let x" ?

Andy

# Allen Wirfs-Brock (9 years ago)

On Jan 31, 2012, at 12:22 PM, Andy Wingo wrote:

On Tue, 2012-01-31 at 10:13 -0800, Brendan Eich wrote:

(function (){let x = 20; eval("var x = 10"); return x;})() 10

Surely a SyntaxError, as the var x conflicts with the let x at the function-level scope?

Oops, you're right. This is non-strict direct eval, so the var hoists and collides with the 'let'. Thanks!

Relatedly:

(function (){ { let x = 20; eval ("var x = 10"); } return x;})()

SyntaxError because the "var x" gets hoisted past the "let x" ?

absolutely

# Claus Reinke (9 years ago)

I bet the "mode" was what got Sam's attention (mine too) in your "classic mode". We are not making hard mode walls or version opt-in. No engine will have a mode enum that must be advanced (implicitly or explicitly) and checked in order to tell what to do in unversioned script. Or so we think!

Btw, how does versioning work across eval? If I have a function body with an eval in it, will the body/eval run as in ES5 or as in ES6? Will that change if the body or the eval contain ES6 features? Will ES5/ES6 scripts be able to eval ES6/ES5 code?

Claus

# Brendan Eich (9 years ago)

On this very thread we are hashing out how eval("let x = ...") interacts with the dynamic scope. I started advocating an ES5-like isolaed eval lexical scope, and we could do that for let and const -- but var for direct eval from non-strict code must affect the dynamic scope, same with function in all likelihood (i.e., that's how eval("function f(){...}") works now).

We already did the work in ES4/3.1 days, culminating in ES5, to distinguish direct from indirect eval. Direct eval from strict code is well-defined to have a fresh lexical scope in which to bind vars and functions in the eval'ed source:

js> function f(s){"use strict"; eval(s); return g}

js> var g = "global";

js> f("function g(){}") "global" js> f("var g=42") "global"

For strict direct eval, it follows that let and const must bind in the fresh lexical scope created for eval. But direct eval from non-strict code still faces the two choices Allen outlined.

Indirect eval is always non-strict and scoped only by the global scope.

# Allen Wirfs-Brock (9 years ago)

On Jan 31, 2012, at 1:53 PM, Brendan Eich wrote:

...

Indirect eval is always non-strict and scoped only by the global scope.

Almost. Indirect eval is strict if the eval'ed strings starts with a "use strict";

# Mark S. Miller (9 years ago)

On Tue, Jan 31, 2012 at 1:53 PM, Brendan Eich <brendan at mozilla.org> wrote:

On this very thread we are hashing out how eval("let x = ...") interacts with the dynamic scope. I started advocating an ES5-like isolaed eval lexical scope, and we could do that for let and const -- but var for direct eval from non-strict code must affect the dynamic scope, same with function in all likelihood (i.e., that's how eval("function f(){...}") works now).

We already did the work in ES4/3.1 days, culminating in ES5, to distinguish direct from indirect eval. Direct eval from strict code is well-defined to have a fresh lexical scope in which to bind vars and functions in the eval'ed source:

js> function f(s){"use strict"; eval(s); return g} js> var g = "global"; js> f("function g(){}") "global" js> f("var g=42") "global"

For strict direct eval, it follows that let and const must bind in the fresh lexical scope created for eval. But direct eval from non-strict code still faces the two choices Allen outlined.

Indirect eval is always non-strict and scoped only by the global scope.

(1,eval)(' "use strict"; let x = 8;')

is a strict indirect eval.

# Brendan Eich (9 years ago)

Mark S. Miller wrote:

Indirect eval is always non-strict and scoped only by the global
scope.


(1,eval)(' "use strict"; let x = 8;')

is a strict indirect eval.

Yes. I hope it was clear I meant that, absent any "use strict"; directive in the eval'd source, an indirect eval even from strict code does not inherit strictness from its caller. No dynamic scope.

# John J Barton (9 years ago)

2) people whose are writing code to dynamically construct the source code of a function that will be created via eval are probably think about different issues than. I hypothesize that they are more likely to place the eval in a block that conditionalized by a if statement.

Just to inform the discussion, some use cases for eval that I have seen:

  1. REPL (dicey, users have to deal with it)
  2. JS source loaders (dicey, we're desperate)
  3. Domain Specific Languages compiled into JS, eg domplate in Firebug, calculators. (solid)

Conditional compilation per se isn't a common use case because generating or downloading the code will probably be more expensive than compiling it.

jjb

# Claus Reinke (9 years ago)

Btw, how does versioning work across eval? If I have a function body with an eval in it, will the body/eval run as in ES5 or as in ES6? Will that change if the body or the eval contain ES6 features? Will ES5/ES6 scripts be able to eval ES6/ES5 code?

On this very thread we are hashing out how eval("let x = ...") interacts with the dynamic scope.

Yes. Prompted by this, I am trying to understand how eval interacts with implicit versioning ("no ES6 opt-in"; btw, is the current state of discussion on opt-in summarized somewhere? I get lost in the threads here, and the wiki seems to predate this discussion).

Both ES6 detection-by-feature-use and some ES6 features imply static checks, with a clear phase distinction between a static and a dynamic phase. eval ensures that ES is multi-staged (static/dynamic phase switches may occur nested, with the static phase of an eval occurring during the dynamic phase of the outer code that reaches that eval).

..[ points about direct vs indirect eval, strict vs non-strict code]..

These precedents seem to suggest that the eval code language version will mostly be independent of versioning the outer code. Which seems sensible: the eval source is dynamic data, so cannot be used for static language version determination of outer code; and, on a larger scale, we want to be able to eval both ES5 and ES6 code. But, on a smaller scale, that means that eval can be used to embed ES5 features in ES6 code, and vice versa.

Take this problematic example from the old no-opt-in thread:

function f(a) { arguments[0]=2; return a } print(f(1)); //2 if ES5, 1 if ES6

There is nothing in the source file that implies which specification to apply so for backwards computability a browser must default to interpreting such program as a ES5 program. Anything syntactically unique to ES5 (eg, use of a with statment) or ES6 (eg, use rest or spread) would force one interpretation or another

and embed the assignment in an eval:

function f(a) { eval("arguments[0]=2"); return a } print(f(1)); // 2 or 1?

If the language version for eval code is independent of the context, we could have ES5 features used in the middle of ES6 code (so the result could be 2 even if f is part of ES6 code, unless such cross-version interactions are prevented by a dynamic barrier), and vice versa. If the language version for the eval code is not independent of the context, we have other problems.

Claus

# Allen Wirfs-Brock (9 years ago)

On Feb 1, 2012, at 7:08 AM, Claus Reinke wrote:

Take this problematic example from the old no-opt-in thread:

function f(a) { arguments[0]=2; return a } print(f(1)); //2 if ES5, 1 if ES6

There is nothing in the source file that implies which specification to apply so for backwards computability a browser must default to interpreting such program as a ES5 program. Anything syntactically unique to ES5 (eg, use of a with statment) or ES6 (eg, use rest or spread) would force one interpretation or another

No, things changed at the last TC39 meeting.

New features can generally be used anywhere. All code is non-strict unless it is either made strict using a use strict directive or contained within a module body (module bodes have an implicit "use strict").

The above code works the same in ES5 and ES6. If it is strict code it returns 1. If it is non-strict code it returns 2

and embed the assignment in an eval:

function f(a) { eval("arguments[0]=2"); return a } print(f(1)); // 2 or 1?

same as above, same as ES5

If the language version for eval code is independent of the context, we could have ES5 features used in the middle of ES6 code (so the result could be 2 even if f is part of ES6 code, unless such cross-version interactions are prevented by a dynamic barrier), and vice versa. If the language version for the eval code is not independent of the context, we have other problems.

Sticking with the strict/non-strict distinction, can you give an example where a ES6 feature within a strict direct eval within a non-strict code context would be problematic?

# Claus Reinke (9 years ago)

No, things changed at the last TC39 meeting.

New features can generally be used anywhere. All code is non-strict unless it is either made strict using a use strict directive or contained within a module body (module bodes have an implicit "use strict").

Okay, that wasn't clear to me from the meeting notes. In general, I've completely lost track of what ES6 is going to look like: too many variations and re-designs in the mailing list threads, no way for me to distinguish member preferences from committee agreements. As the wiki no longer seems to represent the latest agreements, I'll have to wait for your next spec update (and hope that there isn't another thread that obsoletes the spec update).

and embed the assignment in an eval:

function f(a) { eval("arguments[0]=2"); return a } print(f(1)); // 2 or 1?

same as above, same as ES5

But if I put this in a module, f will be in extended strict mode, while the eval code will default to non-extended non-strict mode, right? Which wouldn't quite be the same as in the version without eval.

If the language version for eval code is independent of the context, we could have ES5 features used in the middle of ES6 code (so the result could be 2 even if f is part of ES6 code, unless such cross-version interactions are prevented by a dynamic barrier), and vice versa. If the language version for the eval code is not independent of the context, we have other problems.

Sticking with the strict/non-strict distinction, can you give an example where a ES6 feature within a strict direct eval within a non-strict code context would be problematic?

I'm not yet sure whether any of this is problematic, I'm just trying to pin down how the static determination of language mode is going to work in the presence of eval, and what the interactions are.

Claus

# Sam Tobin-Hochstadt (9 years ago)

On Thu, Feb 2, 2012 at 5:07 AM, Claus Reinke <claus.reinke at talk21.com> wrote:

Okay, that wasn't clear to me from the meeting notes. In general, I've completely lost track of what ES6 is going to look like: too many variations and re-designs in the mailing list threads, no way for me to distinguish member preferences from committee agreements. As the wiki no longer seems to represent the latest agreements, I'll have to wait for your next spec update (and hope that there isn't another thread that obsoletes the spec update).

In general, the most definitive information is from Waldemar's notes from the face-to-face TC39 meetings. Much of what is discussed isn't in the latest spec drafts (modules, for example), and the wiki is both potentially out of date (sadly, this is especially true in things I'm responsible for) and does not necessarily have the consensus of the committee. It's very rare that final designs can be gleaned directly from the mailing list, even the mailing list posts of TC39 members.

Ultimately though, the overall shape of ES6 is fairly clear (see the harmony:proposals page); conversely, many of the fine details haven't been fully decided, so it's not possible to know how they'll turn out yet.

# Claus Reinke (9 years ago)

Okay, that wasn't clear to me from the meeting notes. In general, I've completely lost track of what ES6 is going to look like: too many variations and re-designs in the mailing list threads, no way for me to distinguish member preferences from committee agreements. As the wiki no longer seems to represent the latest agreements, I'll have to wait for your next spec update (and hope that there isn't another thread that obsoletes the spec update).

In general, the most definitive information is from Waldemar's notes from the face-to-face TC39 meetings. Much of what is discussed isn't in the latest spec drafts (modules, for example), and the wiki is both potentially out of date (sadly, this is especially true in things I'm responsible for) and does not necessarily have the consensus of the committee. It's very rare that final designs can be gleaned directly from the mailing list, even the mailing list posts of TC39 members.

Ultimately though, the overall shape of ES6 is fairly clear (see the harmony:proposals page); conversely, many of the fine details haven't been fully decided, so it's not possible to know how they'll turn out yet.

If I could make a suggestion:

directly after each f2f meeting, TC39 could go through the 
harmony:proposals page and annotate every proposal that is 
affected by decisions of that meeting (just the proposal entries
on that single top-level page, not the proposal texts).

For instance, if the no-opt-in decision means giving up on some proposals, annotate those with "obsolete after 19/01 meeting". Similarly, annotate other proposals as "needs update after 19/01" and add placeholders (eg. "no-opt-in") for "new proposal after 19/01", as needed.

That way, even if it takes time to update the actual proposal texts, the harmony:proposals overview page would always reflect the latest agreements and action items. Once the proposal texts are updated, change the annotations on harmony:proposals to "last updated 19/01" or whatever meeting last affected that proposal. In the same direction, have an icon for proposals that have been integrated into the latest spec draft.

Using the harmony:proposal page as the main "whiteboard", with links not only to proposals, but also to spec drafts and meeting notes, and with status/todo annotations, might help to put everyone onto the same page.

Claus

# Allen Wirfs-Brock (9 years ago)

On Feb 2, 2012, at 2:07 AM, Claus Reinke wrote:

and embed the assignment in an eval:

function f(a) { eval("arguments[0]=2"); return a } print(f(1)); // 2 or 1?

same as above, same as ES5

But if I put this in a module, f will be in extended strict mode, while the eval code will default to non-extended non-strict mode, right? Which wouldn't quite be the same as in the version without eval.

Per ES5 10.1.1, the code will be strict code--direct eval from strict code always processes the eval coce as strict code.

# Allen Wirfs-Brock (9 years ago)

On Feb 2, 2012, at 6:46 AM, Claus Reinke wrote:

Okay, that wasn't clear to me from the meeting notes. In general, I've completely lost track of what ES6 is going to look like: too many variations and re-designs in the mailing list threads, no way for me to distinguish member preferences from committee agreements. As the wiki no longer seems to represent the latest agreements, I'll have to wait for your next spec update (and hope that there isn't another thread that obsoletes the spec update). In general, the most definitive information is from Waldemar's notes from the face-to-face TC39 meetings. Much of what is discussed isn't in the latest spec drafts (modules, for example), and the wiki is both potentially out of date (sadly, this is especially true in things I'm responsible for) and does not necessarily have the consensus of the committee. It's very rare that final designs can be gleaned directly from the mailing list, even the mailing list posts of TC39 members. Ultimately though, the overall shape of ES6 is fairly clear (see the harmony:proposals page); conversely, many of the fine details haven't been fully decided, so it's not possible to know how they'll turn out yet.

If I could make a suggestion: directly after each f2f meeting, TC39 could go through the harmony:proposals page and annotate every proposal that is affected by decisions of that meeting (just the proposal entries on that single top-level page, not the proposal texts).

For instance, if the no-opt-in decision means giving up on some proposals, annotate those with "obsolete after 19/01 meeting". Similarly, annotate other proposals as "needs update after 19/01" and add placeholders (eg. "no-opt-in") for "new proposal after 19/01", as needed.

That way, even if it takes time to update the actual proposal texts, the harmony:proposals overview page would always reflect the latest agreements and action items. Once the proposal texts are updated, change the annotations on harmony:proposals to "last updated 19/01" or whatever meeting last affected that proposal. In the same direction, have an icon for proposals that have been integrated into the latest spec draft.

Using the harmony:proposal page as the main "whiteboard", with links not only to proposals, but also to spec drafts and meeting notes, and with status/todo annotations, might help to put everyone onto the same page.

In general, my job as editor is to turn proposal into to actual normative specification language. Informally at any point in time, a wiki proposal is in one of three states relative to the draft ES6 specification. The states "in the draft spec",. "not yet in the draft spec", or "draft spec. work in process".

For proposal that are "in the draft spec", the spec should be the primary think you look at as it reflects my understanding of all current decisions and is the normative text that ultimately needs to be correct. Sometimes there are open issues that are explicitly noted in the draft. I generally "immediately" (within a week or so) after a TC39 meeting update the draft spec. to reflect any decisions that were made concerning "in the draft spec features". Once something is "in draft spec", the wiki pages become many useful as background material.

I find that for most proposal there are many details that need to be specified that were not covered by the proposal. I generally bring to this list any such details that have a significant impact, are likely to be controversial, or for which that are multiple plausable alternatives. But for the rest I simply resolve them in a manner that I believe is most consistent with the overall language. This is why it is important that people review the actual specification language. In the end, its the only thing that counts.

For proposal that are "not yet in the draft spec", it would certainly be helpful if the champions of such proposal kept them up to date.

I treat proposals that are "in process for the draft", similarly to "in the draft spec" items. But it would be helpful for the champions to also update the proposal pages.

Bottom line, always start with the draft spec. Then refer to proposals.

# Allen Wirfs-Brock (9 years ago)

Also, please report all draft spec. issues using bugs.ecmascript.org. That way they won't get lost in the noise on this list. You can also submit issues against proposals using it.