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


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 claus.rei...@talk21.com 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


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: 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 t...@crowdersoftware.com 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 e...@qfox.nl wrote:

 On Mon, May 14, 2012 at 11:57 AM, Claus Reinke claus.rei...@talk21.com
 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 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: 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 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 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