Re: [PrototypeRoot]
On Mon, Jun 22, 2009 at 4:49 PM, Ian Hicksoni...@hixie.ch wrote: On Sun, 21 Jun 2009, Garrett Smith wrote: On Sat, Jun 20, 2009 at 12:43 AM, Ian Hicksoni...@hixie.ch wrote: On Sat, 20 Jun 2009, Garrett Smith wrote: I still want to know: Why would a program want to know the object's [[Class]]? It shouldn't, but [[Class]]es are exposed by ECMAScript objects in their toString() method and thus if we want to ensure universally consistent behaviour we have to define this. No, that is all untrue. Which part is untrue? 1) The [[Class]] property is not exposed in the object's toString. [[Class]] is exposed in Object.prototype.toString. This is very easy to demonstrate. 2) The decision to define this is a choice. That choice as being (part of) a conclusion to the argument: How to define universally consistent behavior. It is possible to define universally consistent as having toString to be a callable object for host objects and allowing for enough wiggle room for things to not break at every possible change (change = browsers, versions, code contexts). It is not necessary to define any sort of prototype chain (e.g. which toString shadows which other toString). That lacks good design sense. I said three things: - A program shouldn't want to know an object's [[Class]] - [[Class]] is exposed by ECMAScript in an object's toString() method - If we want to ensure universal behaviour we have to define this You seem to agree with the second point, as you say: The [[Class]] property is exposed in Object.prototype.toString. You presumably agree with the first point since you were asking for a reason and implying there wasn't one. I haven't actually seen a good reason. Do you disagree that we need to define things to get universal behaviour? No. Do you disagree that design ought to be flexible and extensible? Is universal behavior necessary though? There are many things that browsers will do. Browser vendors can and do innovate proprietary useful features. Sometimes its bad. Okay, often it is bad. As a whole, if done right, implementations can innovate new ideas. It does not all need to come from HTML 5. Ensuring universally consistent behavior would require that *all browsers* behave exactly the same. Right, that's the goal. That is easy: var objString = Object.prototype.toString.call( hostObj ); Assert.isTypeOf( objString, string ); It is more complicated than what we have today (nothing), but adds a little stability to the way objects behave. It says that a string can be obtained from an object. That is not guaranteed today. A program that makes assertions on that string's *value* would be locking itself in to what the API is today. This limits future APIs by locking them in to what web pages use. Authors should not be discouraged from using toString(), but programs that make decisions based on the value it returns would be considered unsafe. MSIE does not behave that way today and versions of other browsers may vary, too. Indeed, that's the problem we are trying to fix. It is not a problem. The proposed change cannot address all possible host objects or other host interfaces. I can't address browsers that do not currently behave that way. On those counts alone, it would be unadvisable for a program to utilize the [[Class]] for anything other than an error message. Probably by the time you are done with fixing it, there will be new interfaces being completed and these interfaces will also need to be woven in. The change you are eliciting seems well-intentioned, but serves only to encourage authors to use strategies that are not advisable. To ensure safer, more reliable behavior, define the [[Class]] property as being a string value. That way, it would be guaranteed that Object.prototype.toString.call( any_object ); would result in string value being produced, and an error would not occur. As far as I can tell, everyone agrees that [[Class]] should be a string. The value of that string should be implementation-dependent. That would not lead to a well-defined universal behaviour. It would most lead to a well-defined universal behavior. It would define the [[Class]] as being a string value, and so a program could reasonable expect that:- Object.prototype.toString.call( anotherObject ) - would return a string value and would not throw errors. That is is not a lot expect, but as a testing requirement, it might help prevent bugs. This makes the feature flexible, extensible, and provides the aforementioned benefits of interfaces over classes (e.g. mixin style behavior with implementation-specific host objects). It seems that the [[Class]] value has nothing to do with the flexibility, extensibility, and mixin style behaviour of objects. Providing a suggestion to implementors as to what that value might be would be harmless. And mostly useless, if they ignore it; if they don't, it might as well be a requirement. Is this (yet
Re: [PrototypeRoot]
On Sun, 21 Jun 2009, Garrett Smith wrote: On Sat, Jun 20, 2009 at 12:43 AM, Ian Hicksoni...@hixie.ch wrote: On Sat, 20 Jun 2009, Garrett Smith wrote: I still want to know: Why would a program want to know the object's [[Class]]? It shouldn't, but [[Class]]es are exposed by ECMAScript objects in their toString() method and thus if we want to ensure universally consistent behaviour we have to define this. No, that is all untrue. Which part is untrue? I said three things: - A program shouldn't want to know an object's [[Class]] - [[Class]] is exposed by ECMAScript in an object's toString() method - If we want to ensure universal behaviour we have to define this You seem to agree with the second point, as you say: The [[Class]] property is exposed in Object.prototype.toString. You presumably agree with the first point since you were asking for a reason and implying there wasn't one. Do you disagree that we need to define things to get universal behaviour? Ensuring universally consistent behavior would require that *all browsers* behave exactly the same. Right, that's the goal. MSIE does not behave that way today and versions of other browsers may vary, too. Indeed, that's the problem we are trying to fix. To ensure safer, more reliable behavior, define the [[Class]] property as being a string value. That way, it would be guaranteed that Object.prototype.toString.call( any_object ); would result in string value being produced, and an error would not occur. As far as I can tell, everyone agrees that [[Class]] should be a string. The value of that string should be implementation-dependent. That would not lead to a well-defined universal behaviour. This makes the feature flexible, extensible, and provides the aforementioned benefits of interfaces over classes (e.g. mixin style behavior with implementation-specific host objects). It seems that the [[Class]] value has nothing to do with the flexibility, extensibility, and mixin style behaviour of objects. Providing a suggestion to implementors as to what that value might be would be harmless. And mostly useless, if they ignore it; if they don't, it might as well be a requirement. Mandating the *value* of that [[Class]] property creates a brittle, fragile API. It creates a well-defined, consistent and predictable API. This is desireable. Authors will utilize the specification to write code to that value to create code that is as brittle and fragile as the API it uses and works in fewer implementations, including browsers that are in widespread use today. I think it is woefully optimistic to expect any significant number of authors to read the specification. Even if a program could know the [[Class]], what's to say it won't change in the future? The specs we write. No, the specifications do change. The specifications we write are the ones that are to say that it won't change. If the specifications say it changes, then it changes. My point is that it is up to the specifications we write to make this not change. The introduction of HTMLFormControls collection, for example, was a new one. There is a possibility of a StaticNodeList or HTMLLinks collection in the future. The interfaces implemented by an object vary between implementations and evolve over time. So long as we converge on a stable and well-implemented platform, early changes are not a problem. Given a particular object, can that object's [[Class]] property change in the future? If it there is an object that exists, say, some sort of HTMLCollection, and it becomes desirable to make more specific behavior, say HTMLFormControlsCollection, what would the code that expects the object's class to be HTMLCollection need to do to continue working in multiple versions of multiple browsers? We would have to test to see if any pages rely on it; if they do, we'd have to make sure we don't change the [[Class]] somehow. That sounds like a brittle feature. It is no more or less brittle than anything else in the Web platform as far as I can tell. Any API could change; it is our responsibility to make sure that we don't change APIs that pages rely on. An object's [[Class]] feature should ideally provide specific, detailed information, and should be used *only* in debugging. Never rely on it. It would be wonderful if that were the case. Given all these reasons, it would still seem like a bad idea to program to an object's [[Class]]. Instead, the interface should be programmed tot using feature detection. Yup. OK. Strings are not a substitute for capability checks. The [[Class]] in particular has very little potential to return information about what an object can do. It would be a very risky design decision to make inferences solely on the [[Class]] value. Yup. We seem to be eye to eye on that much but I think the API design has gone too
Re: [PrototypeRoot]
On Sat, Jun 20, 2009 at 12:43 AM, Ian Hicksoni...@hixie.ch wrote: On Sat, 20 Jun 2009, Garrett Smith wrote: I still want to know: Why would a program want to know the object's [[Class]]? It shouldn't, but [[Class]]es are exposed by ECMAScript objects in their toString() method and thus if we want to ensure universally consistent behaviour we have to define this. No, that is all untrue. The [[Class]] property is exposed in Object.prototype.toString. Ensuring universally consistent behavior would require that *all browsers* behave exactly the same. MSIE does not behave that way today and versions of other browsers may vary, too. To ensure safer, more reliable behavior, define the [[Class]] property as being a string value. That way, it would be guaranteed that Object.prototype.toString.call( any_object ); would result in string value being produced, and an error would not occur. The value of that string should be implementation-dependent. This makes the feature flexible, extensible, and provides the aforementioned benefits of interfaces over classes (e.g. mixin style behavior with implementation-specific host objects). Providing a suggestion to implementors as to what that value might be would be harmless. Mandating the *value* of that [[Class]] property creates a brittle, fragile API. Authors will utilize the specification to write code to that value to create code that is as brittle and fragile as the API it uses and works in fewer implementations, including browsers that are in widespread use today. Even if a program could know the [[Class]], what's to say it won't change in the future? The specs we write. No, the specifications do change. The introduction of HTMLFormControls collection, for example, was a new one. There is a possibility of a StaticNodeList or HTMLLinks collection in the future. The interfaces implemented by an object vary between implementations and evolve over time. Given a particular object, can that object's [[Class]] property change in the future? If it there is an object that exists, say, some sort of HTMLCollection, and it becomes desirable to make more specific behavior, say HTMLFormControlsCollection, what would the code that expects the object's class to be HTMLCollection need to do to continue working in multiple versions of multiple browsers? We would have to test to see if any pages rely on it; if they do, we'd have to make sure we don't change the [[Class]] somehow. That sounds like a brittle feature. An object's [[Class]] feature should ideally provide specific, detailed information, and should be used *only* in debugging. Never rely on it. Given all these reasons, it would still seem like a bad idea to program to an object's [[Class]]. Instead, the interface should be programmed tot using feature detection. Yup. OK. Strings are not a substitute for capability checks. The [[Class]] in particular has very little potential to return information about what an object can do. It would be a very risky design decision to make inferences solely on the [[Class]] value. We seem to be eye to eye on that much but I think the API design has gone too far. Defining the value of the [[Class]] encourages that value to be used in code. That is bad! Programmers who rely on that value will not rightly blame themselves for their design mistakes. Instead, they will look externally, read the standard, and blame the implementations that don't do what their perfectly standards-compliant program expects Garrett
Re: [PrototypeRoot]
Ian Hickson: I don't really mind exactly what the solution is; my only concern here would be that I'd be throwing [PrototypeRoot] around a lot. Acknowledged. If you can propose a way of defining this without needing to use [PrototypeRoot] a lot, that’d help. (I assume with PrototypeRoot that the most-derived interface that inherits from such an interface is automatically promoted to being the [[Class]]?) That’s right. -- Cameron McCormack ≝ http://mcc.id.au/
Re: [PrototypeRoot]
On 6/20/09, Cameron McCormack c...@mcc.id.au wrote: Ian Hickson: I don't really mind exactly what the solution is; my only concern here would be that I'd be throwing [PrototypeRoot] around a lot. Acknowledged. If you can propose a way of defining this without needing to use [PrototypeRoot] a lot, that’d help. (I assume with PrototypeRoot that the most-derived interface that inherits from such an interface is automatically promoted to being the [[Class]]?) That’s right. I still want to know: Why would a program want to know the object's [[Class]]? Even if a program could know the [[Class]], what's to say it won't change in the future? Given a particular object, can that object's [[Class]] property change in the future? If it there is an object that exists, say, some sort of HTMLCollection, and it becomes desirable to make more specific behavior, say HTMLFormControlsCollection, what would the code that expects the object's class to be HTMLCollection need to do to continue working in multiple versions of multiple browsers? Microsoft has had vendor extensions in IE prior to the w3c dom level 1. Such vendor extensions don't fall nicely into type heirarchies, but are well-suited towards mixin style design, which is possible with interfaces. Also, there will always be more browsers that implement an interface, but don't give that object the [[Class]] property that is specified in web IDL. Given all these reasons, it would still seem like a bad idea to program to an object's [[Class]]. Instead, the interface should be programmed to using feature detection. Even the [[Class]] were widespread-adopted, it would be a bad idea to do that. I don't know what I am missing, but it doesn't seem to have been explained on this thread. Why do you want that? Garrett -- Cameron McCormack ≝ http://mcc.id.au/
Re: [PrototypeRoot]
On Sat, 20 Jun 2009, Cameron McCormack wrote: Ian Hickson: I don't really mind exactly what the solution is; my only concern here would be that I'd be throwing [PrototypeRoot] around a lot. Acknowledged. If you can propose a way of defining this without needing to use [PrototypeRoot] a lot, that’d help. Given an object and a list of interface that it implements, remove interfaces from the list that match any of the following conditions: - the interface was on the right hand side of an 'implements' clause the left hand side of which lists an interface that the object implements - the interface is inherited from another interface the object implements - the interface has [NoInterfaceObject] ...you should be lift with one interface. Use its name as the [[Class]]. Are there any objects where that leaves an ambiguity? -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [PrototypeRoot]
On Sat, 20 Jun 2009, Garrett Smith wrote: I still want to know: Why would a program want to know the object's [[Class]]? It shouldn't, but [[Class]]es are exposed by ECMAScript objects in their toString() method and thus if we want to ensure universally consistent behaviour we have to define this. Even if a program could know the [[Class]], what's to say it won't change in the future? The specs we write. Given a particular object, can that object's [[Class]] property change in the future? If it there is an object that exists, say, some sort of HTMLCollection, and it becomes desirable to make more specific behavior, say HTMLFormControlsCollection, what would the code that expects the object's class to be HTMLCollection need to do to continue working in multiple versions of multiple browsers? We would have to test to see if any pages rely on it; if they do, we'd have to make sure we don't change the [[Class]] somehow. Given all these reasons, it would still seem like a bad idea to program to an object's [[Class]]. Instead, the interface should be programmed to using feature detection. Yup. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [PrototypeRoot]
Cameron McCormack: Done: The value of the internal [[Class]] property of a host object is determined as follows: * If the host object implements a single interface, then the value of the internal [[Class]] property MUST be the identifier of that interface. Ian Hickson: I think it would make sense to exclude [NoPrototypeObject] interfaces from consideration here. I assume you mean [NoInterfaceObject]? Is the reasoning for this that [NoInterfaceObject] inerfaces are nearly always “mixins”, and so shouldn’t affect the [[Class]]? Cameron McCormack: Note that this still technically does not mean you can guarantee that the NodeList returned by querySelectorAll() has [[Class]] == NodeList, since it could be that that host object implements another interface, which might be required by another spec, or perhaps just because the implementation wants to. Ian Hickson: IMHO this is a problem. I don't think that UA extensions should affect the [[Class]], and I think that other specs should have a way (e.g. [NoPrototypeObject]) of always making sure they don't affect the [[Class]] of existing stuff. Do you still think it would be bad to use [ProtoypeRoot] on interfaces like NodeList, to indicate that it is the “main” interface? That would be the way, currently, to require a particular [[Class]] that could not be overridden by having a second interface be implemented. Thanks, Cameron -- Cameron McCormack ≝ http://mcc.id.au/
Re: [PrototypeRoot]
On Sat, Mar 7, 2009 at 4:03 PM, Ian Hickson i...@hixie.ch wrote: On Sat, 7 Mar 2009, Cameron McCormack wrote: Done: The value of the internal [[Class]] property of a host object is determined as follows: * If the host object implements a single interface, then the value of the internal [[Class]] property MUST be the identifier of that interface. I think it would make sense to exclude [NoPrototypeObject] interfaces from consideration here. Note that this still technically does not mean you can guarantee that the NodeList returned by querySelectorAll() has [[Class]] == NodeList, since it could be that that host object implements another interface, which might be required by another spec, or perhaps just because the implementation wants to. IMHO this is a problem. What is the problem? I don't think that UA extensions should affect the [[Class]], and I think that other specs should have a way (e.g. [NoPrototypeObject]) of always making sure they don't affect the [[Class]] of existing stuff. An API based on interfaces (the DOM, for example), can only reflect one interface (at most0 in the [[Class]]. What is your use case for designing a program around having to know the [[Class]]? Garrett
Re: [PrototypeRoot]
On Sat, 7 Mar 2009, Cameron McCormack wrote: Done: The value of the internal [[Class]] property of a host object is determined as follows: * If the host object implements a single interface, then the value of the internal [[Class]] property MUST be the identifier of that interface. I think it would make sense to exclude [NoPrototypeObject] interfaces from consideration here. Note that this still technically does not mean you can guarantee that the NodeList returned by querySelectorAll() has [[Class]] == NodeList, since it could be that that host object implements another interface, which might be required by another spec, or perhaps just because the implementation wants to. IMHO this is a problem. I don't think that UA extensions should affect the [[Class]], and I think that other specs should have a way (e.g. [NoPrototypeObject]) of always making sure they don't affect the [[Class]] of existing stuff. -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'
Re: [PrototypeRoot]
Ian Hickson: In that case I would like us to do this (specifically, define [[Class]] for objects that have only one non-[NoPrototypeObject] interface), since that's the majority of them, and it would be better than having to sprinkle [PrototypeRoot] all over the place. Done: The value of the internal [[Class]] property of a host object is determined as follows: * If the host object implements a single interface, then the value of the internal [[Class]] property MUST be the identifier of that interface. * Otherwise, if the host object has a primary prototype interface, then the value of the internal [[Class]] property MUST be the identifier of that interface. * Otherwise, no particular value is required to be used for the value of the internal [[Class]] property. — http://dev.w3.org/2006/webapi/WebIDL/#host-objects Note that this still technically does not mean you can guarantee that the NodeList returned by querySelectorAll() has [[Class]] == NodeList, since it could be that that host object implements another interface, which might be required by another spec, or perhaps just because the implementation wants to. There’s nothing in selectors-api that says “the object returned from querySelectorAll() must implement the NodeList interface and no others” (and I don’t think it’d be a good idea to require that). -- Cameron McCormack ≝ http://mcc.id.au/