On Feb 15, 2009, at 10:23 AM, Mark S. Miller wrote:
> 2009/2/13 Allen Wirfs-Brock <Allen.Wirfs-Brock at microsoft.com>:
>>>> What happens, if the [[DefineOwnProperty]] is used to create an
>> accessor
>> property of an array instance whose name is an array index. I've
>> thought of
>> three possibilities:
>>>> 1) It's disallowed, Array instances can't have own accessor
>> properties with
>> array index names. (and since Array.prototype is an Array instance
>> it can't
>> either. An array instance could only inherit an accessor property
>> with an
>> array index name from Object.prototype)
>>>> 2) It's allowed, but defining such a property doesn't cause length
>> to change
>> (when the array index name is >= the current length) and explicitly
>> reducing
>> the length does not delete such properties.
>>>> 3) They are treated just like data properties WRT the length
>> invariant.
>>>> My preference is #1. Accessor properties are new to the standard
>> and we get
>> to decide where they are and aren't allowed. Excluding them from
>> indexed
>> array properties eliminates some complicating edge cases and may
>> place less
>> of a burden on implementations that want to optimized array
>> representations.
>> However, it may (??) impact existing implementation that already have
>> arrays that allow getter/setter methods.
>> My preference is #3, closely followed by #1. If implementation or
> legacy constraints would favor #1, that's fine.
Implementations want 3, so do users. SpiderMonkey js shell sessions:
js> a = [1,2,3]
1,2,3
js> a.__defineGetter__(9, function()42)
js> a.length
10
js>
Yoyodyne:src brendaneich$ ./Darwin_DBG.OBJ/js
js> a = [0,1,2]
0,1,2
js> a.length
3
js> a.__defineGetter__(9, function(){return 9})
js> a.length
10
js> a
0,1,2,,,,,,,9
> #2 just seems weird and irregular to me. I am against it. #2 would
> mean that -- even without using the new Object meta methods --
> accessor properties become less transparent virtualizations of data
> properties. It also loses the invariant that you mention below: that
> "length is > than the name of any array indexed own properties."
Agreed.
> Even #3 does not enable the creation of array P that acts as a
> transparent proxy for array Q, where P and Q are genuine arrays, since
> there's no way for P's length to track changes to Q's length. So I see
> no strong argument for #3 over #1.
Existing practice favors 3 over 1. That's decisive in my opinion
(getters and setters are a de-facto standard ES3.1 is codifying and
improving).
> 3) Delete from the end until we can't
> * length is set to max(1+largest array index of a non-configurable
> property, attemptedNewLength).
> * all array indexed properties >= new value of length are deleted
> * if the new value of length != attemptedNewLength, then throw.
>> This #3 has the problem that it is not failure atomic: on failure, it
> has partially changed the array. But it does preserve the invariant.
(Plea for A/B/C after different 1/2/3 numbered list style!)
So (reading ahead one message) I join Mark in agreeing with Breton's
followup proposal, or amendment to the second #1 (if you know what I
mean! :-P).
/be