- From: Brendan Eich <brendan@mozilla.org>
- Date: Thu, 8 Oct 2009 10:27:13 -0700
- To: public-script-coord@w3.org
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