Subclassing built-in constructors (was: TC39 meeting Wed 5/23/2012)
On May 26, 2012, at 2:37 AM, David Bruant wrote:
Le 24/05/2012 20:10, Brendan Eich a écrit :
...
Not just array -- DOM too. DOM is a very interesting case, because the proto operator was not an option for them since most of them are created by method calls (not even constructors) and the DOM API is not at all thought to change the prototype (like JSON.parse).
Based upon discussions I've had with some folks (browser engineers, not DOM programmers) on the DOM side of the world, my impression is that they don't want DOM objects to be subclassable. They are disinclined to "trust" any objects other than actual "host objects" they construct. I believe the WebIDL spec. actually requires that DOM APIs reject any such "subclass" objects that were created via ES code and passed to DOM methods in parameter positions that are "typed" with specific DOM interfaces.
Personally, I think that perspective is too conservative. However, it is something to keep in mind if we move into discussions of this topic.
) cannot be achieved anymore.
So don't delete proto :-P.
Really, you can't have it both ways. If you want Zepto, you are not running SES code. Let's see if someone can "cajole" Zepto and then talk. What I was getting at by mentionning Zepto was more about the use case that led to the decision to use proto rather than Zepto itself.
I agree, if proto becomes blessed as a normal feature of the language it will get even wider use than it has today. Especially by framework builders. I'm skeptical that routinely killing it will be practical. Flipping the issue: proto is probably of most use to the developers of framework of various sorts. If proto is routinely disabled by hosting environments then such frameworks can't depend upon its availability and hence can't use it.
The use case of subclassing native constructors (just to clarify I'm only talking about Array, Date, WeakMap, etc. Not DOM constructors) is legitimate and has been raised and detailed in length 1 (the initial message does not point that out, but the rest of the thread does). Being able to securely do that is still a use case. The proto operator was a solution to it but it's out. proto is out because secure JS code first instruction will be to delete it on go on as if it never existed. Extracting just a proto setter is not an option according to what you're saying below. What is there left for the subclassing use case? So far, I don't see anything. The aforementioned thread raised 2 interesting alternatives to proto [2] [3] for the subclassing use case. Could it be considered to standardize any of these functions (or something else as long as it solves the use case)? Unlike grawlix, this function will be polyfillable with proto where it's available. In platform with a native support for this function, it will be possible to both use this function (solving the use case) and delete proto (doing it safely).
Does it sounds like a good alternative?
Because max-min classes are inching towards consensus, I suggest the that appropriate way to subclass the built-in constructors will be via |class extends|. eg
class MyArray extends Array { someMyArrayProtoMethod () {...} constructor (tag) { super(); this.tag=tag } }
I'm quite confident this can be made to work in a backwards compatible manner. I will write a strawman explaining the details.
Also I believe Date and many of the other built-ins can be respecified in a manner that enables them to be subclassed using traditional ad hoc techniques. For example, the only real "magic" in Date instance is its [[PrimitiveValue]] internal property. Date can be made subclassables by replacing [[PrimitiveValue]] by a regular property with a private name.
Finally, note that in the Internationalization spec. 1 we have tried to avoid the subclassing problem from the start. Even though the constructor defined in that spec. create instances that make extensive use of [[internal properties]] they have been defined in a manner that enables even ad hoc "subclassing". All it takes is an actual or equivalent super call. EG: Intl.Collator.call(collatorSubclassInstance). I favor adopting the pattern used in 1 for all new built-in constructors.
Allen
Le 24/05/2012 20:10, Brendan Eich a écrit :
DOM is a very interesting case, because the proto operator was not an option for them since most of them are created by method calls (not even constructors) and the DOM API is not at all thought to change the prototype (like JSON.parse).
What I was getting at by mentionning Zepto was more about the use case that led to the decision to use proto rather than Zepto itself.
The use case of subclassing native constructors (just to clarify I'm only talking about Array, Date, WeakMap, etc. Not DOM constructors) is legitimate and has been raised and detailed in length [1] (the initial message does not point that out, but the rest of the thread does). Being able to securely do that is still a use case. The proto operator was a solution to it but it's out. proto is out because secure JS code first instruction will be to delete it on go on as if it never existed. Extracting just a proto setter is not an option according to what you're saying below. What is there left for the subclassing use case? So far, I don't see anything. The aforementioned thread raised 2 interesting alternatives to proto [2] [3] for the subclassing use case. Could it be considered to standardize any of these functions (or something else as long as it solves the use case)? Unlike grawlix, this function will be polyfillable with proto where it's available. In platform with a native support for this function, it will be possible to both use this function (solving the use case) and delete proto (doing it safely).
Does it sounds like a good alternative?
And I realize that the new hazard is not due to proto in itself, but rather to the capability of arbitrarily changing the prototype of an object, so adding an Object.setPrototypeOf really is a step backward.
David
[1] esdiscuss/2011-March/013131 [2] esdiscuss/2011-March/013141 [3] esdiscuss/2011-March/013154