8.12.4 CanPut

2010-04-19

Boolean [[CanPut]](P:String)

Can a property P be added to this object O?

Code: (Abstract Ecma)
function [[CanPut]](P){
var desc = this.[[GetOwnProperty]](P);
if (desc !== undefined) {
if (!IsAccessorDescriptor(desc)) {
if (desc.[[Set]] === undefined) return false;
return true;
} else { // desc must be data descriptor? why not generic?
return desc.[[Writable]];
}
}
var proto = O.[[Prototype]];
if (proto === null) return O.[[Extensible]];
var inherited = proto.[[GetProperty]](P);
if (inherited === null) return O.[[Extensible]];
if (IsAccessorDescription(inherited)) {
if (inherited.[[Set]] === undefined) return false;
return true;
}
// else inherited must be a Data Descriptor (why not Generic?)
if (O.[[Extensible]] === false) return false;
return inherited.[[Writable]];
}


This is quite an elaborate function.
It first checks whether O has an own property P. It first checks whether P is a data or accessor property. For accessor properties, the method returns true if the property has a [[Get]] method, false otherwise. For data properties the value of O[P].[[Writable]] is returned, because this determines whether you may change any attribute of P at all.
When there is no own property, it gets an inherited property. If there's an accessor property, the same happens as above. Otherwise the result will be a data property (even if there is no such property). In that case false is returned if O.[[Extensible]] is false (because you are about to create an own property because you didn't find one yet, remember?). Otherwise the result of O[P].[[Writable]] is returned.

Note that host objects may add additional constraints to [[Put]]. Those objects should not allow a [[Put]] where this definition of [[Put]] does not allow it.