[[CanPut]] semantics
Oliver Hunt wrote:
My reading of [[CanPut]] implies that it only checks a single level of the prototype chain. This seems incorrect to me but I thought I'd check whether it is in fact intentional, or whether it's a spec bug.
See step 4 and later.
/be
ES5.1 8.12.4 [[CanPut]] (P)
When the [[CanPut]] internal method of O is called with property name P, the following steps are taken:
- Let desc be the result of calling the [[GetOwnProperty]] internal method of O with argument P.
- If desc is not undefined, then a. If IsAccessorDescriptor(desc) is true, then i. If desc.[[Set]] is undefined, then return false. ii. Else return true. b. Else, desc must be a DataDescriptor so return the value of desc.[[Writable]].
- Let proto be the [[Prototype]] internal property of O.
- If proto is null, then return the value of the [[Extensible]] internal property of O.
- Let inherited be the result of calling the [[GetProperty]] internal method of proto with property name P.
- If inherited is undefined, return the value of the [[Extensible]] internal property of O.
- If IsAccessorDescriptor(inherited) is true, then a. If inherited.[[Set]] is undefined, then return false. b. Else return true.
- Else, inherited must be a DataDescriptor a. If the [[Extensible]] internal property of O is false, return false. b. Else return the value of inherited.[[Writable]].
Host objects may define additional constraints upon [[Put]] operations. If possible, host objects should not allow [[Put]] operations in situations where this definition of [[CanPut]] returns false.
- Let inherited be the result of calling the [[GetProperty]] internal method of proto with property name P.
Gah, [[GetProperty]] not [[GetOwnProperty]] -- and we don't care about prototype extensibility? (i think we came to that conclusion in redmond?)
Oliver Hunt wrote:
- Let inherited be the result of calling the [[GetProperty]] internal method of proto with property name P.
Gah, [[GetProperty]] not [[GetOwnProperty]] -- and we don't care about prototype extensibility? (i think we came to that conclusion in redmond?)
Right, see step 6. If there's no inherited property, we're extending the direct object (O, below). Prototype extensibility should not matter.
If there's an inherited accessor without [[Set]], no go; if with [[Set]], we're good to go.
If there's an inherited data property, we need to check its [[Writable]] attribute, but first (8a) we must check O's [[Extensible]] attribute, because at this point if we can write to shadow the inherited data property, then we will be extending O.
On Sep 14, 2012, at 7:05 PM, Brendan Eich wrote:
Oliver Hunt wrote:
My reading of [[CanPut]] implies that it only checks a single level of the prototype chain. This seems incorrect to me but I thought I'd check whether it is in fact intentional, or whether it's a spec bug.
See step 4 and later.
It's worth noting that the refactored [[Put]] algorithm at < harmony:proto_climbing_refactoring#refactoring_put> (which should be behaviorally equivalent to the ES5 [[Put]] algorithm for built-in objects) gets rid of [[CanPut]] and makes the proto-chain walk much more explicit (see [[SetP]] steps 3,4 and 5).
I hope we can get these refactored algorithms in an ES6 draft soon. They're some of the more fundamental algorithms of ECMAScript, so having more eyeballs to scrutinize these algorithms would be good.
My reading of [[CanPut]] implies that it only checks a single level of the prototype chain. This seems incorrect to me but I thought I'd check whether it is in fact intentional, or whether it's a spec bug.