- From: Boris Zbarsky <bzbarsky@mit.edu>
- Date: Fri, 09 Jan 2015 22:31:17 -0500
- To: Domenic Denicola <d@domenic.me>, Anne van Kesteren <annevk@annevk.nl>, WebApps WG <public-webapps@w3.org>, "www-dom@w3.org" <www-dom@w3.org>
On 1/9/15 8:01 PM, Domenic Denicola wrote: > I was writing up my ideas in an email but it kind of snowballed into something bigger so now it's a repo: https://github.com/domenic/element-constructors Domenic, thanks for putting this together. Caveat: I won't get a chance to read through this carefully until Monday. Responses below are based on just what's in the mail. That said, I do have one question already: what does the term "own-instances" mean in that document? >> whether it is acceptable to have an element whose name is "a", namespace is the HTML namespace, and interface is Element I'd like to understand what you mean by "interface is Element" here, exactly. > One ugly point of my design is that the constructor signature is `new Element(localName, document, namespace, prefix)`, i.e. I require the document to be passed in. I am not sure this is necessary It's necessary, but I think the document should be allowed, but not required. As in, the signature should be: new Element(localName, namespace, prefix, document). (though maybe prefix should come after document; hard to say). If the document is undefined, then we get a document as follows: Element is a function, so has an associated Realm. This Realm's [[globalThis]] is a Window. This Window has a .document; use that. The only reason we need the ability to specify a document at all is that there are documents around that are not inside a browsing context (XHR responseXML, for example) and we need to be able to create elements that have those documents as an ownerDocument. But those document's don't have their own global/Realm and hence don't have separate instances of the Element constructor. I commented on the github issue in a bit less detail. >> what is the use case for producing something that extends HTMLImageElement (and presumably has its internal slots?) but doesn't have "img" as the tag name and hence will not have anything ever look at those internal slots? > > Elsehwere on this thread or some related one IIRC he pointed out code that looks at the local name, finds "img", and casts to the C++ backing representation of HTMLImageElement. So from what I am gathering in his view the parts of the platform that treat <img> elements specially currently work by checking explicitly that something has local name "img" (and HTML namespace). Yes. And that's true of not just implementations but also specifications. The entire HTML specification is written in terms of local name tests, for example. > From a naïve authoring point of view that seems suboptimal. I'd rather be able to do `class MyImg extends HTMLImageElement { constructor(document) { super(document); } }` and have MyImg instances treated specially by the platform in all the ways "img" currently is. I don't quite see the issue here. Presumably the HTMLImageElement constructor passes "img" as the localName to the HTMLElement constructor, so your MyImg would get "img" as the localName, right? Can you explain what the concern is here? Now I do think there's an authoring problem where if you want to do a <fancyimage> that's treated like <img> by the platform you have a problem. But that doesn't seem to be what you're talking about... or are you? > Or, for an easier example, I'd like to be able to do `class MyQ extends HTMLQuoteElement { constructor(document) { super(document); } }` and have `(new MyQ()).cite` actually work, instead of throw a "cite getter incompatible with MyQ" error because I didn't get the HTMLQuoteElement internal slots. This should totally work, of course. Why wouldn't it, exactly? Given the subclassing proposal on the table in ES6 right now, it would work splendidly, since the HTMLQuoteElement constructor is what would perform the object allocation and it would pass along "q" as the localName. (Though actually, HTMLQuoteElement is excitingly complicated, because both <q> and <blockquote> would use that constructor, so it would need to either require one of those two strings be passed in, or default to "q" unless "blockquote" is passed in or something.) > The logical extension of this, then, is that if after that `document.registerElement` call I do `document.body.innerHTML = <my-q cite="foo">blah</my-q>` Ah, here we go. This is the part where the trouble starts, indeed. This is why custom elements currently uses <q is="my-q"> for creating custom element subclasses of things that are more specific than HTMLElement. Yes, it's ugly. But the alternative is at least major rewrite of the HTML spec and at least large parts of Gecko/WebKit/Blink. :( I can't speak to whether Trident is doing a bunch of localName checks internally. > However this idea that we'd like custom elements which inherit from existing elements to have their internal slots ties in to the whole upgrading mess Right, which you get for free with the <q is="my-q"> setup, since you just get the slots for <q> and then the upgrade just has to worry about your proto chain... > i.e. it might not be possible at all to make upgraded elements behave anything like parsed-from-scratch elements. I fully expect upgraded elements to perform worse than parsed-from-scratch elements in practice, because of the deoptimizing effects of the dynamic __proto__ mutation involved in the upgrade. Maybe JS engines will work on making this deoptimize less, but it's not clear to me that it's been a huge priority for them so far. -Boris
Received on Saturday, 10 January 2015 03:31:50 UTC