[ES Harmony Proxies] Different points on proxies ground

# David Bruant (14 years ago)

As a starter, I remind that I am not direclty involved in the proposal. What I say about the proposal is ony my view and interpretation of what I read (proposal, blog articles, tutorial, slides) and watch (presentations). I do not make any decision.

Le 23/01/2011 21:36, François REMY a écrit :

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 am sorry, but that's not what I said. I haven't said that we should open everything. I said that I agreed with the idea of providing more power to the users to drive language innovation instead of having a group of people in an ivory tower defining standards. I have said your last point: proxies brings power/potential/possibilities. About proxy users, what I have said is "It's up to the people who are going to use proxies to be careful to be coherent with what they pretend to do". I'm not saying that they will do it. I know they are human. I know some are going to misinterpret and misunderstand a lot of things. That's also the reason why I am currently working on writing the proxy documentation (developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Proxy) which is very likely to be the first thing people go to when they'll have questions and need examples. No one can prevent humans from misusing something. We can work on trying to reduce the unintended misuses, though.

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.

I don't know all the use cases, but I have seen a couple:

  1. Being able to emulate host objects in JavaScript.

    1. Even with ES5, the DOM (and its ECMAScript binding) cannot be implemented in ECMAScript. One example I see is data-* attributes. I need to check, but the way I understand it, an element object needs to have its "data-" properties in sync with the .getAttribute("data-")/.setAttribute("data-", value) for all possible DOMString replacing "". I may be wrong, but it is just impossible to do in ES5
    1. Even with ES5, it is impossible to emulate IE DOM (I have read it, but have no proof. If anyone reading does, feel free to jump in to provide an example).
    1. NodeList. They are live objects (www.w3.org/TR/DOM-Level-3-Core/core.html#ID-536297177). They are currently implemented with host objects. With pure ES5, impossible to implement. Possible with proxies.
  2. Some security features like membranes (developer.mozilla.org/en/XPConnect_security_membranes) (harmony:proxies#a_simple_membrane) requires proxy to be written at all (and easily). Once again, I have no formal proof of it, but seeing the implementation gives me confidence in the fact that it's not possible without proxies (or equivalently-powerful mecanism).

  3. Fixing web browsers's mess. If you haven't seen it yet, I invite you to read this : ejohn.org/blog/the-dom-is-a-mess . I think that it would be ridiculously easier to wrap+replace a lot of native DOM objects using a forwarding proxy to fix them. This is what jQuery and all JS (DOM) library is all about. Proxies will give them the opportunity to fix the mess in browsers (that implement proxies) things they currently may not be able to do since host objects can differ from regular objects by having not emulable semantics.

I don't know any other use case, but unlike CSS, ECMAScript goes beyond the web browser (ejohn.org/blog/the-world-of-ecmascript). Or rather should I say, for the Firefox case, it goes "inside" the web browser which is another usage of ECMAScript.

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.

If Object.getPropertyNames(document.getElementById('myId')) is bogus (for instance inconsistent with getOwnPropertyNames + prototype names), I want to be able to programmatically write a library in JS that fixes the bug (and I think I can if I use a forwarding proxy wrapper around DOM elements). If you only allow me to redefine Object.getOwnPropertyNames, I am left aside with my impossibility to fix the bug.

If the proxy implementation is correct and the trap set complete, I can face ANY bug on host objects. I think I could even face bugs in regular objects (maybe not any bug since handlers are themselves regular objects and a lot of things would certainly require regular objects to be emulated).

  1. Being able to fix ANY bug on host objects. That sounds like a unique use case that would justify everything that is currently in the proxy proposal.

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.

I am sorry, but I think there something I don't understand. Proxies are an addition to ECMAScript. They do not change the language, they do not change the semantics of regular objects. The only thing proxies do is providing a new sort of object-typed /things/ that can be used but do not behave like regular objects. Regular objects remain completely unchanged. As said in a talk (www.youtube.com/watch?v=A1R8KGKkDjU starting at 18'00''). "The API doesn't allow you to redefine the semantics of existing objects". All the things that were true in ES5 remains. Proxies are just a usage of what is written in ES5 8.6.2 Object Internal Properties and Methods right under table 8: "Every object (including host objects) must implement all of the internal properties listed in Table 8.". This is done here : harmony:proxies_semantics#semantics_of_proxies

The inconsistency that proxies could bring isn't in ES5. It is in people's expectations and current (mis)understanding of what ECMAScript objects are. They are going to use proxies, they'll make a mistake once, will learn from some doc/the spec itself/blog articles/whatever and know that what they used to call objects was actually one case of what ECMAScript objects actually are (ES5 section 8.6).

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 think I need the context, because I am not sure of what "object model" means. If it means regular object semantics, then fine, proxies aren't changing it. If it means ES5 section 8.6.2 table 8, then fine, proxies aren't changing the table, they are only an "instanciation of the table" which isn't a change to the table itself or to other "table instanciations" like regular or host objects are. Proxies are implemented in FF4 and currently being used internally, they haven't required "a significant redesign of existing optimization mechanisms and the invention of new techniques" that I would be aware of (bugzilla.mozilla.org/show_bug.cgi?id=546590).

,

# François REMY (14 years ago)

Okay, it seems I don’t agree with the only use case you gave for redifining getPropertyNames, but, well it doesn’t mean the feature should be dropped if nobody else is complaining about that.

For your curiosity : [[Since “fixing” getPropertyNames would involves returning the properties of an object and its prototype chain, you can already fix the problem with a proxy on which you can define both getOwnPropertyNames and the prototype (that can be another proxy if there’s really a big bug that involves a bad getOwnPropertyNames on the prototype itself). BTW, if you want to fix an implementation, it’s because you expect some consistent behavior for the getPropertyNames function, meaning that an inconsistent behavior should not be allowed because you would like to fix it if it once existed in the wild.]]

In fact, it seems that the ES5 specification defines both [[GetProperty]] and [[GetOwnProperty]] on objects, and does not explicitely say that ECMAScript host objects should comply with the default implementation of [[GetProperty]]. Additionnaly, the specification has consistency requirements for [[GetOwnProperty]] but not for [[GetProperty]]. So it seems legal to allow a proxy to redefine both [[GetProperty]] and [[GetOwnProperty]]. It’s not good to allow that, from my point of view, but it’s possible.

While I’m rereading the spec another time, I notice there’s however a notice that specify that “Named properties of the [[Prototype]] object are inherited (are visible as properties of the child object)”meaning that a [[GetProperty]] implementation could not be dramatically different of getOwnProperty(p) || prototype.getProperty(p). Anyway, there’s no way to be sure a supplied ECMAScript function asserts the constraints defined in the specification.

François

From: David Bruant Sent: Monday, January 24, 2011 12:53 AM To: François REMY Cc: es-discuss ; Mark S. Miller Subject: Re: [ES Harmony Proxies] Different points on proxies ground

As a starter, I remind that I am not direclty involved in the proposal. What I say about the proposal is ony my view and interpretation of what I read (proposal, blog articles, tutorial, slides) and watch (presentations). I do not make any decision.

Le 23/01/2011 21:36, François REMY a écrit : 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 am sorry, but that's not what I said. I haven't said that we should open everything. I said that I agreed with the idea of providing more power to the users to drive language innovation instead of having a group of people in an ivory tower defining standards. I have said your last point: proxies brings power/potential/possibilities. About proxy users, what I have said is "It's up to the people who are going to use proxies to be careful to be coherent with what they pretend to do". I'm not saying that they will do it. I know they are human. I know some are going to misinterpret and misunderstand a lot of things. That's also the reason why I am currently working on writing the proxy documentation (developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Proxy) which is very likely to be the first thing people go to when they'll have questions and need examples. No one can prevent humans from misusing something. We can work on trying to reduce the unintended misuses, though.

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. I don't know all the use cases, but I have seen a couple:

  1. Being able to emulate host objects in JavaScript.

    1. Even with ES5, the DOM (and its ECMAScript binding) cannot be implemented in ECMAScript. One example I see is data-* attributes. I need to check, but the way I understand it, an element object needs to have its "data-" properties in sync with the .getAttribute("data-")/.setAttribute("data-", value) for all possible DOMString replacing "". I may be wrong, but it is just impossible to do in ES5
    1. Even with ES5, it is impossible to emulate IE DOM (I have read it, but have no proof. If anyone reading does, feel free to jump in to provide an example).
    1. NodeList. They are live objects (www.w3.org/TR/DOM-Level-3-Core/core.html#ID-536297177). They are currently implemented with host objects. With pure ES5, impossible to implement. Possible with proxies.
  2. Some security features like membranes (developer.mozilla.org/en/XPConnect_security_membranes) (harmony:proxies#a_simple_membrane) requires proxy to be written at all (and easily). Once again, I have no formal proof of it, but seeing the implementation gives me confidence in the fact that it's not possible without proxies (or equivalently-powerful mecanism).

  3. Fixing web browsers's mess. If you haven't seen it yet, I invite you to read this : ejohn.org/blog/the-dom-is-a-mess . I think that it would be ridiculously easier to wrap+replace a lot of native DOM objects using a forwarding proxy to fix them. This is what jQuery and all JS (DOM) library is all about. Proxies will give them the opportunity to fix the mess in browsers (that implement proxies) things they currently may not be able to do since host objects can differ from regular objects by having not emulable semantics.

I don't know any other use case, but unlike CSS, ECMAScript goes beyond the web browser (ejohn.org/blog/the-world-of-ecmascript). Or rather should I say, for the Firefox case, it goes "inside" the web browser which is another usage of ECMAScript.

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. If Object.getPropertyNames(document.getElementById('myId')) is bogus (for instance inconsistent with getOwnPropertyNames + prototype names), I want to be able to programmatically write a library in JS that fixes the bug (and I think I can if I use a forwarding proxy wrapper around DOM elements). If you only allow me to redefine Object.getOwnPropertyNames, I am left aside with my impossibility to fix the bug.

If the proxy implementation is correct and the trap set complete, I can face ANY bug on host objects. I think I could even face bugs in regular objects (maybe not any bug since handlers are themselves regular objects and a lot of things would certainly require regular objects to be emulated).

  1. Being able to fix ANY bug on host objects. That sounds like a unique use case that would justify everything that is currently in the proxy proposal.

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. I am sorry, but I think there something I don't understand. Proxies are an addition to ECMAScript. They do not change the language, they do not change the semantics of regular objects. The only thing proxies do is providing a new sort of object-typed /things/ that can be used but do not behave like regular objects. Regular objects remain completely unchanged. As said in a talk (www.youtube.com/watch?v=A1R8KGKkDjU starting at 18'00''). "The API doesn't allow you to redefine the semantics of existing objects". All the things that were true in ES5 remains. Proxies are just a usage of what is written in ES5 8.6.2 Object Internal Properties and Methods right under table 8: "Every object (including host objects) must implement all of the internal properties listed in Table 8.". This is done here : harmony:proxies_semantics#semantics_of_proxies

The inconsistency that proxies could bring isn't in ES5. It is in people's expectations and current (mis)understanding of what ECMAScript objects are. They are going to use proxies, they'll make a mistake once, will learn from some doc/the spec itself/blog articles/whatever and know that what they used to call objects was actually one case of what ECMAScript objects actually are (ES5 section 8.6).

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 think I need the context, because I am not sure of what "object model" means. If it means regular object semantics, then fine, proxies aren't changing it. If it means ES5 section 8.6.2 table 8, then fine, proxies aren't changing the table, they are only an "instanciation of the table" which isn't a change to the table itself or to other "table instanciations" like regular or host objects are. Proxies are implemented in FF4 and currently being used internally, they haven't required "a significant redesign of existing optimization mechanisms and the invention of new techniques" that I would be aware of (bugzilla.mozilla.org/show_bug.cgi?id=546590).

,

David

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. , 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 (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" (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 (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 ;-)

, 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 :