Re: catch vs function scope; var declaration vs initialization

2012-05-14 Thread Brendan Eich

Claus Reinke wrote:
firefox 12 complains: 'e is not defined' 


Thanks for pointing this out. It is a fairly recent regression. I used 
`hg bisect` to find it and filed


https://bugzilla.mozilla.org/show_bug.cgi?id=755099

I agree with Allen, we should clear this dark corner of the deck with 
vigorous application of early-error solution and scrub in nightly builds 
to prove no real code relies on var e; inside catch (e) {...} hoisting.


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: catch vs function scope; var declaration vs initialization

2012-05-14 Thread Allen Wirfs-Brock

On May 14, 2012, at 2:44 PM, Claus Reinke wrote:
> 
>> Because let is a new feature, this restriction doesn't introduce any
>> backwards compatibility issues. However, for consistency, the draft
>> also currently applies the same let declaration restrictions to catch
>> parameters.
> 
> Even better!-) And in line with treating catch as an anonymous function.

An analogy with inner functions isn't needed and wouldn't be correct.  This is 
simply appling the static semantics of Block level declarations. A Block  is 
not allowed to var declare (including via nested blocks) any identifier that is 
lexically declared in the block (but not including nested blocks).

function f() {
   try { throw "hi"
   } catch (e)  {
  var v;
   };
}

is legal and binds "v" at the top-level of function f.  If the catch clause was 
treated like an anonymous function, "v" would be bound at the level of the 
catch clause.  It isn't...

In terms of scope contours the above is equivalent to 

function f() {
  {  //throw "hi"
 }
  {
  let e;
  var v;
   }
}

Allen




___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: catch vs function scope; var declaration vs initialization

2012-05-14 Thread Claus Reinke

undefined undefined hu

is what should be produced according to the spec.

Divergence among implementations is a good sign that there is an 
opportunity to clean up this particular mess.


Yes, please!-)


The current ES6 draft requires an early error for this function
because it is trying to hoist a var declaration across a block-level
declaration of the same identifier.  EG,


'let' vs 'var' would have been my next question. Good to
know that this particular issue does not propagate to 'let'!


Because let is a new feature, this restriction doesn't introduce any
backwards compatibility issues. However, for consistency, the draft
also currently applies the same let declaration restrictions to catch
parameters.


Even better!-) And in line with treating catch as an anonymous function.

Claus

Your experiment suggests that that we might actually be able to to that 
...


Allen





On May 14, 2012, at 2:57 AM, Claus Reinke wrote:


What should be the output of the following code?

(function(){

try {
throw "hi";
} catch (e) {
var e = "ho";
var o = "hu";
var u;
console.log(e);
}
console.log(e,u,o);

}());

It seems clear that the first console.log should output 'ho'.
Implementations seem to disagree on the second console.log, though.

From my current understanding of the spec, I expected:
  undefined undefined 'hu'

which I consider unfortunate; especially the first 'undefined'
was intended to demonstrate the bad effects of separating declaration 
from initialization while treating catch and function differently, in 
terms of scoping.


node, opera: undefined undefined 'hu'

firefox 12 complains: 'e is not defined'

ie 9 outputs: houndefinedhu

It looks as if firefox misses the hoisted declaration of 'e'
(it doesn't complain about 'u', only about 'e') while ie9 somehow merges 
the declaration and the catch parameter.


Claus
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss







___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: catch vs function scope; var declaration vs initialization

2012-05-14 Thread Claus Reinke

Inside the catch, the catch-scope is first for reading and writing.


In "practice" (as in: what implementations permit; not: what is used),
there is also this variation:

try { throw "oops" }
catch (f) {
   function f() { console.log(f) }
   console.log(f)
}
console.log(f)

This isn't permitted in ES5, and 'f' would be block-scoped if permitted
in ES6. In common non-standard extensions to ES5, the function and
references to 'f' in its body are bound outside the catch. I don't even
want to look at what happens with a function declaration in a catch
where the body references the catch parameter..

I'm currently looking at these edge cases for implementing
renaming (program transformation) - no fun.


§10.5 tells us that `var` creates bindings in the anonymous function's
environment, so the function's env has `e`, `o`, and `u` bindings.

§12.14 tells us that within the `catch`, a new environment is created
with the function's environment being the parent. So the assignment
to `e` is to the `catch`'s `e`, not the function's.


Which means that the single occurrence of 'e' in 'var e = "ho"' is bound
to two different scopes: outside the catch for creating a binding, in the
catch for assignment. As Allen anticipated, I was wondering about the
effects on mixing 'let' and 'var', too.

Claus


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Concise Function Body

2012-05-14 Thread Allen Wirfs-Brock

On May 14, 2012, at 9:53 AM, Brendan Eich wrote:

> From where is this produced? It's unsound if from MemberExpression (ES1-5) or 
> PrimaryExpression (ES6) -> FunctionExpression -> ... ConciseBody.

AssignmentExpression :
   ...
   ArrowFunction

ArrowFunction :
   ArrowParameter => ConciseBody




> 
> /be
> 
> Erik Arvidsson wrote:
>> The latest ES6 draft introduced the notion of a concise function body
>> and it is being used for arrow functions as well as for methods and
>> set/get accessors.
>> 
>> Grammar:
>> 
>> ConciseBody :
>>   [lookahead does not include { ] AssignmentExpression
>>   { FunctionBody }
>> 
>> Example:
>> 
>> var object = {
>>   get x() this._x,
>>   set x(v) this._x = v,
>>   method() this._x
>> };
>> 
>> I don't remember us ever discussing this change?
>> 
>> Personally I think it makes things more consistent since concise
>> function bodies are allowed in ArrowFunction but I've heard people
>> complain about it already.
>> 
>> p.s. Allen, the spec draft has a bunch of ConsiseBody typos.
>> 
> 

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Concise Function Body

2012-05-14 Thread Allen Wirfs-Brock
I'm pretty sure there was some discussion about this on some thread, but it may 
have been fleeting...

Concise methods 
(http://wiki.ecmascript.org/doku.php?id=harmony:concise_object_literal_extensions#methods
 ) have been proposals for quite some time.

When I added ArrowFunctions into the draft, it seemed to make sense to 
consistently apply them to the other new function definition form (concise 
methods) that we already had added. Once that was done, it also made sense, 
from a consistency standpoint, to permit them for get/set properties.

This means there is a simple rule: function definition using the keyword 
function always have a bracketed body.  All other forms of function definition 
use ConciseBody which allows for either an assignment expression or a bracketed 
body.

I'm happy to debate this if there is any disagreement, that's why we have spec. 
drafts.  Nothing is set in stone.  

Allen



On May 14, 2012, at 9:31 AM, Erik Arvidsson wrote:

> The latest ES6 draft introduced the notion of a concise function body
> and it is being used for arrow functions as well as for methods and
> set/get accessors.
> 
> Grammar:
> 
> ConciseBody :
>  [lookahead does not include { ] AssignmentExpression
>  { FunctionBody }
> 
> Example:
> 
> var object = {
>  get x() this._x,
>  set x(v) this._x = v,
>  method() this._x
> };
> 
> I don't remember us ever discussing this change?
> 
> Personally I think it makes things more consistent since concise
> function bodies are allowed in ArrowFunction but I've heard people
> complain about it already.
> 
> p.s. Allen, the spec draft has a bunch of ConsiseBody typos.

all fixed...
> 
> -- 
> erik
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
> 

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Concise Function Body

2012-05-14 Thread Brendan Eich
From where is this produced? It's unsound if from MemberExpression 
(ES1-5) or PrimaryExpression (ES6) -> FunctionExpression -> ... ConciseBody.


/be

Erik Arvidsson wrote:

The latest ES6 draft introduced the notion of a concise function body
and it is being used for arrow functions as well as for methods and
set/get accessors.

Grammar:

ConciseBody :
   [lookahead does not include { ] AssignmentExpression
   { FunctionBody }

Example:

var object = {
   get x() this._x,
   set x(v) this._x = v,
   method() this._x
};

I don't remember us ever discussing this change?

Personally I think it makes things more consistent since concise
function bodies are allowed in ArrowFunction but I've heard people
complain about it already.

p.s. Allen, the spec draft has a bunch of ConsiseBody typos.


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Concise Function Body

2012-05-14 Thread Erik Arvidsson
The latest ES6 draft introduced the notion of a concise function body
and it is being used for arrow functions as well as for methods and
set/get accessors.

Grammar:

ConciseBody :
  [lookahead does not include { ] AssignmentExpression
  { FunctionBody }

Example:

var object = {
  get x() this._x,
  set x(v) this._x = v,
  method() this._x
};

I don't remember us ever discussing this change?

Personally I think it makes things more consistent since concise
function bodies are allowed in ArrowFunction but I've heard people
complain about it already.

p.s. Allen, the spec draft has a bunch of ConsiseBody typos.

-- 
erik
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: catch vs function scope; var declaration vs initialization

2012-05-14 Thread John J Barton
On Mon, May 14, 2012 at 3:25 AM, T.J. Crowder  wrote:
>> Inside the catch, the catch-scope is first for reading and writing.
>> But the catch scopes are ignored for declaring new variables. So your
>> expectation seems to be the correct one.
>
>
> That was my analysis as well.
>
> §10.5 tells us that `var` creates bindings in the anonymous function's
> environment, so the function's env has `e`, `o`, and `u` bindings.
>
> §12.14 tells us that within the `catch`, a new environment is created with
> the function's environment being the parent. So the assignment to `e` is to
> the `catch`'s `e`, not the function's.
>
> Annotating that code a bit:
>
> (function(){
>     var e; // Where these actually happen
>     var o;
>     var u;
>
>     try {
>         throw "hi";
>     } catch (e) {
>         e = "ho"; // Assigns to the `catch` env's `e`
>         o = "hu"; // Assigns to the function's `o`
>         console.log(e);
>     }
>     console.log(e, u, o); // Expect undefined undefined "hu"

I believe that -- if we had any practical way to measure this --
'most' web developers would expect 'ho undefined hu'. This is the
sensible output, the one given by ie9. It is sensible because the
simple synopsis of the funky var rules is "variables get values when
assignments are executed".  In my opinion the spec-ed answer here is
less useful to developers than the ie9 answer.  It may be true that
specifications which allowed the sensible answer would result in other
more serious nonsense of course.

jjb


>
> }());
>
> -- T.J.
>
>
> On 14 May 2012 11:11, Peter van der Zee  wrote:
>>
>> On Mon, May 14, 2012 at 11:57 AM, Claus Reinke 
>> wrote:
>> > What should be the output of the following code?
>> >
>> > (function(){
>> >
>> > try {
>> >  throw "hi";
>> > } catch (e) {
>> >  var e = "ho";
>> >  var o = "hu";
>> >  var u;
>> >  console.log(e);
>> > }
>> > console.log(e,u,o);
>> >
>> > }());
>> >
>> > It seems clear that the first console.log should output 'ho'.
>> > Implementations seem to disagree on the second console.log, though.
>> >
>> > From my current understanding of the spec, I expected:
>> >   undefined undefined 'hu'
>> >
>>
>> Inside the catch, the catch-scope is first for reading and writing.
>> But the catch scopes are ignored for declaring new variables. So your
>> expectation seems to be the correct one. `e` is created in the scope
>> of the anonymous function. Likewise, `o` and `u` are created in that
>> scope too (so neither throw at the second console.log). "ho" is
>> assigned to the catch-scope `e`, since that's the first scope in the
>> scope traversal lookup at that point. Catch scopes are weird, yo.
>>
>> - peter
>> ___
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>
>
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: catch vs function scope; var declaration vs initialization

2012-05-14 Thread Allen Wirfs-Brock
undefined undefined hu 

is what should be produced according to the spec. 

Divergence among implementations is a good sign that there is an opportunity to 
clean up this particular mess. 

The current ES6 draft requires an early error for this function because it is 
trying to hoist a var declaration across a block-level declaration of the same 
identifier.  EG,

function f() {
{
let x=1;  //early error let declaration of x in a block that contains a 
nested var declaration of x
{
 var x=2;
}
}
}

Because let is a new feature, this restriction doesn't introduce any backwards 
compatibility issues. However, for consistency, the draft also currently 
applies the same let declaration restrictions to catch parameters.  Your 
experiment suggests that that we might actually be able to to that ...

Allen





On May 14, 2012, at 2:57 AM, Claus Reinke wrote:

> What should be the output of the following code?
> 
> (function(){
> 
> try {
> throw "hi";
> } catch (e) {
> var e = "ho";
> var o = "hu";
> var u;
> console.log(e);
> }
> console.log(e,u,o);
> 
> }());
> 
> It seems clear that the first console.log should output 'ho'.
> Implementations seem to disagree on the second console.log, though.
> 
> From my current understanding of the spec, I expected: 
>   undefined undefined 'hu'
> 
> which I consider unfortunate; especially the first 'undefined'
> was intended to demonstrate the bad effects of separating declaration from 
> initialization while treating catch and function differently, in terms of 
> scoping.
> 
> node, opera: undefined undefined 'hu'
> 
> firefox 12 complains: 'e is not defined'
> 
> ie 9 outputs: houndefinedhu
> 
> It looks as if firefox misses the hoisted declaration of 'e'
> (it doesn't complain about 'u', only about 'e') while ie9 somehow merges the 
> declaration and the catch parameter.
> 
> Claus
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
> 

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Reflect.parse (from RE:typeof null)

2012-05-14 Thread Claus Reinke

it appears that the SpiderMonkey AST has emerged as a de-facto
standard.


Really? I guess there are many more users of Uglify and Esprima is
growing fast. Personally I never heard of any non-Mozilla uses of the
SpiderMonkey API, but perhaps you can point to some.


I was merely stating my personal impression. It is difficult to pin
down all the bits of information that contributed to that impression,
but here are some of them:

- not all JS parsers document their AST, but it appears that the 
   SpiderMonkey AST has the largest number of (partial) 
   implementations; most parsers have their own AST (jslint

   and jshint might share their AST by forking) but
   SpiderMonkey, esprima, PanPG, reflect.js, jstr
   all refer to the same AST document.

   Of those, esprima seems the most active. The combination of
   Reflect.parse awareness and esprima being an efficient cross-
   browser implementation is certainly the reason why I think 
   that this AST spec is in the process of winning.


- even though I've moved to JS relatively recently, I've already
   worked with 3 different JS parsers and have written one myself; 


   it just isn't funny anymore: all of them had different ASTs
   and varying support, and I was still missing out on one popular
   JS parser and its community; so I'm in the process of consolidating
   my JS tool efforts on top of esprima, giving up or porting my 
   own code to gain from collaboration;


- some of the people working with or on esprima have been
   working with other JS parsers before, so I assume they, too,
   prefer convergence and sharing over their previous efforts;
   I expect more tools to be converted for use with esprima;

esprima doesn't try to be anything but an efficient, simple, ES
parser. It doesn't define its own AST, special-purpose code has
been moved out of the main branch, so it just aims to be a
common building block for tool builders.

Having different standards compete in the market has its
advantages, but not for the foundations on which tool-builders
base and share their work. Code implementing the ES grammar 
is such a foundation. 


There isn't much added value to be expected from parsing JS
differently, we just need one good parser, one useable AST
format. Depending on half a dozen parsers with slightly 
different ASTs, just because each was popular at a time when

a different JS tool project was started, is slowing down progress,
and adds to complexity and maintenance costs.

Since I used to be among those asking for an ES standard AST,
I just wanted to join this thread by pointing out that de-facto 
standardizing on esprima (or on the Reflect.parse AST it uses)

appears to offer a pragmatic solution to this problem. For my
own tool building purposes, that is sufficient for the moment.

It would be good if the ES test suite included parser-only tests,
though, so that one could test JS frontends that do not have a JS
engine behind them for conformance to the ES spec grammar.


Also: I think this might be a better topic for the js-tools
http://groups.google.com/group/js-tools?pli=1


As you know, that was one motivation for starting that group.

Claus

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: catch vs function scope; var declaration vs initialization

2012-05-14 Thread T.J. Crowder
>
> Inside the catch, the catch-scope is first for reading and writing.
> But the catch scopes are ignored for declaring new variables. So your
> expectation seems to be the correct one.


That was my analysis as well.

§10.5 tells us that `var` creates bindings in the anonymous function's
environment, so the function's env has `e`, `o`, and `u` bindings.

§12.14 tells us that within the `catch`, a new environment is created with
the function's environment being the parent. So the assignment to `e` is to
the `catch`'s `e`, not the function's.

Annotating that code a bit:

(function(){
var e; // Where these actually happen
var o;
var u;

try {
throw "hi";
} catch (e) {
e = "ho"; // Assigns to the `catch` env's `e`
o = "hu"; // Assigns to the function's `o`
console.log(e);
}
console.log(e, u, o); // Expect undefined undefined "hu"

}());

-- T.J.


On 14 May 2012 11:11, Peter van der Zee  wrote:

> On Mon, May 14, 2012 at 11:57 AM, Claus Reinke 
> wrote:
> > What should be the output of the following code?
> >
> > (function(){
> >
> > try {
> >  throw "hi";
> > } catch (e) {
> >  var e = "ho";
> >  var o = "hu";
> >  var u;
> >  console.log(e);
> > }
> > console.log(e,u,o);
> >
> > }());
> >
> > It seems clear that the first console.log should output 'ho'.
> > Implementations seem to disagree on the second console.log, though.
> >
> > From my current understanding of the spec, I expected:
> >   undefined undefined 'hu'
> >
>
> Inside the catch, the catch-scope is first for reading and writing.
> But the catch scopes are ignored for declaring new variables. So your
> expectation seems to be the correct one. `e` is created in the scope
> of the anonymous function. Likewise, `o` and `u` are created in that
> scope too (so neither throw at the second console.log). "ho" is
> assigned to the catch-scope `e`, since that's the first scope in the
> scope traversal lookup at that point. Catch scopes are weird, yo.
>
> - peter
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: catch vs function scope; var declaration vs initialization

2012-05-14 Thread Peter van der Zee
On Mon, May 14, 2012 at 11:57 AM, Claus Reinke  wrote:
> What should be the output of the following code?
>
> (function(){
>
> try {
>  throw "hi";
> } catch (e) {
>  var e = "ho";
>  var o = "hu";
>  var u;
>  console.log(e);
> }
> console.log(e,u,o);
>
> }());
>
> It seems clear that the first console.log should output 'ho'.
> Implementations seem to disagree on the second console.log, though.
>
> From my current understanding of the spec, I expected:
>   undefined undefined 'hu'
>

Inside the catch, the catch-scope is first for reading and writing.
But the catch scopes are ignored for declaring new variables. So your
expectation seems to be the correct one. `e` is created in the scope
of the anonymous function. Likewise, `o` and `u` are created in that
scope too (so neither throw at the second console.log). "ho" is
assigned to the catch-scope `e`, since that's the first scope in the
scope traversal lookup at that point. Catch scopes are weird, yo.

- peter
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


catch vs function scope; var declaration vs initialization

2012-05-14 Thread Claus Reinke

What should be the output of the following code?

(function(){

try {
 throw "hi";
} catch (e) {
 var e = "ho";
 var o = "hu";
 var u;
 console.log(e);
}
console.log(e,u,o);

}());

It seems clear that the first console.log should output 'ho'.
Implementations seem to disagree on the second console.log, 
though.


From my current understanding of the spec, I expected: 


   undefined undefined 'hu'

which I consider unfortunate; especially the first 'undefined'
was intended to demonstrate the bad effects of separating 
declaration from initialization while treating catch and function 
differently, in terms of scoping.


node, opera: undefined undefined 'hu'

firefox 12 complains: 'e is not defined'

ie 9 outputs: houndefinedhu

It looks as if firefox misses the hoisted declaration of 'e'
(it doesn't complain about 'u', only about 'e') while ie9 
somehow merges the declaration and the catch parameter.


Claus

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss