Thanks for your response.
I understand your point. You say that we should open up everything, because
authors will be responsible users and because freedom brings more
possibilities. I’m not against opening everything, but does it have a sense ?
I’m also involved in the www-style mailing list, and we’ve seen there many
attempts to bring new things to the CSS language. Many times, however, the
proposals are not followed by true changes, and even some initially appraised
specifications sometimes finish in the tourment. Because use cases where not
correctly defined, and because the specification has become hazardous and
difficult to implement, while the main use cases could require something a lot
simpler.
We should consider here the questions we need to answer each time we’re going
to change anything to a language: What are our goals when doing this addition?
Which use cases are we supporting? Will it really bring more good than bad? Is
there not something we can do to make things easier? Without use cases,
implementing a feature is an hazardous action, which don’t lead to the expected
results. Among the use cases presented of the site, none would benefit from a
separate getPropertyName (or has or ...) implementation.
While I remove my proposal to replace the true prototype by a function, I’m
still staying strong on what I said. Is there any use case that could justify
to allow to redefine the fundamental meaning of functions like
Object.getPropertyNames? Does our users really want to worry about possible
inconsistencies of getOwnPropertyNames and getPropertyNames ? If yes, what is
the reason ?
I suppose that you realize that by allowing has and (chained) hasOwn to have
different results, you forces users to rely on their own methods to determine
if a property exists? Or, at least, you assume that code written today may not
work as expected tomorrow because it used hasOwn and not has. With such a
change, we are consciently making the core functionnalities of ES5 potentially
inconsistents. Just because it sounds beautiful to open up everything. What
amazes me is that, however, everybody seems conscient that redefining === and
typeof is not a good thing. And with no other arguments than consistency.
Saying that people are good developers, that they will be attentive to avoid
breaking anything, all this is pure utopy. People are humans. They do errors.
They are not omniscient. Even more, some are intentionally evil. The best help
you could give to developers is to keep things simple and help them making good
code by avoiding things they are not likely to do but that could confuse them.
Because getPropertyNames is not used often, and a mistake in the code written
for its accessor may well stay unnoticed for years, but have important
consequences after.
Yes, I meant that by removing some of the consistency of ECMAScript, you’re
moving to a dangerous way. But my point is not that it should not be done.
Discovering the United States was the reward of a dangerous journey. However,
nobody should engage in a dangerous way if it has no reason to do so. So, I
repeat my question: what are the use cases we’re wanting to solve by exposing
access to both getOwnPropertyNames and getPropertyNames ? I humbly think they
are no use cases. It’s up to everyone to show they are use cases. But it should
be done.
By adding possible inconsistency to ECMAScript, this spec seems to fail at
their own goals. No matter what you’re saying, the driving forces of the
proposal are meant to be simplicity and consistency (following ES5
conventions). Power isn’t written down anywhere on the spec. It’s not clear to
me how being able to define both getPropertyName and getOwnPropertyNames is a
gage of consistency. Consistency is to say that getPropertyNames returns a list
containing the property of an object and its prototype chain. It’s simple.
There’s no exception. There should be no other defintion of getPropertyNames
that should be on the table if there’s not a reason for it (sorry for
repeating, but it’s important to me).
On the other side, a proxy could redifine getOwnPropertyNames. Well, the
properties we’re talking in getOwnPropertyNames are their own properties. It
seems normal the proxy can choose to expose those or not, or event invent them.
But it should not have an impact on the prototype properties when
getPropertyNames is called.
Maybe the best thing I can do to end up this mail is to cite Allen Wirfs-Brock :
For these reasons, any major proposal to extend JavaScript needs to be
critically examined for its impact upon the existing JavaScript object mode.
If the extension requires a major change to the object model, it may be
difficult for programers to understand and use. For implementers, even seemly
simple object model changes may require significant redesign of existing
optimization mechanisms and the invention of new techniques.
I’m not asking anything different. If there’s a reason to allow the redifine
getPropertyNames, it should be done. But is there a reason ? This is my
question.
Regards,
François
From: David Bruant
Sent: Sunday, January 23, 2011 7:29 PM
To: François REMY
Cc: es-discuss ; Mark S. Miller
Subject: [ES Harmony Proxies] Different points on proxies ground (was:
Fundamental trap definition)
Hi,
Since your response does not really answer my point (definition of fundamental
traps), I take the responsibility to change the title and provide an answer.
I am not an ECMAScript expert and not involved in the TC-39 commitee, but here
are my answers.
Overall, I think (I may be wrong) that you're confusing two different concepts
which are :
- ECMAScript objects which are "regular objects", a set of properties with all
the semantics that we are all used to and which any programmer can create
through "new Object()" (or "{}" for lazy people like myself);
- The Object Type (ECMAScript 5 section 8.6) in the broad sense which includes
"regular objects", "host objects" and maybe soon proxies.
The former are an "instanciation" of the latter with the semantics that is
defined in ES5 section 8.12 (Algorithms for Object Internal Methods). Proxy
will be one with programmer-defined semantics.
As far as I understand proxies, they are not designed to provide garantees
toward acting the same way as regular objects do (even for the prototype chain
behavior). They aim at allowing the programmer to FULLY redefine in ECMAScript
the semantics of operations on object besides some core operations (typeof,
===, Object.getPrototypeOf, instanceof, am I forgetting one?) which are some
core garantees that define the object type (ES5 section 8.6) identity.
Actually, as I am writing it, I am realizing that only "typeof" and "===" are
really part of the object type identity.
But it can be read
(http://wiki.ecmascript.org/doku.php?id=harmony:proxies#interaction_with_instanceof)
that 'Object.getPrototypeOf' ([[Prototype]]) isn't trapped because it would
provoke an inconsistant behavior for instanceOf
and 'instanceof' have been decided to not be trapped because of a security
issue.
I think that the main idea behind proxies isn't consistency. It's power. In
"Harmony of my dreams" (http://brendaneich.com/2011/01/harmony-of-my-dreams/),
Brendan Eich's quotes Guy Steele on language growth:
"We need to put tools for language growth in the hands of the users.". First i
agree with this and second of all, proxies are going in that direction.
I share your concern that it's a powerful and then dangerous feature for
consistency's sake, but "with great power, comes great responsibility". It's up
to the people who are going to use proxies to be careful to be coherent with
what they pretend to do. And there are already some mecanisms that helps
consistency like derived traps or even the Default Proxy forwarding handler
proposal
(http://wiki.ecmascript.org/doku.php?id=strawman:proxy_defaulthandler&s=forwarding)
David
Le 23/01/2011 17:43, François REMY a écrit :
Moreover, should a Proxy really have a prototype ?
I mean, what’s the point about having a prototype, since the “get” method can
return everything you would like for any property ?
I think getProtototypeOf should be defined as a new trap. And its default
behaviour should be to return null (or Object.prototype, but I think null is
the intented behavior of a proxy).
On the other hand, overriding getPropertyNames should not be allowed.
getPropertyNames should *always* return the concatenation of the properties
returned by getOwnPropertyNames() and by
getPrototypeOf(this).getPropertyNames(). It makes no sense otherwhise.
I understand that we may want to redefine the way an ECMAScript Object can
handle the native commands, but I’m strongly against anything that can conduce
to illogical results (if there’s not an use case that justify it, naturally).
The definition of getPropertyNames is clear and being able to redefine it
locally seems me wrong. A proxy can modify is own behavior, not the behavior of
the ES engine. Being able to have getPropertyNames and getOwnPropertyNames
returning incompatible results is somewhat hurting me. Is there any reason we
should allow that ? Any use case ?
I’m issuing the same concerns for the “has” trap. It think it should not be a
trap. It should always return hasOwn(key) || prototype.has(key). Each one of
hasOwn and prototype can be tuned by the proxy, but not the “has” itself. We’re
not removing features, but we prevent bad usage of it. Whatever the user code
do, the ‘has’ behavior will stay logical.
Another thing I don’t quite understand is the difference between “keys” and
“enumerate”. If there’s no strong difference, it should be the same trap (same
logic: enumerate should return the concatenation of this.keys and
this.prototype.keys). Having two different but similar traps will cause
confusion. Maybe there’s a need for this difference however. I just didn’t
understand why such a difference should exist, but at least I see more possible
usages than the first three traps I “contested”.
Anyway, if we should retain only one thing from the discussions we already have
seen on the Proxy hub, is that it’s a great feature, but one that still needs
some work before implementation ;-)
Regards,
François
From: David Bruant
Sent: Sunday, January 23, 2011 4:24 PM
To: es-discuss
Cc: Mark S. Miller
Subject: [ES Harmony Proxies] Fundamental trap definition
Hi,
I am wondering if getPropertyDescriptor and getPropertyNames fundamental traps
shouldn't rather be derived traps since they could have a pretty
straightforward default implementation.
One implementation of getPropertyNames could be :
--------------------------
Object.getPropertyNames = function(o){
var objectToInspect;
var result = [];
for(objectToInspect = o;
objectToInspect !== null;
objectToInspect = Object.getPrototypeOf(objectToInspect))
{
result =
result.concat(Object.getOwnPropertyNames(objectToInspect));
}
return result.removeDuplicates(); // the removeDuplicates method is made
up, but you get the point
}
--------------------------
This seem to fit the proposal
(http://wiki.ecmascript.org/doku.php?id=harmony:extended_object_api&s=getpropertydescriptor)
expectations). This could be also the default getPropertyNames trap
implementation.
I haven't really seen a strong definition of what fundamental traps are in the
proposal. On Mark Miller's e-mail
(https://mail.mozilla.org/pipermail/es-discuss/2011-January/012601.html) is
written:
[a trap is fundamental if] there is no coherent default behavior to fall back
to that would be defined in terms of the remaining traps. (please tell me if I
misinterpret what you meant)
If we're going with this definition, then getPropertyDescriptor and
getPropertyNames should probably be derived traps since they can clearly be
defined thanks to other traps (respectively getOwnPropertyDescriptor and
getOwnPropertyNames as I showed above) which seems to be coherent fallback
behavior.
Instead of a formal definition, this could be a rational for deciding what is a
fundamental trap and what isn't.
In the 5 remaining traps (getOwnPropertyDescriptor, getOwnPropertyNames,
defineProperty, delete, fix), I don't see any that could be defined thanks to
the others. They seem to be also the fundamental actions that one can perform
on a single object:
Property-wise:
- create/configure a property (defineProperty)
- delete a property (delete)
- retrieve a property (getOwnPropertyDescriptor. Can be used to separate the
create and configure cases of defineProperty)
Property-set-wise:
- retrieve the property set (getOwnPropertyNames. More can be found later on
each property with getOwnPropertyDescriptor)
- prevent further extension (and optional reconfigurations for seal and
freeze)(fix)
The prototype can be retrieved thanks to Object.getPrototypeOf (which cannot be
trapped for consistency purposes) and all actions can be performed by climbing
the prototype chain.
Any thoughts on the fundamental trap definition?
Or on the idea of turning getPropertyDescriptor and getPropertyNames into
derived traps with the suggested definition?
David
--------------------------------------------------------------------------------
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss