[Harmony Proxies] Default trap implementations should be non-normative

Sean Eagan seaneagan1 at gmail.com
Tue May 31 10:04:38 PDT 2011


Problem:

There have been two main justifications for having the default trap
implementations:

* To prove ES implementability
* To provide a starting point to slightly tweak a trap's behavior.

However, all that is required to achieve these goals is that default
trap implementations exist, not that they be normatively specified
within the spec.  We have already seen a number of questions around
the consistency of default trap implementations with the internal
method pseudocode e.g. [1], [2].  It is likely that such issues will
keep popping up even after ES.next is finalized.  If default trap
implementations are included within the spec, any such issues found
will remain unfixed until the next spec.  Also, proxies have entirely
separate internal methods than the standard implementations, which
creates two problems:

1) proxies do not inherit alternate internal method implementations.

For example, functions have an alternate [[Get]] implementation
(15.3.5.4), and this is not reflected in the default "get" behavior of
function proxies.  Also, array proxies could be useful as well, and a
similar issue would be encountered there since they override the
[[DefineOwnProperty]] internal method.

2) duplication of internal method behavior in the spec

The only thing that should be different about the internal method
behavior of proxies is that the proxy's traps should be used when they
exist, instead of the default behavior.  So why should we duplicate
the logic that is the same for both proxies and non-proxies by having
separate internal method implementations which subsequently call
default trap implementations which are just intended to match the
behavior of the standard implementations.  This duplication causes
unnecessary burden in maintaining the spec, introduces
inconsistencies, and most importantly makes the spec less clear since
the reader needs to determine which proxy semantics are just
duplicating the standard semantics, and which are different.

Solution:

Encapsulate the trapping behavior in an internal [[Trap]] method:

[[Trap]] (Name, Arguments, Throw)

When the [[Trap]] internal method of O is called with trap name Name,
arguments list Arguments, and Boolean flag Throw, the following steps
are taken:

1.  If O does not have a [[Handler]] internal property return [false].
2.  Let handler be the value of the [[Handler]] internal property of O.
3.  Let trap be the result of calling the [[Get]] internal method of
handler with argument Name.
4.  If trap is undefined, return a List whose first element is false.
5.  If IsCallable(trap) is false, then
    a.  If Throw is true throw a TypeError exception.
    b.  return a List whose first element is false.
7.  Return trap.
6.  Return a List whose first element is true, and whose second
element is the result of calling the [[Call]] internal method of trap
providing handler as the this value and Arguments appended with O as
the arguments.

Then update the proxy semantics [3] such that proxies just use the
standard internal method implementations which are updated to call
[[Trap]].  For example, the standard [[Get]] implementation ( 8.12.3 )
which corresponds to the optional "get" trap, could be updated to
support proxies by merely prepending these two steps:

1. Let hasTrap be the first element and trapReturn be the second
element of the result of calling the [[Trap]] internal method of O
with arguments "get", a List with only element P, and false.
2. If hasTrap is true, return trapReturn.

The function [[Get]] implementation (15.3.5.4) can prepend the same
steps only replacing O with F.  Generally, it will be slightly more
complicated than prepending steps, but not by much.  For example, the
standard [[Delete]] implementation ( 8.12.7 ) which corresponds to the
required "delete" trap, could be updated to the following:

[[Delete]] (P, Throw)

When the [[Delete]] internal method of a trapping proxy O is called
with property name P and the Boolean flag Throw the following steps
are taken:

1. Let hasTrap be the first element and success be the second element
of the result of calling the [[Trap]] internal method of O with
arguments "delete", a List with only element P, and true.
2. If hasTrap is true
  a. Let success be ToBoolean(success)
3. Else
  a. Let desc be the result of calling the [[GetOwnProperty]] internal
method of O with property name P.
  b. If desc is undefined, then return true.
  c. Let success be the value of desc.[[Configurable]].
  d. If success is true, remove the own property with name P from O.
4.  If success is false, then
  a. If Throw, throw a TypeError exception
  b. Return false.
5.  Return true.


[1] http://wiki.ecmascript.org/doku.php?id=strawman:proxy_set_trap
[2] https://mail.mozilla.org/pipermail/es-discuss/2011-May/014717.html
[3] http://wiki.ecmascript.org/doku.php?id=harmony:proxies_semantics


Thanks,
Sean Eagan


More information about the es-discuss mailing list