Real World Func Decl in Block Scope Breakages

Brendan Eich brendan at mozilla.com
Thu Dec 27 23:49:14 PST 2012


Charles McCathie Nevile wrote:
> On Thu, 27 Dec 2012 00:26:48 +0100, Brendan Eich <brendan at mozilla.com> 
> wrote:
>
>> Brian Terlson wrote:
>>> 20 sites, however, will likely be broken by this change in some way.
>
> I am guessing this is the key point. But there is a scope error, and 
> "this" is undefined. It seems you're trying to find out why we are one 
> of the few sites that do *something*, because you'd like to change 
> something in ES that would break what we are doing, right? I am not 
> sure exactly what the *something* or the change are, and that makes it 
> hard for me to find the person who knows the answer (yes, folks, I 
> confess that I didn't write this particular bit of code and haven't 
> even carefully deconstructed it in my head.... ;) ).
>
> So, any more clues? (No list-archive header to follow :( I can of 
> course search, but someone here might be able to give a better reply 
> more efficiently).

Sure, and sorry for lack of context.

The issue is that

    function foo() { return 42; }

and

   var foo = function() { return 42; }

and variations on the latter function expression syntax are all 
standardized. However,

   if (cond) {
     function bar() { return 43; }
   }
   console.log(bar());

is not standardized. This syntax is not produced the any ECMA-262 
standard grammar, but it is supported by all major implementations, with 
varying semantics. Call it function-in-block (f-i-b for short).

In IE and browsers that reverse-engineered IE JScript's implementation 
of f-i-b, bar is hoisted whether cond evaluates to truthy or falsy, so 
the console.log(bar()) always works.

In SpiderMonkey in Firefox and other apps, only if cond evaluates to 
truthy will bar be defined, leaving the bar() call within the 
console.log(bar()) expression possibly failing due to bar not being 
found in the scope chain, or resolving to an outer bar that might not be 
callable.

>>> There is also a chance that the tool used to identify breakages has 
>>> missed some code that will breka.
>>>
>>> Below are some examples of code on the web today that will be 
>>> broken. For each I include a snippet of code that is heavily edited 
>>> in an attempt to convey the pattern used and the developer intent. I 
>>> also attempt to identify what functionality will actually be broken.
>
> What is the proposed change?

ES6 proposes that f-i-b always bind bar in the nearest enclosing 
curly-braced block, hoisted in the manner of function in JS today but to 
block scope, not function or program scope, so that the function can be 
used in expressions evaluated before control flows to evaluate the 
declaration of bar.

This means the example can fail if !cond. Only within the "then" block 
(anywhere, thanks to hoisting) could one safely use bar to mean the 
function declared within that block.

Clearly we had an incompatible change in mind. The fallback if we can't 
get away with this compat-break is to have ES6's f-i-b semantics only 
under "use strict" and have the old mess (browser-dependent) in 
non-strict ("sloppy") mode code.

Any help you can give on the one of 20 hard cases Brian found will be 
gratefully received.

/be


More information about the es-discuss mailing list