Re: [WebIDL] Trying to understand IndexGetter/NameGetter

On Oct 8, 2009, at 8:52 AM, Boris Zbarsky wrote:

>> The only reason the current design is defined somewhat indirectly,  
>> and
>> defined as creating actual properties on the object (rather than
>> handling all of it within the [[Get]] and [[Put]]), is so that ‘in’  
>> and
>> Object.hasOwnProperty() return true appropriately.  There’s no spec  
>> hook
>> in ES3 (or ES5 I think) to change how ‘in’ works on host objects.   
>> All
>> that can be done is to make those properties actually exist.
>
> I think we should fix this.  The current setup really doesn't work  
> very well...  Gecko's ES implementation certainly has a hook that  
> can be used by host objects to affect 'in' and enumeration behavior,  
> and is what we use for nodelists.

There is an internal method used by the 'in' operator's semantics in  
ES3 and ES5. Citing ES3:

11.8.7 The in operator
The production RelationalExpression : RelationalExpression in  
ShiftExpression is evaluated as follows:
1. Evaluate RelationalExpression.
2. Call GetValue(Result(1)).
3. Evaluate ShiftExpression.
4. Call GetValue(Result(3)).
5. If Result(4) is not an object, throw a TypeError exception.
6. Call ToString(Result(2)).
7. Call the [[HasProperty]] method of Result(4) with parameter  
Result(6).
8. Return Result(7).

The [[HasProperty]] internal method is specified in 8.6.2, with this  
language allowing host objects to go nuts:

"For native objects the [[Get]], [[Put]], [[CanPut]], [[HasProperty]],  
[[Delete]] and [[DefaultValue]] methods behave as described in  
described in sections 8.6.2.1, 8.6.2.2, 8.6.2.3, 8.6.2.4, 8.6.2.5 and  
8.6.2.6, respectively, except that Array objects have a slightly  
different implementation of the [[Put]] method (section 15.4.5.1).  
Host objects may implement these methods in any manner unless  
specified otherwise; for example, one possibility is that [[Get]] and  
[[Put]] for a particular host object indeed fetch and store property  
values but [[HasProperty]] always generates false."

ES5 says in its 8.6.2:

"Host objects may implement these internal methods in any manner  
unless specified otherwise; for example, one possibility is that  
[[Get]] and [[Put]] for a particular host object indeed fetch and  
store property values but [[HasProperty]] always generates false.  
However, if any specified manipulation of a host object's internal  
properties is not supported by an implementation, that manipulation  
must throw a TypeError exception when attempted."

So a host object can use [[HasProperty]] to customize the "in" operator.

ES5 layers Object.prototype.hasOwnProperty on [[GetOwnProperty]], an  
internal method new in ES5. But this too may be customized by host  
objects.

As for the for-in loop, its prose spec is blessedly free of internal  
methods and detailed modeling. There are only a few constraints to do  
with properties deleted or added after the loop begins.

This is a weakness in the ES specs, but it does not mean  
[[HasProperty]] or [[GetOwnProperty]] or something used by for-in  
could not be tweaked by a host object, and as bz says, SpiderMonkey  
and Gecko use such a meta-object protocol to customize for-in loops  
along with operator 'in' and hasOwnProperty.

So I do not think WebIDL should labor to create properties eagerly  
just to make them appear to be there when queried by 'in' or for-in or  
a meta-programming method. All optimizing implementations of ES are  
lazy about creating rarely-used properties, and need to be free to  
continue to be lazy.

/be

Received on Thursday, 8 October 2009 17:28:27 UTC