[Harmony proxies] Opinion on the open issue (How to deal with inconsistent data returned by handler traps?)

David Bruant david.bruant at labri.fr
Tue Mar 22 11:04:36 PDT 2011

Le 22/03/2011 13:12, Tom Van Cutsem a écrit :
> 2011/3/18 David Bruant <bruant at enseirb-matmeca.fr
> <mailto:bruant at enseirb-matmeca.fr>>
>     Le 16/03/2011 10:25, Tom Van Cutsem a écrit :
>>     David,
>>     This open issue is indeed one that merits further discussion here.
>>     Some thoughts and comments:
>>     * I think we did come to an agreement that custom property
>>     attributes were seen as very useful for communicating new kinds
>>     of meta-data about objects, and that they ought to be preserved.
>>     See also this bug:
>>     <https://bugzilla.mozilla.org/show_bug.cgi?id=601379>
>>     That would solve one of the issues you raise.
>     Ok. I'll follow on the bug.
>     However, from what I understand, it (and the current
>     Object.defineProperty semantics) does not fully let the user to
>     define his/her attributes names and semantics.
>     In the proxy semantics strawman, Object.defineProperty step 3:
>     "Let desc be the result of calling ToPropertyDescriptor with
>     Attributes as the argument."
>     The /ToPropertyDescriptor/ call normalizes 'configurable',
>     'enumerable', 'writable' to booleans and throw if 'get' or 'set'
>     isn't callable. This prevents people from passing differently
>     typed values.
> Right, this is following the current ES5 semantics of
> Object.defineProperty.
>     I think we need the other communication side too.
>     [[GetOwnProperty]] calls /ToCompletePropertyDescriptor/ which also
>     calls /ToPropertyDescriptor/. So if I want to use a different type
>     for the usual attribute names (which, in my opinion, are common
>     names), I cannot. Moreover, the property descriptors returned by
>     Object.getOwnPropertyDescriptor are forced to have an 'enumerable'
>     and 'configurable' property (and others depending on data or
>     accessor descriptor). If I want to decide my own
>     attributes&semantics and do not care about the "forced" one, then
>     I am paying a performance/semantics overhead for no obvious
>     reason. This can be annoying if I want to return a proxy as the
>     property descriptor or if I want to iterate over property
>     attributes through a for-in loop or
>     Object.getOwnPropertyNames+Array method (forEach, every, reduce...).
>     What is your position on this point? Is there also a bug number
>     for this one?
> There is no bug report for this as far as I can tell. I have no strong
> opinion on the coercion of standard property attributes. Coercing is
> closest to the current ES5 behavior, though. Also, I'm not convinced
> that programmers should be able to redefine the meaning of the
> standard property attributes. The standard attributes have a
> well-defined meaning, and they are an implicit part of the
> Object.defineProperty/getOwnPropertyDescriptor/... API.
I wouldn't argue if we had: Object.defineDataProperty(o, name,
enumerable, configurable, writable, value) and
Object.defineAccessorProperty(...). Or one Object.defineProperty with
ten arguments. But this is not the case.
I think that part of the reason why the commitee has agreed on an object
rather than another solution is to have the liberty of providing
different flavors (there are currently two with data and accessor, maybe
a third will show up eventually) and different attributes one day or
another. (Can someone from TC39 can provide insights on the property
attribute API design?)
Based on this rationale, I think that since proxies have the potential
entirely redefine their internal consistency, it could make sense to
completely forget about usual semantics of attributes. This actually
could be an interesting way to drive innovation and maybe that relevant
property attribute semantics patterns made by library authors could
eventually be added to the spec.

> Won't redefining their semantics be needlessly confusing?
I cannot answer that question. It will depend on people. For the
comparison, I would ask:
How confusing would it be if a host objects redefined property attribute
semantics? I'm going to provide a response below.

>>     * The place where argument/return value validation is most
>>     critical is where fundamental traps are called by the runtime
>>     itself, not by client code, because of a missing derived trap.
>>     The question here is: how should the default implementation of a
>>     derived trap deal with inconsistent data returned by the
>>     fundamental trap on which it relies?
>     The way I see it, default implementations of derived traps are
>     just a convenience. In my opinion, they should be the exact
>     reflection of their related ECMAScript object method/internal
>     method and not do more data validation/formatting than these do.
>     As a convenience, proxy programmers should be aware of limitations
>     and conventions in default implementation expectations. We can
>     document them, it won't be hard at all.
>     And if programmers decide to not respect the conventions in what
>     they return from their fundamental traps, then they are exposing
>     themselves to inconsistencies. Either they accept it and consider
>     that as feature and not bug or they can always implement derived
>     traps if they aren't satisfied with how the default derived trap
>     behaves.
>     No matter what is decided for derived traps default
>     implementations (current spec, current spec + data
>     validation/formatting, other spec), there are going to be people
>     for which this doesn't fit their use cases, so they will have to
>     re-implement them. So I would be in favor of having default
>     implementations which are consistent with ES objects behavior and
>     perform no further checks (which will also improve performance).
>     I would like to point out that internal data validation/massaging
>     is always surprising from the programming/debugging point of view.
>     A programmer doesn't always know the restrictions ("I returned
>     duplicates in the get(Own)PropertyNames trap and they've been
>     removed! How so?", etc.)
> I fully agree. On the other hand, it may be equally surprising for a
> programmer to find out that Object.getOwnPropertyNames(obj) may
> contain duplicate property names.
> It's not clear to me which side is more important. However, there will
> probably be much more "client code" using proxies than code creating
> proxies.

About the surprising aspect, I am going to take the example of an host
object: NodeLists. NodeLists (returned by
document.getElementsByTagName() ) are live objects. It means that once
you have created it, it stays in sync with the DOM tree without the
programmer having to refresh the object in any way. This behavior cannot
be provided by any regular object. So programmers could something
equivalent to:
var divs = document.getElementsByTagName('div');
for(var i; i< divs.length ; i++){
    document.appendChild( divs[i].cloneNode );
Because of the live property, divs.length changes and this turns out to
be an infinite loop. This is surprising to the programmer since live
objects do not exist in ES3/5. What solves the surprise is that the
programmer searches, discover the live property of NodeLists and fixes
the bug. There is a surprise, it may be annoying, frustrating, but it
doesn't last long.
My opinion is that no matter what library you're loading and what crazy
sort of proxies you're loading, these things will come with some
documentation explaining differences with regular objects ("under such
condition, we will return duplicate property names after a
Object.getOwnPropertyNames call"). If the documentation is lacking, you
still have the source code. In a way or another, the source of your
surprise can find its cause. When you choose a proxy library, you know
it won't behave like regular objects. This is for the case where you
purposefully import a library/module of some sort.
If you haven't loaded the module on purpose, well, I think that being
surprised by object behaviors may be the least of your concerns :-)
I think I do not really understand what is inherently wrong with
"surprising" the programmer who has chosen to run your code. The
programmer who has chosen your library did it with

Proxies offer the potential to break properties. Even elementary things
o.a = 2;
b = o.a; // b === 1 (or undefined or "whatever")
Even though there is normalization of property attributes, you, as a
proxy writer, has the Turing-complete freedom to deny the usual
semantics of these attribute by defining your own internal consistency.
As soon as you write "defineProperty: function(name, desc) {}" (emphasis
on the /function/ keyword) in your handler no one can ever have any
control over you to make sure you properly extract "enumerable" and
"configurable" and give them proper semantics. Forcing these properties
to be part of a property descriptor without being able to enforce that
they are going to be used as they are in regular objects sounds like an
half-enforcement. And you certainly agree that the second part of the
enforcement is just unreasonably complicated (if not impossible).

Proxies will break things. Proxies will be surprising. Proxies will be
confusing. It's part of what they are. It's built-in or rather
"to-be-built-in". But I think it won't last for long, like with DOM live
objects (or any other tricky host object). Libraries which do not show
enough consistency ("internal consistency", not "consistency with
regular objects") won't be widely used. For the comparison, it's not
that difficult to understand with NodeLists that they are in sync with
the DOM tree. This is one "consistent enough" internal consistency.
My opinion is that the Proxy API should encourage rich internal
consistencies as much as possible. And trying to keep consistency with
what we know of current regular objects interfers with that vision. Once
again, that's just my opinion, I don't mean to impose it in any way. (I
do not have any power to impose it anyway :-p ).


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110322/a8ba24ae/attachment.html>

More information about the es-discuss mailing list