archives

« Bugzilla Issues Index

#3385 — Require that the mandatory parameter to object literal setter syntax not have an overall default


The grammar for a setter in an object literal is:

> MethodDefinition [Yield] :
> ...
> set PropertyName ( PropertySetParameterList ) { FunctionBody }

And we have

> PropertySetParameterList :
> FormalParameter

and then

> FormalParameter [Yield,GeneratorParameter] :
> BindingElement [?Yield, ?GeneratorParameter]

and then

> BindingElement [Yield, GeneratorParameter ] :
> SingleNameBinding [?Yield, ?GeneratorParameter]
> [+GeneratorParameter] BindingPattern [?Yield,GeneratorParameter] Initializer [In]opt
> [~GeneratorParameter] BindingPattern [?Yield] Initializer [In, ?Yield]opt

and

> SingleNameBinding [Yield,GeneratorParameter] :
> [+GeneratorParameter] BindingIdentifier [Yield] Initializer [In]opt
> [~GeneratorParameter] BindingIdentifier [?Yield] Initializer [In, ?Yield]opt

Every expansion of BindingElement permits an initializer. But setter method syntax is unique and unusual in that it is specifically tailored to setters, in that exactly one argument must be present. No provision is made for the setter being a general function taking any number of arguments other than 1. Given that precedent and the ongoing existence of PropertySetParameterList, it seems strange that top-level initializers are permitted here.

Instead of the current grammar, I think we should instead have

PropertySetFormalParameter :
BindingIdentifier
BindingPattern

to restrict this argument to a name or a destructuring pattern *without* an initializer. (Note that nested initializers would still be fine with this, as in the following example -- this just prohibits an initializer for the single argument passed to the setter.)

var API =
{
_count: 0,
_rational: true,
set options({ count = 17, rational = true }) {
this._count = count;
this._rational = rational;
}
};
API.options = { count: 25 }; // would imply rational = true


But, default parameter value initializes are also trigger by passing the value undefined. So you might reasonably say:

var o={set foo(value=null) {doSomething(value)}};
o.value = undefined; //null gets passed to doSomething

It since use cases like this are possible, it seems reasonable to not try to special case away the initializer. Even though it will be very infrequently used. Fewer special cases is better.


Oh, right, I forgot that defaults aren't just for not-present arguments (a decision I don't particularly like, but whatever). Never mind then.