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 20487 - [Custom]: Creation of custom elements via createElement is underdefined
Summary: [Custom]: Creation of custom elements via createElement is underdefined
Status: RESOLVED FIXED
Alias: None
Product: WebAppsWG
Classification: Unclassified
Component: HISTORICAL - Component Model (show other bugs)
Version: unspecified
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: Dimitri Glazkov
QA Contact: public-webapps-bugzilla
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 20684
  Show dependency treegraph
 
Reported: 2012-12-22 00:01 UTC by Boris Zbarsky
Modified: 2013-02-08 23:46 UTC (History)
4 users (show)

See Also:


Attachments

Description Boris Zbarsky 2012-12-22 00:01:03 UTC
Consider this script:


  var proto = { myProp: 1 };
  proto.__proto__ = HTMLElement.prototype;
  var fun = document.register("x-foo", { prototype: obj });
  
  var elem1 = document.createElement("x-foo");
  var elem2 = document.createElement("X-FOO");
  var elem3 = document.createElementNS(null, "x-foo");
  var elem4 = document.createElementNS(null, "X-FOO");
  var elem5 = document.createElementNS("http://www.w3.org/1999/xhtml", "x-foo");
  var elem6 = document.createElementNS("http://www.w3.org/1999/xhtml", "X-FOO");

as far as I can tell, the specification does not define which of those elements, if any, have "proto" as their proto, nor whether it depends on whether "document" is an HTML document or an XML/XHTML document.

This is not a hypothetical problem: we just had two implementors who were trying to guess what the spec might maybe mean here write two different incompatible implementations.
Comment 1 Olli Pettay 2012-12-22 14:33:09 UTC
did you mean 
var fun = document.register("x-foo", { prototype: proto });
not
var fun = document.register("x-foo", { prototype: obj });
?
Comment 2 Boris Zbarsky 2012-12-22 23:09:12 UTC
Yes, I did.  Sorry, renamed the protoobj partway through the comment, and didn't catch all the uses....
Comment 4 Boris Zbarsky 2013-01-22 22:20:08 UTC
You need to patch createElementNS too.

And presumably have a namespace check, somewhere?  Or should registering "x-foo" affect both html:x-foo and svg:x-foo?
Comment 5 Dimitri Glazkov 2013-01-22 22:32:41 UTC
(In reply to comment #4)
> You need to patch createElementNS too.
> 
> And presumably have a namespace check, somewhere?  Or should registering
> "x-foo" affect both html:x-foo and svg:x-foo?

Yup, working on it. 

I am thinking something along the lines of: you can't create custom elements out of it unless your namespace and qualifiedName are asking for HTML namespace. I need to read up on whether this still lets us create SVGElement-derived custom elements. I think it does.
Comment 6 Boris Zbarsky 2013-01-22 22:49:37 UTC
> I think it does.

No, I don't think it would.

Furthermore the current text does not allow that sort of thing anyway, since it requires that prototypes "inherit from HTMLElement.prototype", whatever that means.  It sure sounds like deriving things from SVG elements is excluded, though.
Comment 7 Dimitri Glazkov 2013-01-22 23:35:37 UTC
(In reply to comment #6)
> > I think it does.
> 
> No, I don't think it would.

You're right.

> 
> Furthermore the current text does not allow that sort of thing anyway, since
> it requires that prototypes "inherit from HTMLElement.prototype", whatever
> that means.  It sure sounds like deriving things from SVG elements is
> excluded, though.

Aside from incorrect wording, I am wondering if I should ignore SVG elements, at least for now.

Ian pointed out that ideally, it should be possible to create custom SVG elements as well, but there's a lot of complexity that starts creeping here once I open that pandora's box.

I have no intention to ever introduce namespaces here, so it should be possible to add SVG support later: the custom element namespace would be resolved based on inherited interface.

WDYT?
Comment 8 Boris Zbarsky 2013-01-24 20:38:28 UTC
That might be doable somehow by basically special-casing particular namespaces _somewhere_ in the spec, yes.
Comment 9 Dimitri Glazkov 2013-01-28 23:22:24 UTC
I think I finally got it. https://dvcs.w3.org/hg/webcomponents/rev/1b0e39e2d815 and https://dvcs.w3.org/hg/webcomponents/rev/d46c3b299481.

Boris, can you pls take a look?

https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#monkeypatch-create-element

Anne, I liked the wording that you've added, but I still needed to replace the steps in my monkeypatch, because I have to:

a) define how interface is determined -- I wonder if this could be a different monkeypatch in HTML?
b) run instantiation/finalization steps before I return out of createElement/NS.
Comment 10 Boris Zbarsky 2013-01-29 06:14:53 UTC
> When a custom element is instantiated with the createElement method,

The concept of "custom element" is not defined in a way that I can tell, as a createElement implementor, whethere I'm creating a "custom element".

Perhaps this should simply say "When an element is instantiated..."?

The custom element instantiation algorithm might need to say something about what happens if the namespace is neither HTML nor SVG.  Or can that situation not arise?

I don't think anything defines how to tell whether a custom interface inherits from HTMLElement.  I certainly can't find anything that defines it.

The custom element instantiation algorithm creates HTML-namespaced elements even if we're extending SVG elements.  That seems ... odd.

> Let CHAIN be ELEMENT's prototype chain, in reverse order (starting with at the
> top of the prototype chain)

Is the "top" Object.prototype or the other end?  Better to say which end you're starting with (e.g. the prototype closest to the object or furthest away) instead of assuming your mental geometry matches other people's.

Apart from those, this is starting to look much better, yes.  I think at this point the createElement bits are fine and the remaining vagueness has been pushed to elsewhere.  ;)
Comment 11 Dimitri Glazkov 2013-01-30 00:04:25 UTC
(In reply to comment #10)
> > When a custom element is instantiated with the createElement method,
> 
> The concept of "custom element" is not defined in a way that I can tell, as
> a createElement implementor, whethere I'm creating a "custom element".
> 
> Perhaps this should simply say "When an element is instantiated..."?

Sounds good: https://dvcs.w3.org/hg/webcomponents/rev/709e43cb4699

> 
> The custom element instantiation algorithm might need to say something about
> what happens if the namespace is neither HTML nor SVG.  Or can that
> situation not arise?

As spec'd now, you can build a non-HTML/SVG Element and get away with instantiating it in any namespace. Which seems fine.

> 
> I don't think anything defines how to tell whether a custom interface
> inherits from HTMLElement.  I certainly can't find anything that defines it.

This is true. I need to think about this. I think the solution is to just use the Web IDL's concept of inheritance (http://www.w3.org/TR/WebIDL/#dfn-inherit), but then specify how custom element's interface is defined.

> 
> The custom element instantiation algorithm creates HTML-namespaced elements
> even if we're extending SVG elements.  That seems ... odd.

No, as spec'd now, it will throw a NamespaceError. Which actually might be bad. For:

var s = document.createElement('svg')

WebKit simply creates an HTMLUnknownElement. Should I do that instead? It seems more error-prone.

> 
> > Let CHAIN be ELEMENT's prototype chain, in reverse order (starting with at the
> > top of the prototype chain)
> 
> Is the "top" Object.prototype or the other end?  Better to say which end
> you're starting with (e.g. the prototype closest to the object or furthest
> away) instead of assuming your mental geometry matches other people's.

Will fix.

> 
> Apart from those, this is starting to look much better, yes.  I think at
> this point the createElement bits are fine and the remaining vagueness has
> been pushed to elsewhere.  ;)

Yay! Now to push it out all the way :)
Comment 12 Boris Zbarsky 2013-01-30 06:52:32 UTC
> As spec'd now, you can build a non-HTML/SVG Element and get away with
> instantiating it in any namespace. Which seems fine.

I think if you try to instantiate an element not in the HTML namespace which has HTMLElement.prototype on the proto chain we should consider making that not work.  Just my 2 cents.

> No, as spec'd now, it will throw a NamespaceError

Why?

>var s = document.createElement('svg')
>WebKit simply creates an HTMLUnknownElement. 

I think so does everyone else.  Certainly Gecko does (in an HTML document).
Comment 13 Dimitri Glazkov 2013-01-30 23:46:55 UTC
(In reply to comment #12)
> > As spec'd now, you can build a non-HTML/SVG Element and get away with
> > instantiating it in any namespace. Which seems fine.
> 
> I think if you try to instantiate an element not in the HTML namespace which
> has HTMLElement.prototype on the proto chain we should consider making that
> not work.  Just my 2 cents.

Good point.

> 
> > No, as spec'd now, it will throw a NamespaceError
> 
> Why?

Because of this line:

"If INTERFACE inherits from SVGElement and NAMESPACE is not SVG namespace, throw a NamespaceError and stop."

I am not sure if that's the right behavior, though.

> 
> >var s = document.createElement('svg')
> >WebKit simply creates an HTMLUnknownElement. 
> 
> I think so does everyone else.  Certainly Gecko does (in an HTML document).

WDYT, should we keep the same lackadaisical behavior for custom elements? For example, for a custom element "super-svg", that extends SVGSVGElement:

var superSvg1 = document.createElement('super-svg');

Should it:

a) throw NamespaceError
b) returns HTMLUnknownElement
c) returns the instance of "super-svg" custom element?
Comment 14 Boris Zbarsky 2013-01-31 02:35:31 UTC
> "If INTERFACE inherits from SVGElement and NAMESPACE is not SVG namespace,
> throw a NamespaceError and stop."

Oh, that part is just fine.  The problem is that in the very next step NAMESPACE is completely ignored and the element is created in the HTML namespace no matter what NAMESPACE was.  So if the incoming NAMESPACE is SVG and the interface inherits from SVGElement we'll get to step 5 and happily create ... an HTML element.

> WDYT, should we keep the same lackadaisical behavior for custom elements?
> For example, for a custom element "super-svg", that extends SVGSVGElement:
> 
> var superSvg1 = document.createElement('super-svg');
> 
> Should it:
> 
> a) throw NamespaceError

I would probably be OK with this.

> b) returns HTMLUnknownElement

I would be OK with this as long as the super-svg custom stuff is not applied to it...

> c) returns the instance of "super-svg" custom element?

I would probably be OK with this one too.

Worth roping in Anne to see what his thoughts are on createElement here.
Comment 15 Dimitri Glazkov 2013-02-01 23:35:10 UTC
(In reply to comment #14)
> > "If INTERFACE inherits from SVGElement and NAMESPACE is not SVG namespace,
> > throw a NamespaceError and stop."
> 
> Oh, that part is just fine.  The problem is that in the very next step
> NAMESPACE is completely ignored and the element is created in the HTML
> namespace no matter what NAMESPACE was.  So if the incoming NAMESPACE is SVG
> and the interface inherits from SVGElement we'll get to step 5 and happily
> create ... an HTML element.

I am terrible. Thank you for pointing this out.
https://dvcs.w3.org/hg/webcomponents/rev/c417c040987a

> 
> > WDYT, should we keep the same lackadaisical behavior for custom elements?
> > For example, for a custom element "super-svg", that extends SVGSVGElement:
> > 
> > var superSvg1 = document.createElement('super-svg');
> > 
> > Should it:
> > 
> > a) throw NamespaceError
> 
> I would probably be OK with this.

I sort of prefer this one, since it's very likely the user is unintentionally making a mistake by attempting to create a custom element in the wrong namespace.

> 
> > b) returns HTMLUnknownElement
> 
> I would be OK with this as long as the super-svg custom stuff is not applied
> to it...
> 
> > c) returns the instance of "super-svg" custom element?
> 
> I would probably be OK with this one too.
> 
> Worth roping in Anne to see what his thoughts are on createElement here.

Anne, WDTY?
Comment 16 Anne 2013-02-07 12:49:52 UTC
I defined a hook recently to fix a similar bug for HTML (so it can say that for "a" and "http://www.w3.org/1999/xhtml" you use HTMLAnchorElement).

http://dom.spec.whatwg.org/#concept-element-interface

As far as I can tell you should be able to use that hook to define the appropriate interface.
Comment 17 Dimitri Glazkov 2013-02-07 22:25:02 UTC
(In reply to comment #16)
> I defined a hook recently to fix a similar bug for HTML (so it can say that
> for "a" and "http://www.w3.org/1999/xhtml" you use HTMLAnchorElement).
> 
> http://dom.spec.whatwg.org/#concept-element-interface
> 
> As far as I can tell you should be able to use that hook to define the
> appropriate interface.

Great, I really appreciate that.

Can I have your opinion on the question in https://www.w3.org/Bugs/Public/show_bug.cgi?id=20487#c13?
Comment 18 Anne 2013-02-08 10:57:01 UTC
Throwing seems fine to me. 

Ignoring it's declared as custom element because the namespace is wrong and just creating HTMLUnknownElement also seems fine to me.

It should do the same as what happens for createElementNS() I think with namespace being the HTML namespace.
Comment 19 Dimitri Glazkov 2013-02-08 18:35:28 UTC
(In reply to comment #18)
> Throwing seems fine to me. 
> 
> Ignoring it's declared as custom element because the namespace is wrong and
> just creating HTMLUnknownElement also seems fine to me.

After some thinking, this seems like the most consistent behavior. Conceptually, the model of the element-interface-concept hook is a table:

(namespace, localName) -> interface

if the namespace is wrong, then the result of this table lookup fails, and thus HTMLUnknownElement is returned.

If we add throwing, then we need to add more hooks, and that seems less consistent with how things work now.
Comment 20 Dimitri Glazkov 2013-02-08 23:46:16 UTC
This is now done. Please let me know if I goofed up.

https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#monkeypatch-create-element

There's discussion that will probably trigger more changes in bug 20913.