May the defineProperty method of a proxy handler throw a TypeError?

Tom Van Cutsem at
Thu May 26 06:36:42 PDT 2011

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 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
the default 'set' trap behavior from being written in Javascript itself,
since it's impossible to specify the value of the 'Throw' parameter
in Javascript.

Option #2 is in line with how the current default 'set' behavior is
specified at <>.


2011/5/25 David Flanagan <dflanagan at>

> 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
> properties.
> 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
> TypeError?
> _______________________________________________
> es-discuss mailing list
> es-discuss at
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list