May the defineProperty method of a proxy handler throw a TypeError?
dflanagan at mozilla.com
Thu May 26 09:44:21 PDT 2011
On 5/26/11 6:51 AM, Sean Eagan wrote:
> Is think it would beneficial to replace all this.* calls in the
> default trap implementations with Object.* methods and syntax that
> subsequently triggers the this.* calls. This would guarantee that
> none of the internal object semantics are being missed, and
> implementations could still optimize just as easily.
With specification text "as if by calling the primordial Object.*
function"? So that user modifications to Object.* are not observable?
traps would not be possible from a module that could not run at
interpreter startup? (That may not be a goal that anyone has, of course.)
Personally, I think that proxies would be easier to reason about if no
distinction was made between fundamental and derived traps. I'd put that
distinction in an abstract Proxy.Handler class and then rename the
current Proxy.Handler to Proxy.ForwardingHandler.
> On Thu, May 26, 2011 at 8:36 AM, Tom Van Cutsem<tomvc.be at gmail.com> wrote:
>> Hi David,
>> The short answer: if you also define a 'set' trap, throwing a TypeError from
>> defineProperty() to signal rejection is appropriate.
>> The longer answer:
>> defineProperty() is based on [[DefineOwnProperty]] (ES5 section 8.12.9)
>> whose rejection behavior depends on an explicit 'Throw' parameter, just like
>> [[Put]] and [[Delete]]. Why then, do set() and delete() return a boolean
>> success flag to determine their rejection behavior, while defineProperty()
>> does not?
>> I believe that, until now, we were convinced that in the case of proxies,
>> defineProperty() actually does _not_ depend on strict mode, because the
>> built-in Object.defineProperty and Object.defineProperties methods (ES5
>> section 22.214.171.124-7) call the built-in [[DefineOwnProperty]] method with its
>> 3rd argument 'Throw' set unconditionally to 'true', meaning it should never
>> reject silently, independent of the strictness of the code.
>> However, checking other parts of the spec where [[DefineOwnProperty]] is
>> invoked, I now notice it's also invoked by [[Put]], which passes its own
>> 'Throw' argument to [[DefineOwnProperty]], and this time, the 'Throw'
>> argument is dependent on strict mode. This complicates matters because of
>> derived traps.
>> If a proxy handler does _not_ define a 'set' trap (which is derived), the
>> proxy implementation will fall back on the fundamental defineProperty()
>> trap, whose rejection behavior in that context now _should_ depend on strict
>> mode. However, the current defineProperty() API doesn't allow the programmer
>> to express this.
>> I see two options here:
>> 1) modify the defineProperty() trap such that it also returns a boolean flag
>> to indicate rejection, like set() and delete(). This is still possible as
>> defineProperty() currently has no useful return value.
>> 2) specify unambiguously that defineProperty() on proxies should always
>> reject explicitly by throwing a TypeError, even if the defineProperty() trap
>> was called as part of the default 'set' trap.
>> This can be justified if we specify that the default 'set' trap invokes the
>> 'defineProperty' trap as if by calling "Object.defineProperty", which is
>> specified to never reject silently.
>> Option #1 would most closely follow the current ES5 spec, but would disallow
>> since it's impossible to specify the value of the 'Throw' parameter
>> Option #2 is in line with how the current default 'set' behavior is
>> 2011/5/25 David Flanagan<dflanagan at mozilla.com>
>>> I'm using a proxy to implement the DOM NodeList interface. A NodeList
>>> object is array-like and has read-only, non-configurable array index
>>> In my handler's set() and delete() methods, I just return false if an
>>> attempt is made to set or delete an indexed property.
>>> The defineProperty() method is not parallel to set() and delete(),
>>> however. I can't just return false, since the return value is ignored. And
>>> I can't tell from the proposal whether I am allowed to throw a TypeError
>>> from this method. In getOwnPropertyDescriptor() I know that I have to lie
>>> and return a descriptor with configurable:true for the indexed properties.
>>> So in defineProperty() should I just silently ignore any attempts to set an
>>> indexed property, or should I actively reject those attempts with a
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>> es-discuss mailing list
>> es-discuss at mozilla.org
More information about the es-discuss