Generator issue: exceptions while initializing arguments

Brendan Eich brendan at
Sat Sep 8 17:11:00 PDT 2012

Allen Wirfs-Brock wrote:
> On Sep 8, 2012, at 3:51 PM, Brendan Eich wrote:
>> Allen Wirfs-Brock wrote:
>>> On Sep 8, 2012, at 3:20 PM, Brendan Eich wrote:
>>>> SpiderMonkey (Firefox 15 and newer has default parameters):
>>>> js>   function f(a = g) { function g(){}; return a; }
>>>> js>   f()
>>>> function g(){}
>>>> So function g is hoisted and a defaults to it, as expected.
>>> While I agree that the above is reasonable behavior.  It wasn't the consensus that was reach earlier this year at the Jan.  (or may March??) meeting.  What we agreed upon is that default value expressions in parameter lists have visibility to the left and upward in scope but do not have visibility of anything declared within the curlies that surround the body.   So, in the above example, g should be a reference error when evaluated as a default value initializer.
>>> As the NOTE in step 9 of 10-5-3 says:
>>> 	NOTE	Binding Initialisation for formals is performed prior to instantiating any non-parameter declarations in order to ensure that any such local declarations are not visible to any parameter Initialisation code that may be evaluated.
>> You're right, I had forgotten that.
>> Is it well-motivated other than in the naive left-to-right sense, which function hoisting already violates? Perhaps, because parameters to the right are not yet bound.
> Personally, I think the consensus rules create special case anomaly  in the scoping rules that it would be good to avoid.  However, some of the TC39 member had a hard time accepting that the parameter list had visibility into what they perceived as a deeper level of curlies (the function body).  Personally, I would prefer to just think of the parameter list declaration as being logically part of the function body and treat all declaration in that scope contour consistently.

I agree. ES1-5 had no observable scope or hoisting boundaries among 
parameters, or between parameters and body top-level bindings.

I say we re-raise this at the TC39 meeting week after next. What say you?

>> If so, then I can live with it, and g in the f(a = g) bit above would use an outer g, if any (or throw on undefined g).
>> But this still does not mean the implicit |yield;| at entry to generator function should be other than observably "after" parameter defaulting, so that we get the throw at loc 1. Right?
> Right. It just means have to place the initial implicit (almost) yield right at the end of generator declaration


> instantiation and before any user code executes.
> (I have more to say about that in a separate message)
>> IOW, this is a tangent, good to nail down (sorry for prying it up), but not a crucial experiment for generator default parameter semantics.
> Right, it's a separate issue and it's good that you identified that the FF implementation doesn't match the spec.

Indeed the prototype default parameter implementation in Firefox 
(SpiderMonkey) has more of what you and I prefer:

js> function f(a, b=a, c=d, d=d) {return [a,b,c,d]}
js> var d='global'
js> f(1)
[1, 1, (void 0), (void 0)]
js> f(1,2)
[1, 2, (void 0), (void 0)]
js> f(1,2,3)
[1, 2, 3, (void 0)]
js> f(1,2,3,4)
[1, 2, 3, 4]

Note no outer 'd' shows up in the result of f(1,2). When SpiderMonkey 
implements support for undefined as the default-triggering sentinel, 
then we'd have

js> f(1, 2, void 3)
[1, 2, (void 0), (void 0)]
js> f(1, 2, void 3, 4)
[1, 2, 4, 4]

which I prefer on the simpler-to-have-one-contour basis. What do you think?

The TC39 meeting that favored let* (Scheme let*, I mean) binding of 
parameters seems unnecessarily complicated, without a motivating 
use-case, and alient to the rest of the language.


More information about the es-discuss mailing list