Re: getter and setter inheritance
On 2008-05-09, at 12:46 EDT, Lars Hansen wrote: (One bike ride and one cup of coffee later.) Clearly there is a difference between class/interface inheritance on the one hand and prototype inheritance on the other. In either case I think the introduction of a setter and/or a getter in a context introduces definitions for both in that context, essentially a special property that holds a getter/setter pair. A missing getter/setter is generated (that's what ES4 specifies now.) That means that in prototype contexts, if an object has a getter or a setter for a field, the prototype will never be searched for the missing half. In a class context, getters and setters can be overridden because the class instance only has the one special property with the getter/setter pair, and the values in that property depend on the class that the instance is an instance of. So different classes have different pairs. (I've only been to spin class, but I've had 1 coffee and 2 teas.) When A missing getter/setter is generated, what is its functionality? Does it just error? Can I call a super getter/setter method (I hope)? What is the syntax for that? ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: getter and setter inheritance
The generated getter and setter ought to have roughly the same behavior as the getting and setting behavior for a property on the class. The behavior for reading and writing properties is this, IIRC: If the class is compiled in standard mode, then reads from nonexistent properties return undefined. Writes to nonexistent properties on non-dynamic classes fail silently, whereas writes to nonexistent properties on dynamic classes create those properties. If the class is compiled in strict mode, then reads from nonexistent properties on non-dynamic classes throw an exception (no such property); reads from nonexistent properties on dynamic classes return undefined. Writes to nonexistent properties on non-dynamic classes throw an exception (no such property), whereas writes to nonexistent properties on dynamic classes create those properties. For generated getters and setters (in classes at least), it seems that matching that behavior, except for property creation, is roughly right. I'd say that the write ought to be silently ignored on non-strict classes and that an error should be thrown on strict classes. And yes, it ought to be possible to invoke the superclass getter, the syntax is as for accessing a property on a superclass, super.p for the immediate base class or super(C).p for classes higher up the inheritance chain. --lars -Original Message- From: P T Withington [mailto:[EMAIL PROTECTED] On Behalf Of P T Withington Sent: 12. mai 2008 07:59 To: Lars Hansen Cc: Kris Zyp; [EMAIL PROTECTED]; es4-discuss Discuss Subject: Re: getter and setter inheritance On 2008-05-09, at 12:46 EDT, Lars Hansen wrote: (One bike ride and one cup of coffee later.) Clearly there is a difference between class/interface inheritance on the one hand and prototype inheritance on the other. In either case I think the introduction of a setter and/or a getter in a context introduces definitions for both in that context, essentially a special property that holds a getter/setter pair. A missing getter/setter is generated (that's what ES4 specifies now.) That means that in prototype contexts, if an object has a getter or a setter for a field, the prototype will never be searched for the missing half. In a class context, getters and setters can be overridden because the class instance only has the one special property with the getter/setter pair, and the values in that property depend on the class that the instance is an instance of. So different classes have different pairs. (I've only been to spin class, but I've had 1 coffee and 2 teas.) When A missing getter/setter is generated, what is its functionality? Does it just error? Can I call a super getter/setter method (I hope)? What is the syntax for that? ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: getter and setter inheritance
How does super lookups and calls work for getters and setters in ES3.1 and ES4? It seems like the following scheme should work. Given the following code in ES4: class A { function get x() { ... } function set x(value) { ... } } class B extends A { private let _x = 0; function get x() { return super.x; } function set x(value) { _x = value; super.x = value; } } In JS1.7 I think the following works function A() { ... } A.prototype.__defineGetter__('x', ...); A.prototype.__defineSetter__('x', ...); function B() { A.call(this); } B.prototype = new A; // Or use helper to prevent calling A's constructor while setting up the prototype object B.prototype._x = 0; B.prototype.__defineGetter__('x', function() { var aGetter = A.prototype.__lookupGetter__('x); return aGetter.call(this); }; B.prototype.__defineSetter__('x', function(value) { this.x_ = value; var aSetter = A.prototype.__lookupSetter__('x); aSetter.call(this, value); }; Would ES3.1 work by simply replacing __lookup(G|S)etter__ by Object.getProperty? -- erik On Mon, May 12, 2008 at 08:52, Lars Hansen [EMAIL PROTECTED] wrote: The generated getter and setter ought to have roughly the same behavior as the getting and setting behavior for a property on the class. The behavior for reading and writing properties is this, IIRC: If the class is compiled in standard mode, then reads from nonexistent properties return undefined. Writes to nonexistent properties on non-dynamic classes fail silently, whereas writes to nonexistent properties on dynamic classes create those properties. If the class is compiled in strict mode, then reads from nonexistent properties on non-dynamic classes throw an exception (no such property); reads from nonexistent properties on dynamic classes return undefined. Writes to nonexistent properties on non-dynamic classes throw an exception (no such property), whereas writes to nonexistent properties on dynamic classes create those properties. For generated getters and setters (in classes at least), it seems that matching that behavior, except for property creation, is roughly right. I'd say that the write ought to be silently ignored on non-strict classes and that an error should be thrown on strict classes. And yes, it ought to be possible to invoke the superclass getter, the syntax is as for accessing a property on a superclass, super.p for the immediate base class or super(C).p for classes higher up the inheritance chain. --lars -Original Message- From: P T Withington [mailto:[EMAIL PROTECTED] On Behalf Of P T Withington Sent: 12. mai 2008 07:59 To: Lars Hansen Cc: Kris Zyp; [EMAIL PROTECTED]; es4-discuss Discuss Subject: Re: getter and setter inheritance On 2008-05-09, at 12:46 EDT, Lars Hansen wrote: (One bike ride and one cup of coffee later.) Clearly there is a difference between class/interface inheritance on the one hand and prototype inheritance on the other. In either case I think the introduction of a setter and/or a getter in a context introduces definitions for both in that context, essentially a special property that holds a getter/setter pair. A missing getter/setter is generated (that's what ES4 specifies now.) That means that in prototype contexts, if an object has a getter or a setter for a field, the prototype will never be searched for the missing half. In a class context, getters and setters can be overridden because the class instance only has the one special property with the getter/setter pair, and the values in that property depend on the class that the instance is an instance of. So different classes have different pairs. (I've only been to spin class, but I've had 1 coffee and 2 teas.) When A missing getter/setter is generated, what is its functionality? Does it just error? Can I call a super getter/setter method (I hope)? What is the syntax for that? ___ Es3.x-discuss mailing list [EMAIL PROTECTED] https://mail.mozilla.org/listinfo/es3.x-discuss ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: getter and setter inheritance
On Mon, May 12, 2008 at 10:10 AM, Erik Arvidsson [EMAIL PROTECTED] wrote: Would ES3.1 work by simply replacing __lookup(G|S)etter__ by Object.getProperty? Yes, I think so. B.prototype.__defineGetter__('x', function() { var aGetter = A.prototype.__lookupGetter__('x); ... Object.defineProperties(B.prototype, {x: { getter: function() { var aGetter = Object.getProperty(A.prototype, 'x').getter; ... -- Cheers, --MarkM ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: getter and setter inheritance
When an object A is defined that inherits from it's prototype object B that has a getter and setter defined for foo, and object A wants to inherit the behavior of B except for a slight modification to the getter behavior, it could be advantageous if the setter could still be inherited without having to redefine it on object A. If the developer wants to make property foo read-only, this can still easily be done by creating a setter that throws an exception (or does nothing). That being said, I would still favor the approach of treating getters/setters as a full slot, where inheritance doesn't go past half-definitions because that is behavior that is currently used on the web today. Also, the idea of making setters without getters illegal is interesting. However, while they may be rare, I think setters without getters has use cases. This seems like unnecessary arbitrary restriction to dissallow setters without getters. Furthermore, this is not the behavior of current browsers, there is no precedent in JavaScript implementations for preventing this combination. Is there other reasons for this restriction that I am not aware of? Thanks, Kris - Original Message - From: Mark S. Miller [EMAIL PROTECTED] To: Kris Zyp [EMAIL PROTECTED] Cc: [EMAIL PROTECTED]; es4-discuss Discuss es4-discuss@mozilla.org Sent: Sunday, May 11, 2008 10:23 AM Subject: Re: getter and setter inheritance 2008/5/9 Kris Zyp [EMAIL PROTECTED]: A question of how inheritance/delegation should work with getters and setters was raised in a recent discussion. Hi Kris, The way I've been thinking of getters and setters is as if there are two kinds of properties: * A data property is defined by its current value, and whether the value is writable. If the value is not writable, the property is considered read-only. * A procedural property is defined by a getter function and an optional setter function. If there is no setter function, the property is considered read-only. For both kinds of properties, a property is further defined by its property name, whether the property is enumerable, and whether the property's definition is redefinable. (Where redefinable implies deletable.) This would be reflected (so to speak) concretely in the results of Object.getProperties and Object.getProperty, and in the argument of Object.defineProperties. Object.getProperty(x, 'foo') = {value: 3, writable: false, enumerable: false, redefinable: false} Object.getProperty(x, 'bar') = {getter: function(){return 3;}, enumerable: false, redefinable: false} in which case x.foo and x.bar are behaviorally identical for non-reflective clients. If there is an object A whose prototype is object B, and object A defines a getter for property foo, and object B defines a setter for property foo, and we write a value to A.foo, should the setter defined on object B be called? I think it should be illegal to define a setter without defining a getter. A procedural property should either have a getter or have a getter and a setter. Assuming B defines a getter and a setter for foo, and A defines a getter for foo, the answer should be no. A's own foo is a read-only procedural property that fully masks B's foo. If A didn't define any property on A, the setter would be inherited from B and would be called when A.foo was modified. Yes. However, with the getter defined on A, should the inheritance stop at A, because there is a slot defined, or should it continue along the prototype chain because there was no setter defined for that property (nor plain value)? Stop at A. s/slot/property The question also applies when the getter and setter are reversed. When a property is accessed and there is a setter defined, but no getter, That case should be rejected as illegal. should we continue to down the prototype chain to find a getter or a plain value, or stop and return undefined? AFAICT, ES4 doesn't explicitly define which is the correct behavior. Firefox follows the former behavior: B={set foo(v){foo = v}, get bar(){return bar value}} B.foo should be rejected as illegal. A={get foo(){return foo value}, set bar(v){bar = v}, __proto__:B} A.bar should be rejected as illegal. -- Cheers, --MarkM ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: getter and setter inheritance
On Sun, May 11, 2008 at 4:40 PM, Kris Zyp [EMAIL PROTECTED] wrote: [...] That being said, I would still favor the approach of treating getters/setters as a full slot, where inheritance doesn't go past half-definitions because that is behavior that is currently used on the web today. Great! Also, the idea of making setters without getters illegal is interesting. However, while they may be rare, I think setters without getters has use cases. This seems like unnecessary arbitrary restriction to dissallow setters without getters. Furthermore, this is not the behavior of current browsers, there is no precedent in JavaScript implementations for preventing this combination. Is there other reasons for this restriction that I am not aware of? Not really. I can live with write-only procedural properties. I don't think it changes any of the other points. When reading a write-only property, i.e., a procedural property with a setter and no getter, one reads undefined, even in strict mode. Right? So an absent getter is always equivalent to a getter of function(){return undefined;}? -- Cheers, --MarkM ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
getter and setter inheritance
A question of how inheritance/delegation should work with getters and setters was raised in a recent discussion. If there is an object A whose prototype is object B, and object A defines a getter for property foo, and object B defines a setter for property foo, and we write a value to A.foo, should the setter defined on object B be called? If A didn't define any property on A, the setter would be inherited from B and would be called when A.foo was modified. However, with the getter defined on A, should the inheritance stop at A, because there is a slot defined, or should it continue along the prototype chain because there was no setter defined for that property (nor plain value)? The question also applies when the getter and setter are reversed. When a property is accessed and there is a setter defined, but no getter, should we continue to down the prototype chain to find a getter or a plain value, or stop and return undefined? AFAICT, ES4 doesn't explicitly define which is the correct behavior. Firefox follows the former behavior: B={set foo(v){foo = v}, get bar(){return bar value}} A={get foo(){return foo value}, set bar(v){bar = v}, __proto__:B} A.bar - undefined A.foo = 'new value' - setter is not called, foo is not set Thanks, Kris___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: getter and setter inheritance
2008/5/9 Lars Hansen [EMAIL PROTECTED]: My view is that getters and setters introduce properties and that whatever we do should be appropriate to that model. That is pretty much my view as well. Just a couple of questions that might need addressing, if it hasn't been dealt with already: - Can you have a property together with a getter and/or a setter? - If so: * Is there any way to reach that property from inside the getter/setter without ending up recurring into the getter/setter? * Can a setter modify the property if there is a property but no getter? * Can a getter read the property if there is a property but no setter? Others seem to think that getters and setters introduce a way of invoking normal methods by a different syntax and that they are truly just methods. In the world of classes and instances that may be appropriate, but not in the object-and-property world of ES3, I expect. Or one could consider an ES3 property as a getter/setter pair, if one wished. -- David liorean Andersson ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: getter and setter inheritance
(One bike ride and one cup of coffee later.) Clearly there is a difference between class/interface inheritance on the one hand and prototype inheritance on the other. In either case I think the introduction of a setter and/or a getter in a context introduces definitions for both in that context, essentially a special property that holds a getter/setter pair. A missing getter/setter is generated (that's what ES4 specifies now.) That means that in prototype contexts, if an object has a getter or a setter for a field, the prototype will never be searched for the missing half. In a class context, getters and setters can be overridden because the class instance only has the one special property with the getter/setter pair, and the values in that property depend on the class that the instance is an instance of. So different classes have different pairs. There's no particular problem with interfaces holding getter and setter declarations, they are just constraints on the contents of the implementing class -- the class must have a matching getter or setter definition (possibly inherited from base class). That said, getters and setters in interfaces feels pretty lame, because what they're doing is basically requiring a particular *implementation* of a property. A good interface would require there to be a property x with a particular type, but not worry about whether it was introduced by var, let, const, or implemented as a getter/setter. So, using var to stand for all of those possibilities: interface ArrayLike.T { var length: double; meta function get(n):T; meta function set(n,v:T); } In practice most types implementing ArrayLike would use a getter/setter pair for the length field, but why should the type worry about that? --lars From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Lars Hansen Sent: 9. mai 2008 08:41 To: Kris Zyp; [EMAIL PROTECTED]; es4-discuss Discuss Subject: RE: getter and setter inheritance Very timely questions. I've been worrying about similar things this week (more in the context of the ES4 type system) and not yet reached any conclusions. My view is that getters and setters introduce properties and that whatever we do should be appropriate to that model. Others seem to think that getters and setters introduce a way of invoking normal methods by a different syntax and that they are truly just methods. In the world of classes and instances that may be appropriate, but not in the object-and-property world of ES3, I expect. --lars From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Kris Zyp Sent: 9. mai 2008 07:19 To: [EMAIL PROTECTED]; es4-discuss Discuss Subject: getter and setter inheritance A question of how inheritance/delegation should work with getters and setters was raised in a recent discussion. If there is an object A whose prototype is object B, and object A defines a getter for property foo, and object B defines a setter for property foo, and we write a value to A.foo, should the setter defined on object B be called? If A didn't define any property on A, the setter would be inherited from B and would be called when A.foo was modified. However, with the getter defined on A, should the inheritance stop at A, because there is a slot defined, or should it continue along the prototype chain because there was no setter defined for that property (nor plain value)? The question also applies when the getter and setter are reversed. When a property is accessed and there is a setter defined, but no getter, should we continue to down the prototype chain to find a getter or a plain value, or stop and return undefined? AFAICT, ES4 doesn't explicitly define which is the correct behavior. Firefox follows the former behavior: B={set foo(v){foo = v}, get bar(){return bar value}} A={get foo(){return foo value}, set bar(v){bar = v}, __proto__:B} A.bar - undefined A.foo = 'new value' - setter is not called, foo is not set Thanks, Kris ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss