Update on ES3.1 block scoped function declarations

View: New views
13 Messages — Rating Filter:   Alert me  

Update on ES3.1 block scoped function declarations

by Allen Wirfs-Brock-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Some parts of this message have been removed. Learn more about Nabble's security policy.

We discussed these issues at today’s ES3.1 conference call and arrived at a new plan of record:

 

1) We concluded that the present diversity of semantics of block nested function declarations among browser implementations probably cannot be replaced with a standard semantics without significant breakage of the web. One compelling use case is the apparent common usage of the difference in IE and FF semantics  in this regard as a browser identification test. So, for ES3.1 we will not change the ES3 stance on such function declarations. This means, that block nested functions will not be part of the ES3.1 syntax or semantics.  The occurrence and meaning of them in an implementation dependent non-standard language extension that is  allowable by section 16.  Our expectation is that most implementations will just continuing doing what they currently do.

 

2) While we can’t reconcile the divergent existing semantics of function declarations within blocks, we can discourage  their on-going use.  To that end, the cautious subset will specify that the occurrence of such a function declaration must be reported as a syntax error at scan time. So, while section 16 of the full ES3.1 language implicitly permits implementations to allow  block nested function declarations, the opt-in cautious subset explicitly withdraws that permission.

 

3) We will still include lexically scoped block environments, but only for const declarations. If you want to define a block scoped function, do it using a const whose value is a function expression.  In a latter revision, we would expect to also add block-scoped let declaration to enable block scoped variables. 


_______________________________________________
Es4-discuss mailing list
Es4-discuss@...
https://mail.mozilla.org/listinfo/es4-discuss

Re: Update on ES3.1 block scoped function declarations

by Brendan Eich-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Jul 10, 2008, at 10:55 AM, Allen Wirfs-Brock wrote:

> We discussed these issues at today’s ES3.1 conference call and  
> arrived at a new plan of record:
>
> 1) We concluded that the present diversity of semantics of block  
> nested function declarations among browser implementations probably  
> cannot be replaced with a standard semantics without significant  
> breakage of the web. One compelling use case is the apparent common  
> usage of the difference in IE and FF semantics  in this regard as a  
> browser identification test.
>

Could you please cite a few URLs showing this common usage? It's a  
new one on me.

> 3) We will still include lexically scoped block environments, but  
> only for const declarations. If you want to define a block scoped  
> function, do it using a const whose value is a function expression.
>
So what would this program print in ES3.1?

const C = 42;
function f(x, y) {
   const C = 33;
   if (x) {
     const C = 21;
     return eval(y);
   }
   return C;
}
print(f(true, "C"));

> In a latter revision, we would expect to also add block-scoped let  
> declaration to enable block scoped variables.
>
"latter revision" is spelled E-S-4 :-P.

/be


_______________________________________________
Es4-discuss mailing list
Es4-discuss@...
https://mail.mozilla.org/listinfo/es4-discuss

Re: Update on ES3.1 block scoped function declarations

by Mark S. Miller-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thu, Jul 10, 2008 at 11:05 AM, Brendan Eich <brendan@...> wrote:

So what would this program print in ES3.1?

const C = 42;
function f(x, y) {
  const C = 33;
  if (x) {
    const C = 21;
    return eval(y);
  }
  return C;
}
print(f(true, "C"));

21

What does it print in ES4-opt-in?

 

> In a latter revision, we would expect to also add block-scoped let
> declaration to enable block scoped variables.
>
"latter revision" is spelled E-S-4 :-P.

;)

Kidding aside, if we could somehow agree on one language, I would want it to have ES4-opt-in's "let".


--
Cheers,
--MarkM
_______________________________________________
Es4-discuss mailing list
Es4-discuss@...
https://mail.mozilla.org/listinfo/es4-discuss

Re: Update on ES3.1 block scoped function declarations

by Brendan Eich-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Jul 10, 2008, at 1:28 PM, Mark S. Miller wrote:

On Thu, Jul 10, 2008 at 11:05 AM, Brendan Eich <brendan@...> wrote:

So what would this program print in ES3.1?

const C = 42;
function f(x, y) {
  const C = 33;
  if (x) {
    const C = 21;
    return eval(y);
  }
  return C;
}
print(f(true, "C"));

21

What does it print in ES4-opt-in?

Call it ES4, please. There's no point in playing games about opt-in, since we know we can't "break the web". ES3 added new syntax, so did ES2. No one bugged out about "opt-in".

21 is the right answer, although reflecting lexical blocks into something eval can see is a big pain (we did this in Firefox 2). It's a lot of work just for block-scoped const. Sorry if I missed the discussion, but was restricting const to top level considered?

/be

_______________________________________________
Es4-discuss mailing list
Es4-discuss@...
https://mail.mozilla.org/listinfo/es4-discuss

RE: Update on ES3.1 block scoped function declarations

by Allen Wirfs-Brock-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Some parts of this message have been removed. Learn more about Nabble's security policy.

Maybe, I’m missing something subtle, but 21 is clearly the right answer and is what I believe is specified by the version of section 10 that I sent out yesterday regardless of the scoping of block nested functions.  Of course, that’s just spec-ware…

 

From: es4-discuss-bounces@... [mailto:es4-discuss-bounces@...] On Behalf Of Brendan Eich
Sent: Thursday, July 10, 2008 1:45 PM
To: Mark S. Miller
Cc: es3.x-discuss@...; es4-discuss@...; Herman Venter
Subject: Re: Update on ES3.1 block scoped function declarations

 

On Jul 10, 2008, at 1:28 PM, Mark S. Miller wrote:



On Thu, Jul 10, 2008 at 11:05 AM, Brendan Eich <brendan@...> wrote:

 

So what would this program print in ES3.1?

const C = 42;
function f(x, y) {
  const C = 33;
  if (x) {
    const C = 21;
    return eval(y);
  }
  return C;
}
print(f(true, "C"));


21

What does it print in ES4-opt-in?

 

Call it ES4, please. There's no point in playing games about opt-in, since we know we can't "break the web". ES3 added new syntax, so did ES2. No one bugged out about "opt-in".

 

21 is the right answer, although reflecting lexical blocks into something eval can see is a big pain (we did this in Firefox 2). It's a lot of work just for block-scoped const. Sorry if I missed the discussion, but was restricting const to top level considered?

 

/be


_______________________________________________
Es4-discuss mailing list
Es4-discuss@...
https://mail.mozilla.org/listinfo/es4-discuss

Re: Update on ES3.1 block scoped function declarations

by Brendan Eich-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Jul 10, 2008, at 1:58 PM, Allen Wirfs-Brock wrote:

Maybe, I’m missing something subtle, but 21 is clearly the right answer and is what I believe is specified by the version of section 10 that I sent out yesterday regardless of the scoping of block nested functions.  Of course, that’s just spec-ware…


21 is the right answer, I agree. But it requires reifying what could otherwise be lexical bindings the compiler tracks and then throws away, just so the compiler invoked by eval can see the bindings again. It's true that catch variables also need this kind of infrastructure, and named function expressions. So you could argue "in for a penny, ...". But block-scoped const in ES3.1, without let or function, is kind of half-a-pound, if you get my meaning. All the implementation cost, half the utility.

/be

 

From: es4-discuss-bounces@... [es4-discuss-bounces@...] On Behalf Of Brendan Eich
Sent: Thursday, July 10, 2008 1:45 PM
To: Mark S. Miller
Cc: es3.x-discuss@...; es4-discuss@...; Herman Venter
Subject: Re: Update on ES3.1 block scoped function declarations

 

On Jul 10, 2008, at 1:28 PM, Mark S. Miller wrote:



On Thu, Jul 10, 2008 at 11:05 AM, Brendan Eich <brendan@...> wrote:

 

So what would this program print in ES3.1?

const C = 42;
function f(x, y) {
  const C = 33;
  if (x) {
    const C = 21;
    return eval(y);
  }
  return C;
}
print(f(true, "C"));


21

What does it print in ES4-opt-in?

 

Call it ES4, please. There's no point in playing games about opt-in, since we know we can't "break the web". ES3 added new syntax, so did ES2. No one bugged out about "opt-in".

 

21 is the right answer, although reflecting lexical blocks into something eval can see is a big pain (we did this in Firefox 2). It's a lot of work just for block-scoped const. Sorry if I missed the discussion, but was restricting const to top level considered?

 

/be

_______________________________________________
Es4-discuss mailing list


_______________________________________________
Es4-discuss mailing list
Es4-discuss@...
https://mail.mozilla.org/listinfo/es4-discuss

Re: Update on ES3.1 block scoped function declarations

by Brendan Eich-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Jul 10, 2008, at 2:03 PM, Brendan Eich wrote:

On Jul 10, 2008, at 1:58 PM, Allen Wirfs-Brock wrote:

Maybe, I’m missing something subtle, but 21 is clearly the right answer and is what I believe is specified by the version of section 10 that I sent out yesterday regardless of the scoping of block nested functions.  Of course, that’s just spec-ware…


21 is the right answer, I agree.


/be


_______________________________________________
Es4-discuss mailing list
Es4-discuss@...
https://mail.mozilla.org/listinfo/es4-discuss

RE: Update on ES3.1 block scoped function declarations

by Allen Wirfs-Brock-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Some parts of this message have been removed. Learn more about Nabble's security policy.

I see, yes there is a potential eval tax.  If I thought this was really a concern (and as you say, we already have the issue for catch and such) I’d be more inclined to fiddling with the scoping rule of eval rather than discarding lexically scoped consts.  BTW, I think many of the use cases for such const are more in support of code generators then actual end user programming.

 

 

From: Brendan Eich [mailto:brendan@...]
Sent: Thursday, July 10, 2008 2:03 PM
To: Allen Wirfs-Brock
Cc: Mark S. Miller; es3.x-discuss@...; es4-discuss@...; Herman Venter
Subject: Re: Update on ES3.1 block scoped function declarations

 

On Jul 10, 2008, at 1:58 PM, Allen Wirfs-Brock wrote:

Maybe, I’m missing something subtle, but 21 is clearly the right answer and is what I believe is specified by the version of section 10 that I sent out yesterday regardless of the scoping of block nested functions.  Of course, that’s just spec-ware…

 

21 is the right answer, I agree. But it requires reifying what could otherwise be lexical bindings the compiler tracks and then throws away, just so the compiler invoked by eval can see the bindings again. It's true that catch variables also need this kind of infrastructure, and named function expressions. So you could argue "in for a penny, ...". But block-scoped const in ES3.1, without let or function, is kind of half-a-pound, if you get my meaning. All the implementation cost, half the utility.

 

/be

 

From: es4-discuss-bounces@... [es4-discuss-bounces@...] On Behalf Of Brendan Eich
Sent: Thursday, July 10, 2008 1:45 PM
To: Mark S. Miller
Cc: es3.x-discuss@...; es4-discuss@...; Herman Venter
Subject: Re: Update on ES3.1 block scoped function declarations

 

On Jul 10, 2008, at 1:28 PM, Mark S. Miller wrote:




On Thu, Jul 10, 2008 at 11:05 AM, Brendan Eich <brendan@...> wrote:

 

So what would this program print in ES3.1?

const C = 42;
function f(x, y) {
  const C = 33;
  if (x) {
    const C = 21;
    return eval(y);
  }
  return C;
}
print(f(true, "C"));


21

What does it print in ES4-opt-in?

 

Call it ES4, please. There's no point in playing games about opt-in, since we know we can't "break the web". ES3 added new syntax, so did ES2. No one bugged out about "opt-in".

 

21 is the right answer, although reflecting lexical blocks into something eval can see is a big pain (we did this in Firefox 2). It's a lot of work just for block-scoped const. Sorry if I missed the discussion, but was restricting const to top level considered?

 

/be

_______________________________________________

Es4-discuss mailing list

 


_______________________________________________
Es4-discuss mailing list
Es4-discuss@...
https://mail.mozilla.org/listinfo/es4-discuss

Re: Update on ES3.1 block scoped function declarations

by Mark S. Miller-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thu, Jul 10, 2008 at 2:51 PM, Allen Wirfs-Brock <Allen.Wirfs-Brock@...> wrote:

I see, yes there is a potential eval tax.  If I thought this was really a concern (and as you say, we already have the issue for catch and such) I'd be more inclined to fiddling with the scoping rule of eval rather than discarding lexically scoped consts.  BTW, I think many of the use cases for such const are more in support of code generators then actual end user programming.

Could you explain the "eval tax" issue you guys are concerned about? I don't get it. Thanks.

--
Cheers,
--MarkM
_______________________________________________
Es4-discuss mailing list
Es4-discuss@...
https://mail.mozilla.org/listinfo/es4-discuss

Re: Update on ES3.1 block scoped function declarations

by Maciej Stachowiak :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On Jul 10, 2008, at 3:28 PM, Mark S. Miller wrote:

On Thu, Jul 10, 2008 at 2:51 PM, Allen Wirfs-Brock <Allen.Wirfs-Brock@...> wrote:

I see, yes there is a potential eval tax.  If I thought this was really a concern (and as you say, we already have the issue for catch and such) I'd be more inclined to fiddling with the scoping rule of eval rather than discarding lexically scoped consts.  BTW, I think many of the use cases for such const are more in support of code generators then actual end user programming.

Could you explain the "eval tax" issue you guys are concerned about? I don't get it. Thanks.

Because eval exposes lexical bindings by name in a way that is not statically detectable, it defeats implementation techniques like renaming or symbol versioning for block scope, and forces the use of actual environment objects for blocks if they contain a call to eval. For example:

function g(x)
{
    if (x) {
        const C = 0;
        return eval(s1);
    } else {
        const C = 1;
        return eval(s2);
    }
}

Assuming s1 and s2 reference C, you at minimum need a separate runtime symbol table for each block to allow the eval lookup to succeed. When combined with closures and mutable block-scoped variables this can force the creation of a full activation object per block that introduces bindings. 

And to avoid creating an activation object for every block (a huge performance cost), an implementation would have to detect which blocks introduce bindings, which contain calls to eval, and which contain closures. Reasonable implementations do this anyway but I think it is an unfortunate cost, even in ES4. In ES4, however, the benefit is arguably greater.

Regards,
Maciej


_______________________________________________
Es4-discuss mailing list
Es4-discuss@...
https://mail.mozilla.org/listinfo/es4-discuss

Re: Update on ES3.1 block scoped function declarations

by Brendan Eich-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Jul 10, 2008, at 3:28 PM, Mark S. Miller wrote:

On Thu, Jul 10, 2008 at 2:51 PM, Allen Wirfs-Brock <Allen.Wirfs-Brock@...> wrote:

I see, yes there is a potential eval tax.  If I thought this was really a concern (and as you say, we already have the issue for catch and such) I'd be more inclined to fiddling with the scoping rule of eval rather than discarding lexically scoped consts.  BTW, I think many of the use cases for such const are more in support of code generators then actual end user programming.

Could you explain the "eval tax" issue you guys are concerned about? I don't get it. Thanks.


In ES1-3, the scope chain is a linked list of objects. Every function call creates an activation object to be the variable object used when "entering the execution context" for that function's code. Thus when entering the execution context for eval code, one uses the caller's scope chain.

Real implementations do not reify objects for all activations. This is a good way to be slow.

Separately, we aspire to lexical scope. This does not necessarily mean block scope, see e.g. ES4 comprehensions. But however it maps onto syntax, lexical scope holds out the hope that the binding information is compile-time only. After that, the implementation can forget about bindings and the lexical scopes they inhabit.

That's not possible if eval can see const bindings in ES3.1 as proposed, or let/const/sub-statement-function bindings in ES4. The "Previously" thread I cited talks about an alternative where eval cannot see lexical bindings. But that thread concluded (IMHO) with the victorious and inevitable usability argument that programmers would be greatly put out, as well as surprised, if eval could not see its caller's lexical bindings.

So implementations have to save lexical binding information when compiling, and reify or otherwise propagate it to eval.

Implementations that support indirect eval must not only save the lexical binding information, they must reify bindings as properties and scopes as objects (or something morally equivalent), since the compiler cannot see all eval calls and make a private arrangement to pass private binding/scope data structures preserved with the function or script that calls eval. The indirect eval activation really does need to see objects on a scope chain. This can be done on demand, but it is not pretty.

Imposing this tax on implementations of ES3.1 and not giving them let and function sub-statements seems half-hearted, and implementations are likely to extend.

Block scope is nice, but it's a big change for ES3.1. The alternative is to

a. confine const grammatically to top level where it can be treated like a property of the global or activation object in the spec, and

b. deal with eval referencing a catch variable or named lambda specially.

The (b) cases were specified in ES3 using "as if by new Object" or equivalent, which is a bug, but some implementations ignored ES3 and used lexical binding machinery. I'm not sure whether all such all eval to see such bindings. Firefox 2 and 3 do for catch variables. I'll test Opera and report back.

/be

_______________________________________________
Es4-discuss mailing list
Es4-discuss@...
https://mail.mozilla.org/listinfo/es4-discuss

Re: Update on ES3.1 block scoped function declarations

by Waldemar Horwat :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Brendan,

You're beating a dead horse here.  If this call to eval is allowed, the only reasonable answer is 21.  All that means is that you must be able to recreate the bindings if the function uses eval.  Unless you're proposing to take block-scoped declarations out of ES4, what's the harm with ES3.1 having a compatible subset of them?

    Waldemar


Brendan Eich wrote:

> On Jul 10, 2008, at 3:28 PM, Mark S. Miller wrote:
>
>> On Thu, Jul 10, 2008 at 2:51 PM, Allen Wirfs-Brock
>> <Allen.Wirfs-Brock@...
>> <mailto:Allen.Wirfs-Brock@...>> wrote:
>>
>>     I see, yes there is a potential eval tax.  If I thought this was
>>     really a concern (and as you say, we already have the issue for
>>     catch and such) I'd be more inclined to fiddling with the scoping
>>     rule of eval rather than discarding lexically scoped consts.  BTW,
>>     I think many of the use cases for such const are more in support
>>     of code generators then actual end user programming.
>>
>> Could you explain the "eval tax" issue you guys are concerned about? I
>> don't get it. Thanks.
>
>
> In ES1-3, the scope chain is a linked list of objects. Every function
> call creates an activation object to be the variable object used when
> "entering the execution context" for that function's code. Thus when
> entering the execution context for eval code, one uses the caller's
> scope chain.
>
> Real implementations do not reify objects for all activations. This is a
> good way to be slow.
>
> Separately, we aspire to lexical scope. This does not necessarily mean
> block scope, see e.g. ES4 comprehensions. But however it maps onto
> syntax, lexical scope holds out the hope that the binding information is
> compile-time only. After that, the implementation can forget about
> bindings and the lexical scopes they inhabit.
>
> That's not possible if eval can see const bindings in ES3.1 as proposed,
> or let/const/sub-statement-function bindings in ES4. The "Previously
> <http://www.nabble.com/Eval-invisible-let-bindings-td14182651.html%2523a14182651>"
> thread I cited talks about an alternative where eval cannot see lexical
> bindings. But that thread concluded (IMHO) with the victorious and
> inevitable usability argument that programmers would be greatly put out,
> as well as surprised, if eval could not see its caller's lexical bindings.
>
> So implementations have to save lexical binding information when
> compiling, and reify or otherwise propagate it to eval.
>
> Implementations that support indirect eval must not only save the
> lexical binding information, they must reify bindings as properties and
> scopes as objects (or something morally equivalent), since the compiler
> cannot see all eval calls and make a private arrangement to pass private
> binding/scope data structures preserved with the function or script that
> calls eval. The indirect eval activation really does need to see objects
> on a scope chain. This can be done on demand, but it is not pretty.
>
> Imposing this tax on implementations of ES3.1 and not giving them let
> and function sub-statements seems half-hearted, and implementations are
> likely to extend.
>
> Block scope is nice, but it's a big change for ES3.1. The alternative is to
>
> a. confine const grammatically to top level where it can be treated like
> a property of the global or activation object in the spec, and
>
> b. deal with eval referencing a catch variable or named lambda specially.
>
> The (b) cases were specified in ES3 using "as if by new Object" or
> equivalent, which is a bug, but some implementations ignored ES3 and
> used lexical binding machinery. I'm not sure whether all such all eval
> to see such bindings. Firefox 2 and 3 do for catch variables. I'll test
> Opera and report back.
>
> /be
_______________________________________________
Es4-discuss mailing list
Es4-discuss@...
https://mail.mozilla.org/listinfo/es4-discuss

Re: Update on ES3.1 block scoped function declarations

by Brendan Eich-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Jul 10, 2008, at 6:08 PM, Waldemar Horwat wrote:

> Brendan,
>
> You're beating a dead horse here.

Sorry, no -- the question of whether and how much of ES4 is pulled  
into ES3.1, requiring costly and untestable work within the framework  
of the ES3 spec, is a live one, and it should be for anyone who cares  
about either version being done, and about 3.1 being done before 4.

>   If this call to eval is allowed, the only reasonable answer is  
> 21.  All that means is that you must be able to recreate the  
> bindings if the function uses eval.  Unless you're proposing to  
> take block-scoped declarations out of ES4, what's the harm with  
> ES3.1 having a compatible subset of them?

The harm is of two kinds:

1. That ES3.1 will be pushed through Ecma standardization this  
calendar year, then to ISO fast track, with zero implementations.

2. That ES3.1 spec work, using and extending the clumsy formalisms of  
ES1-3, will take a lot of time from everyone involved, with  
opportunity costs on other work including ES4, actual implementation  
improvements, better subsets like Caja, etc.

We could turn ES3.1 into ES4 but I think you see the problem there.  
I'm suggesting it is a problem that 3.1 is growing to formalize  
lexical scope. It contradicts the stated aspiration of at least some  
(Mark was among them) at the January face to face that ES3.1 avoid  
mission creep, reflect "ES3 + reality", and be done this calendar year.

/be
_______________________________________________
Es4-discuss mailing list
Es4-discuss@...
https://mail.mozilla.org/listinfo/es4-discuss