May the defineProperty method of a proxy handler throw a TypeError?
david.bruant at labri.fr
Fri Jun 17 15:05:52 PDT 2011
Le 26/05/2011 15:36, Tom Van Cutsem a écrit :
> 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 184.108.40.206-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 the default 'set' trap behavior from being written in
> Option #2 is in line with how the current default 'set' behavior is
> at <http://wiki.ecmascript.org/doku.php?id=harmony:proxies#trap_defaults>.
What about adding a "throw" argument to the defineProperty trap (and any
trap for which the equivalent internal method has a "throw" argument) ?
The engine would set the boolean value correctly depending on strict
mode or any relevant parameter. Trap writers can adapt their behavior
based on this boolean.
More information about the es-discuss