This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 22343 - [DOM]: Need a function to retrieve a constructor (or prototype) by localName
Summary: [DOM]: Need a function to retrieve a constructor (or prototype) by localName
Status: RESOLVED NEEDSINFO
Alias: None
Product: WebAppsWG
Classification: Unclassified
Component: DOM (show other bugs)
Version: unspecified
Hardware: PC Windows NT
: P2 normal
Target Milestone: ---
Assignee: Anne
QA Contact: public-webapps-bugzilla
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-06-12 19:06 UTC by Scott Miles
Modified: 2014-11-21 17:36 UTC (History)
7 users (show)

See Also:


Attachments

Description Scott Miles 2013-06-12 19:06:06 UTC
To produce a prototype chain that extends an arbitrary element to pass to document.register requires (in the general case) that one create an instance of the element to extend. 

This is slightly inefficient, but much worse is that instancing an element can have unwanted side-effects.

I suggest we need something like `document.getConstructorForTag(tagName)`.
Comment 1 Dominic Cooney 2013-06-13 11:07:32 UTC
This sounds reasonable to me. So the proposal is

partial interface Document {
  any getConstructorForTag(DOMString tag);
}

?

Is there a more precise type for these than "any"?

I assume this returns constructors for registered custom elements? Does that present any problems for people using Custom Elements with ES6 classes?

What does it do if there's no such tag? Raise NotFoundError? Return HTMLUnknownElement?

What about accessing SVG element constructors?

Just out of curiosity--why constructors and not prototypes?
Comment 2 Scott Miles 2013-06-13 22:16:07 UTC
> What does it do if there's no such tag? ... Return HTMLUnknownElement?

Returning HTMLUnknownElement seems like the right choice, since this is what I get if I document.createElement with the same input.

> What about accessing SVG element constructors?

I don't know the ins and outs here.

> Just out of curiosity--why constructors and not prototypes?

The vague notion that the prototype is in service of the constructor, so 'constructor' is driving the bus. For example, it feels more reliable to evaluate 'constructor.prototype' then 'prototype.constructor', and it's easier to compare against known objects (e.g. HTMLImageElement).

For my particular use case, I only actually want the prototype.
Comment 3 Dominic Cooney 2013-06-14 00:20:08 UTC
What do you think about putting this on the constructor. That gives you some built-in namespacing, e.g.

HTMLElement.getConstructorForTagName('div') ~> HTMLDivElement
SVGElement.getConstructorForTagName('use') ~> SVGUseElement
Comment 4 Scott Miles 2013-06-14 01:08:29 UTC
That sounds good to me.
Comment 5 Dimitri Glazkov 2013-06-19 21:51:38 UTC
This seems like a (useful) general DOM function, not specifically related to Custom Elements. I don't mind monkeypatching this into Custom Elements spec, but it might be better to just add it straight to DOM?
Comment 6 Dominic Cooney 2013-06-20 00:56:19 UTC
(In reply to comment #5)
> This seems like a (useful) general DOM function, not specifically related to
> Custom Elements. I don't mind monkeypatching this into Custom Elements spec,
> but it might be better to just add it straight to DOM?

Since DOM does not define specific elements, should we instead add them straight to HTML and SVG?
Comment 7 Anne 2013-06-20 01:58:48 UTC
Given that we don't have constructors for all elements yet, isn't this a bit soon? Some of this might belong in DOM, given how createElement() / createElementNS() work.

As noted elsewhere, createElement("audio") and new Audio() do different things, is that something we want to keep, or are we moving away from that?
Comment 8 Dominic Cooney 2013-06-21 08:23:23 UTC
(In reply to comment #7)
> Given that we don't have constructors for all elements yet, isn't this a bit
> soon? Some of this might belong in DOM, given how createElement() /
> createElementNS() work.

This could just return the closest available constructor, for example

HTMLElement.getConstructorForTag('ins') === HTMLModElement

> As noted elsewhere, createElement("audio") and new Audio() do different
> things, is that something we want to keep, or are we moving away from that?

Scott mentioned he wants to mint prototype chains, so I guess HTMLElement.getConstructorForTag('img') === HTMLImageElement.prototype and not Image.prototype?

Alternatively, does making this getPrototypeForTag instead of getConstructorForTag address some concerns?
Comment 9 Anne 2013-06-21 08:39:40 UTC
But there are no constructors at the moment. And I'm not sure we want to make HTMLModElement a constructor. It has no tie to any particular local name. It'd be like making Node a constructor.

The difference between createElement("audio") and new Audio() is that the latter sets an attribute. I think we might want to end up with doing that for both though so that the former can simply map to the latter.
Comment 10 Dominic Cooney 2013-06-21 09:35:17 UTC
(In reply to comment #9)
> The difference between createElement("audio") and new Audio() is that the
> latter sets an attribute. I think we might want to end up with doing that
> for both though so that the former can simply map to the latter.

Ah, interesting--I did not know this.

> But there are no constructors at the moment. And I'm not sure we want to
> make HTMLModElement a constructor. It has no tie to any particular local
> name. It'd be like making Node a constructor.

Maybe this is just a naming issue...

I believe Scott wants a function which has these two properties:

o.f(x).prototype === Object.getPrototypeOf(document.createElement(x))

document.createElement(x) instanceof o.f(x)

With the proposal that o is one of {HTMLElement, SVGElement} and f is getConstructorForTagName.
Comment 11 Anne 2013-06-23 03:27:20 UTC
Except it's not the constructor. If we actually introduce constructors for elements we'll likely have a 1:1-mapping rather than the current situation. So exposing APIs which further expose the current brittleness seems like a bad idea.
Comment 12 Dominic Cooney 2013-06-24 14:20:07 UTC
(In reply to comment #11)
> Except it's not the constructor.

Yes. I guess these are Interface Objects, but getInterfaceObjectForTagName is gross. What about:

HTMLElement.getPrototypeForTagName('div') ~> HTMLDivElement.prototype.

That should be 1:1; the name is nice, it is vaguely reminiscent of Object.getPrototypeOf.

WDYT?
Comment 13 Anne 2013-06-24 14:29:45 UTC
You don't think it would be better to first introduce constructors? Such as HTMLH1Element and co? Because at that point that method would return different results and it would be somewhat unfortunate if people started to rely on the current results (although they might already to some extent I suppose).
Comment 14 Dominic Cooney 2013-06-24 14:52:00 UTC
(In reply to comment #13)
> You don't think it would be better to first introduce constructors?

I think with constructors, this mapping is still useful. I'm not sure about the order of moves here... do you think constructors will happen in a nontrivial timeframe?

> Such as
> HTMLH1Element and co? Because at that point that method would return
> different results and it would be somewhat unfortunate if people started to
> rely on the current results (although they might already to some extent I
> suppose).

HTMLElement.getPrototypeForTagName('h1') has better backwards compat than HTMLHeadingElement.prototype.

It is true that web developers could start to depend on some specific aspects of the object getPrototypeForTagName returns, like prototype chain depth, and that would be unfortunate.
Comment 15 Anne 2013-06-24 15:20:09 UTC
In a non-trivial timeframe sounds about right, as I've no idea.
Comment 16 Dominic Cooney 2013-06-25 00:24:21 UTC
For the fossil record I believe this is the thread discussing constructors: <http://lists.w3.org/Archives/Public/public-webapps/2013AprJun/0152.html>
Comment 17 Dimitri Glazkov 2013-06-25 20:51:21 UTC
(In reply to comment #15)
> In a non-trivial timeframe sounds about right, as I've no idea.

What's our non-geological timeframe solution to this, then?
Comment 18 Scott Miles 2013-06-25 20:56:06 UTC
  HTMLElement.getPrototypeForTagName('div')

would work for me, if that helps.

Presumably one could retrieve a constructor (or perhaps even a selection of constructors) from the prototype.
Comment 19 Dominic Cooney 2013-08-29 21:04:14 UTC
Moving this to DOM per Comment 5.
Comment 20 Anne 2014-05-22 13:52:23 UTC
If we go with comment 3 this should be in WHATWG => HTML. Still not entirely sure whether this is the way forward though.
Comment 21 Domenic Denicola 2014-05-22 15:41:20 UTC
I re-read this thread several times, but I don't understand what problem this solves. Can someone give a code example that uses this function?