Deleting Getters and Setters (was Re: Controlling DontEnum...)

Brendan Eich brendan at mozilla.org
Mon Mar 17 14:36:19 PDT 2008


On Mar 17, 2008, at 1:31 PM, Lars Hansen wrote:

>> -----Original Message-----
>> From: Kris Zyp [mailto:kris at sitepen.com]
>>
>>>>> 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



More information about the Es4-discuss mailing list