Re: Deleting Getters and Setters (was Re: Controlling DontEnum...)
On Mar 17, 2008, at 1:31 PM, Lars Hansen wrote: -Original Message- From: Kris Zyp [mailto:[EMAIL PROTECTED] obj = {get foo() { return 'hi' }} Object foo=hi obj.foo hi delete obj.foo true obj.foo = 'goodbye' goodbye obj.foo goodbye With ES4, obj.foo would still be returning hi at the end? That sounds nice, but is there no fear of compatibility issues with that? It's an interesting point. The proposal is here: http://wiki.ecmascript.org/doku.php?id=proposals:getters_and_setters but does not mention deletion (either way). Brendan, opinions? Clearly the proposal is incomplete :-/. SpiderMonkey originated three special forms for getters and setters, in 1999 (see rev 3.18 at http://bonsai.mozilla.org/cvsgraph.cgi?file=/mozilla/js/src/jsparse.c for one entry point into the change): 1. getter function x() { return ++i; }; 2. o = {x getter: function () { return ++this.i; }}; 3. o = {i: 0}; o.x getter= function () { return ++this.i; }; The first two were changed long ago, with Waldemar guiding things, into the ES4 syntax the RI supports today: 1'. function get x() { return ++i; }; 2'. o = {get x() { return ++this.i; }; SpiderMonkey supports only form 2', while still maintaining support for the original 1-3. Form 3 became 3': o = {i: 0}; o.__defineGetter__('x', function () { return + +this.i; }); About DontDelete: only the first form or its revised version, 1 or 1', sets DontDelete among the bound getter's attributes, just as any non-eval'ed function binding created for a function definition makes a DontDelete property (eval makes delete-able bindings, for reasons I do not recall from ES1 days -- this is design flaw, btw, but I won't get into it here). ES4 supports get and set methods in classes, also DontDelete or stronger (fixtures, so at least DontDelete). For backward compatibility with SpiderMonkey, one might like 2' to make a getter that can be deleted. On the other hand, for higher integrity one might prefer that the object-initialiser-hosted syntactic form would make a DontDelete property. The recent o = {var x: don't delete} proposal compatibly extends initialiser syntax to support user-created DontDelete properties, but whatever the outcome for that late-breaking micro-proposal, I do not think o = {var get x() { ... }}; is a good idea -- var and get next to each another do not convey DontDelete; the combo looks like a typo of some sort. And would const get for a ReadOnly + DontDelete binding be wanted too? A getter without a setter in SpiderMonkey behaves like a const binding, in that assignments go into the bit bucket: js o = {get x() ++this.i, i:0} [object Object] js o.x 1 js o.x 2 js o.x = 42 42 js o.x 3 A getter without a setter makes something const-like, in the sense of ES1-3's ReadOnly attribute and its semantics, but this kind of const lacks defensive consistency, to use a phrase defined in Mark Miller's thesis. We used to throw an error in SpiderMonkey when one sets a getter-only property, but we changed this to match the desired (for foolish consistency? ;-) ES1-3-like ReadOnly behavior. Users wanted only one kind of const. A setter without a getter means property gets return undefined. We've always done this. I hope this helps, even though it is about more than DontDelete. Given our history and the delete-ability of properties created in object initialisers in ES3, I favor reserving DontDelete getters and setters for the 1' special form: a variation on function definition syntax. So only function get x() ++i; or similar in a class (static or instance) would make a DontDelete binding, if not a fixture. My two cents, /be ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Deleting Getters and Setters (was Re: Controlling DontEnum...)
On Mar 17, 2008, at 2:36 PM, Brendan Eich wrote: 1. getter function x() { return ++i; }; 2. o = {x getter: function () { return ++this.i; }}; 3. o = {i: 0}; o.x getter= function () { return ++this.i; }; The first two were changed long ago, with Waldemar guiding things, into the ES4 syntax the RI supports today: 1'. function get x() { return ++i; }; 2'. o = {get x() { return ++this.i; }; SpiderMonkey supports only form 2', while still maintaining support for the original 1-3. Form 3 became 3': o = {i: 0}; o.__defineGetter__('x', function () { return + +this.i; }); Only in SpiderMonkey, I should have added -- the RI and of course ES4 do not specify support for __define[GS]etter__. /be ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Deleting Getters and Setters (was Re: Controlling DontEnum...)
On Mon, Mar 17, 2008 at 5:36 PM, Brendan Eich [EMAIL PROTECTED] wrote: For backward compatibility with SpiderMonkey, one might like 2' to make a getter that can be deleted. That pattern is used in Firefox now (and perhaps elsewhere) to do lazy initialization of expensive objects: this.__defineGetter__(Debug, function() { var d = loadModule(debug.js); delete this.Debug; this.Debug = d; return d; }); We could adapt, obviously, dunno if it's widely used on the web. Mike ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Deleting Getters and Setters (was Re: Controlling DontEnum...)
On Mar 17, 2008, at 3:08 PM, Mike Shaver wrote: On Mon, Mar 17, 2008 at 5:36 PM, Brendan Eich [EMAIL PROTECTED] wrote: For backward compatibility with SpiderMonkey, one might like 2' to make a getter that can be deleted. That pattern is used in Firefox now (and perhaps elsewhere) to do lazy initialization of expensive objects: this.__defineGetter__(Debug, function() { var d = loadModule(debug.js); delete this.Debug; this.Debug = d; return d; }); We could adapt, obviously, dunno if it's widely used on the web. With only SpiderMonkey supporting __defineGetter__, it's not widely used. The canonical JS memoization pattern, presented nicely here: http://osteele.com/archives/2006/04/javascript-memoization changes (shadows or replaces) a function-valued property, requiring callers to add pesky () to invoke the property explicitly. With getters and setters, this noise-problem can be avoided and (beyond noise reduction) old client code that wanted to get a property, not call a method, can be made to call a memoizing wrapper without requiring vast or infeasible (you don't own write access to the client code) search and replace work. So getters and setters plus memoization patterns do summon __defineGetter__, in our experience. /be ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Deleting Getters and Setters (was Re: Controlling DontEnum...)
On Mon, Mar 17, 2008 at 6:14 PM, Brendan Eich [EMAIL PROTECTED] wrote: With only SpiderMonkey supporting __defineGetter__, it's not widely used. The canonical JS memoization pattern, presented nicely here: Yeah, I would expect that only properties of new objects are lazily defined that way, using the 2' form from above. Mike ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Deleting Getters and Setters (was Re: Controlling DontEnum...)
the fact; getters and setters defined by an object initializer or in a class are fixtures and hence not deletable. Really, that doesn't create a compatibility problem? I realize getters and setters aren't in ES3, but this seems like ES4 would be making a significant departure in behavior from the majority of current browser implementations of the same getter/setter syntax used by ES4: obj = {get foo() { return 'hi' }} Object foo=hi obj.foo hi delete obj.foo true obj.foo = 'goodbye' goodbye obj.foo goodbye With ES4, obj.foo would still be returning hi at the end? That sounds nice, but is there no fear of compatibility issues with that? Kris ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss