ToPropertyDescriptor and [[DefineOwnProperty]], regarding Object.defineProperty

Brendan Eich brendan at mozilla.com
Mon Jun 1 16:39:56 PDT 2009


On Jun 1, 2009, at 1:47 PM, Allen Wirfs-Brock wrote:

> Jeff Walden wrote:
>> 0. Throughout this email any reference to a "property descriptor"  
>> refers
>> to the specification type, not to the reification of one as exposed  
>> by
>> Object.getOwnPropertyDescriptor or to the object taken as an  
>> argument by
>> ToPropertyDescriptor.
>
> The main reason we needed to deal with such partial property  
> descriptors is to enable the use case of Object.defineProperty where  
> someone wants to set the state of some specific attribute of an  
> already existing property.

Hi Allen -- please note regarding this mail that I'm not proposing any  
change to draft ES5. Possibly Jeff's mail could lead to informative  
material rationalizing the particular API design decision noted below,  
so that others won't run into the same issue. It does seem that the  
ability to "define" an existing property in order to change its  
attributes is the source of this issue (apologies if I missed it in  
your rationale doc).


>  We wanted to enable a programmer to, for example, write:
> 	Object.defineProperty(myObj,"myProp", {configurable:false});
> Rather than:
> 	var desc= Object.getOwnPropertyDescriptor(myObj,"myProp");
> 	desc.configurable=false;
> 	Object.defineProperty(myObj,"myProp", desc);

You could imagine an alternative where Object.changeProperty were  
specified, and it insisted on a name parameter identifying an existing  
property, and more intuitively tolerated a partial property  
descriptor. The "defineProperty" name suggests an all-or-nothing act  
of creation (replacing an previous property, perhaps). This is how  
"define" is generally used in ES1-3 and other specs and languages.

With getters and setters, some ambiguity crept into certain contexts,  
e.g. __defineGetter__ and __defineSetter__ may both be called with the  
same |this| object and name parameter, to define the two "halves" of  
an accessor property. This looks like the precedent for  
Object.defineProperty both "creating" and "accumulating" or "changing"  
attributes.


> If we are going to allow such modification of individual attributes  
> (or subsets of attributes) then we need to specify the acceptable  
> attribute transformations for an existing property.  That is  
> specified by the algorithm steps of [[DefineOwnProperty]].

It's true that a "funnel" into which all control flows, which leads to  
the decision logic to update or create a property, exists in any  
alternative scheme. The only issue here, it seems, is API veneer,  
specifically the number of Object methods and the connotation of verbs  
in API names.


> Note the such partial descriptors primarily come from  
> Object.defineProperty via ToPropertyDescriptor. Within the actual  
> specification we have generally tried to use write populated  
> property descriptors in situations where we need to explicitly  
> specify the attributes of a property. ToPropertyDescriptor adds  
> another layer of complexity that logically is really part of  
> Object.defineProperty/defineProperties and is necessary to ensure  
> that the user hasn't specified bogus values for the various  
> properties.

This too can't be avoided with Object.changeProperty, unless that  
method were to split into a painfully large set of methods for  
changing each possible attribute or internal property -- and then we'd  
lose atomicity. These issues, IIRC, are in the rationale doc.


> I agree that the rules of [[DefineOwnProperty]] are fairly complex.   
> I originally used a decision table to work out what they needed to  
> be. I don't see any good way to reduce this complexity without  
> eliminating support for the motivating use case for partial  
> descriptors in Object.defineProperty.

One plausible change would be to make Object.defineProperty always  
create a new property (throwing if one already exists), and add  
Object.changeProperty which would require an existing property.

But this seems more complex due to the two APIs and error conditions.  
So again I'm content with the current design, but interested in what  
kind of informative prose we could add to the spec (not too much) to  
clarify this design decision.

/be


More information about the es-discuss mailing list