Closed Bug 1419662 Opened 7 years ago Closed 7 years ago

Autonomous custom element get confused if it contains 'is' attribute

Categories

(Core :: DOM: Core & HTML, enhancement, P2)

enhancement

Tracking

()

RESOLVED FIXED
mozilla59
Tracking Status
firefox59 --- fixed

People

(Reporter: edgar, Assigned: jdai)

References

Details

Attachments

(1 file, 4 obsolete files)

For example, if we have <x-foo is="x-bar"></x-foo>, we will treat this custom element as 'x-bar' type, it seems wrong to me. But I need to look carefully through the spec steps to see if this is an implementation issue. If we do follow the spec, it probably requires filing a spec bug to clarify. Test script: http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=5534.
In Chrome and Safari, it will treat <x-foo is="x-bar"></x-foo>[1] as autonomous custom element, not customized built-in element. [1] http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=5534
(In reply to John Dai[:jdai] from comment #1) > In Chrome and Safari, it will treat <x-foo is="x-bar"></x-foo>[1] as > autonomous custom element, not customized built-in element. > > [1] http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=5534 But Chrome and Safari don't support customized built-in element yet, AFAIK.
(In reply to Edgar Chen [:edgar] from comment #0) > For example, if we have <x-foo is="x-bar"></x-foo>, we will treat this > custom element as 'x-bar' type, it seems wrong to me. But I need to look > carefully through the spec steps to see if this is an implementation issue. > If we do follow the spec, it probably requires filing a spec bug to clarify. > The problem is because we didn't follow look up a custom element definition spec[1]. Per spec, we need to pass localName and |is| value, then it'll check if there is custom element definition in registry with name and local name both equal to localName, return that custom element definition ([1] step 4). However, we put localName and |is| value into one parameter[2], if there is a |is| value, we will pass |is| value as parameter in most of cases[3]. [1] https://html.spec.whatwg.org/multipage/custom-elements.html#look-up-a-custom-element-definition [2] https://searchfox.org/mozilla-central/rev/797c93d81fe446f78babf20894f0729f15f71ee6/dom/base/CustomElementRegistry.cpp#238-249 [3] https://searchfox.org/mozilla-central/rev/797c93d81fe446f78babf20894f0729f15f71ee6/parser/html/nsHtml5TreeOperation.cpp#410-412
Assignee: nobody → jdai
(In reply to John Dai[:jdai] from comment #3) > However, we put localName and |is| value into one parameter[2], if > there is a |is| value, we will pass |is| value as parameter in most of > cases[3]. We do pass another parameter for localname, and LookupCustomElementDefinition() will check the passed parameter with the one stored in CustomElementDefintion. In http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=5534 case, it won't pass the check and returns nullptr (though this is still not expected behavior), right? And I am also curious why prototype of <x-foo> is Bar in this case ...
(In reply to Edgar Chen [:edgar] from comment #4) > (In reply to John Dai[:jdai] from comment #3) > > However, we put localName and |is| value into one parameter[2], if > > there is a |is| value, we will pass |is| value as parameter in most of > > cases[3]. > > We do pass another parameter for localname, and > LookupCustomElementDefinition() will check the passed parameter with the one > stored in CustomElementDefintion. In > http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=5534 case, it > won't pass the check and returns nullptr (though this is still not expected > behavior), right? And I am also curious why prototype of <x-foo> is Bar in > this case ... The prototype of <x-foo> is Bar because when parser run NS_NewHTMLElement if there is no definition, but it's a valid custom element, we'll set CustomElementData[1]. Hence, we will do prototype swizzling at Element::WrapObject[2]. It'll be fixed at bug 1416999. However, we still need to fix LookupCustomElementDefinition return incorrect definition in this bug. [1] https://searchfox.org/mozilla-central/rev/33c90c196bc405e628bc868a4f4ba29b992478c0/dom/html/nsHTMLContentSink.cpp#370-373 [2] https://searchfox.org/mozilla-central/rev/33c90c196bc405e628bc868a4f4ba29b992478c0/dom/base/Element.cpp#521-541
(In reply to John Dai[:jdai] from comment #5) > we'll set CustomElementData[1]. Hence, we will do prototype swizzling at > Element::WrapObject[2]. That means we also set incorrect custom element type in CustomElementData, we should also fix this.
(In reply to Edgar Chen [:edgar] from comment #6) > (In reply to John Dai[:jdai] from comment #5) > > we'll set CustomElementData[1]. Hence, we will do prototype swizzling at > > Element::WrapObject[2]. > > That means we also set incorrect custom element type in CustomElementData, > we should also fix this. Thanks to notice this!
Attached patch patch, v1 (obsolete) — Splinter Review
Attachment #8936800 - Flags: feedback?(echen)
Comment on attachment 8936800 [details] [diff] [review] patch, v1 Review of attachment 8936800 [details] [diff] [review]: ----------------------------------------------------------------- Could you add some comments in https://searchfox.org/mozilla-central/rev/b0098afaeaad24a6752aa418ca3e86eade5fab17/dom/base/nsNodeUtils.cpp#465 to explain why we are good for clone case. ::: dom/base/nsContentUtils.cpp @@ +10121,5 @@ > isCustomElementName = nsContentUtils::IsCustomElementName(name); > } > + > + RefPtr<nsAtom> tagAtom = nodeInfo->NameAtom(); > + RefPtr<nsAtom> typeAtom = (isCustomElementName || !aIs) ? tagAtom : NS_Atomize(*aIs); Hmm, I think we probably could be better here. The typeAtom seems could still be a weird value, for example, the value of the button element without `is` attribute, in this case we set it to 'button', but this element is not a custom elements at all. I think we should set typeAtom to nullptr to prevent someone misuse it in the future. And if it is possible adding some assertions, the will be great. ::: dom/tests/mochitest/webcomponents/test_autonomous_custom_element_contain_is_attribute.html @@ +30,5 @@ > + > +</script> > +<x-foo is="x-bar"></x-foo> > +<script> > +ok(xfoo instanceof XFoo, "Parser create an autonomous custom element which contains is attribute should create as autonomous custom element"); I don't quite understand the test here, 1. The `xfoo` is still first <x-foo> that is removed from container, right? 2. And the first <x-foo> is also created from parser, why we test the parser created case again? Or you meant to test the definition come before/after creation case? And please also add test for document.createElement() and clonNode(). Last thing, could this test be a web platform test? If yes, you could do in this bug or file a follow-up bug to move this test to a web platform test. ::: parser/html/nsHtml5TreeOperation.cpp @@ +408,5 @@ > isCustomElement = (aCreator == NS_NewCustomElement || !isValue.IsEmpty()); > if (isCustomElement && aFromParser != dom::FROM_PARSER_FRAGMENT) { > RefPtr<nsAtom> tagAtom = nodeInfo->NameAtom(); > RefPtr<nsAtom> typeAtom = > + (aCreator == NS_NewCustomElement || isValue.IsEmpty()) ? tagAtom : NS_Atomize(isValue); Ditto.
Attachment #8936800 - Flags: feedback?(echen)
(In reply to Edgar Chen [:edgar] from comment #9) > Comment on attachment 8936800 [details] [diff] [review] > patch, v1 > > Review of attachment 8936800 [details] [diff] [review]: > ----------------------------------------------------------------- > > Could you add some comments in > https://searchfox.org/mozilla-central/rev/ > b0098afaeaad24a6752aa418ca3e86eade5fab17/dom/base/nsNodeUtils.cpp#465 to > explain why we are good for clone case. > Will do. > ::: dom/base/nsContentUtils.cpp > @@ +10121,5 @@ > > isCustomElementName = nsContentUtils::IsCustomElementName(name); > > } > > + > > + RefPtr<nsAtom> tagAtom = nodeInfo->NameAtom(); > > + RefPtr<nsAtom> typeAtom = (isCustomElementName || !aIs) ? tagAtom : NS_Atomize(*aIs); > > Hmm, I think we probably could be better here. The typeAtom seems could > still be a weird value, for example, the value of the button element without > `is` attribute, in this case we set it to 'button', but this element is not > a custom elements at all. I think we should set typeAtom to nullptr to > prevent someone misuse it in the future. And if it is possible adding some > assertions, the will be great. > Will do. > ::: > dom/tests/mochitest/webcomponents/ > test_autonomous_custom_element_contain_is_attribute.html > @@ +30,5 @@ > > + > > +</script> > > +<x-foo is="x-bar"></x-foo> > > +<script> > > +ok(xfoo instanceof XFoo, "Parser create an autonomous custom element which contains is attribute should create as autonomous custom element"); > > I don't quite understand the test here, > 1. The `xfoo` is still first <x-foo> that is removed from container, right? > 2. And the first <x-foo> is also created from parser, why we test the parser > created case again? > Or you meant to test the definition come before/after creation case? > I want to test the definition come before/after creation, I'll revise test message for better understanding. > And please also add test for document.createElement() and clonNode(). > Will do. > Last thing, could this test be a web platform test? If yes, you could do in > this bug or file a follow-up bug to move this test to a web platform test. > Will do. > ::: parser/html/nsHtml5TreeOperation.cpp > @@ +408,5 @@ > > isCustomElement = (aCreator == NS_NewCustomElement || !isValue.IsEmpty()); > > if (isCustomElement && aFromParser != dom::FROM_PARSER_FRAGMENT) { > > RefPtr<nsAtom> tagAtom = nodeInfo->NameAtom(); > > RefPtr<nsAtom> typeAtom = > > + (aCreator == NS_NewCustomElement || isValue.IsEmpty()) ? tagAtom : NS_Atomize(isValue); > > Ditto. Will do.
Attached patch patch, v2 (obsolete) — Splinter Review
Address comment 9.
Attachment #8936800 - Attachment is obsolete: true
Attachment #8939488 - Flags: feedback?(echen)
Comment on attachment 8939488 [details] [diff] [review] patch, v2 Review of attachment 8939488 [details] [diff] [review]: ----------------------------------------------------------------- ::: dom/base/nsNodeUtils.cpp @@ +513,1 @@ > RefPtr<nsAtom> typeAtom = extension.IsEmpty() ? tagAtom : NS_Atomize(extension); I just realized that we still possibly have incorrect CustomElementData setup on the cloned node, var foo = document.createElement("button", { is: "x-foo" }); foo.removeAttribute("is"); var bar = foo.cloneNode(); In above case, we will set CustomElementData with 'button' type to 'bar', but 'bar' is not a custom element because the 'is' attribute on 'foo' have been removed when cloning, and the 'button' is not a correct custom element type, either. Maybe adding some sanity checks in Element::SetCustomElementData() would help to catch the incorrectness of custom element type? ::: parser/html/nsHtml5TreeOperation.cpp @@ +408,5 @@ > isCustomElement = (aCreator == NS_NewCustomElement || !isValue.IsEmpty()); > if (isCustomElement && aFromParser != dom::FROM_PARSER_FRAGMENT) { > RefPtr<nsAtom> tagAtom = nodeInfo->NameAtom(); > + RefPtr<nsAtom> typeAtom; > + if (isCustomElement) { We already check isCustomElement in above if, so maybe just RefPtr<nsAtom> typeAtom = (aCreator == NS_NewCustomElement) ? tagAtom : NS_Atomize(isValue); ::: testing/web-platform/meta/MANIFEST.json @@ +523704,5 @@ > "d1661ab1734f7d1a252030aeac7e9842a7a4cb3b", > "testharness" > ], > "custom-elements/Document-createElement.html": [ > + "06c2041a52cccc068fa2001af8d205088302f562", Node-cloneNode.html also needs an update.
Attachment #8939488 - Flags: feedback?(echen)
(In reply to Edgar Chen [:edgar] from comment #12) > Comment on attachment 8939488 [details] [diff] [review] > patch, v2 > > Review of attachment 8939488 [details] [diff] [review]: > ----------------------------------------------------------------- > > ::: dom/base/nsNodeUtils.cpp > @@ +513,1 @@ > > RefPtr<nsAtom> typeAtom = extension.IsEmpty() ? tagAtom : NS_Atomize(extension); > > I just realized that we still possibly have incorrect CustomElementData > setup on the cloned node, > > var foo = document.createElement("button", { is: "x-foo" }); > foo.removeAttribute("is"); > var bar = foo.cloneNode(); > > In above case, we will set CustomElementData with 'button' type to 'bar', > but 'bar' is not a custom element because the 'is' attribute on 'foo' have > been removed when cloning, and the 'button' is not a correct custom element > type, either. > Thank you for catching this. This is a case we should consider. > Maybe adding some sanity checks in Element::SetCustomElementData() would > help to catch the incorrectness of custom element type? > Will do. > ::: parser/html/nsHtml5TreeOperation.cpp > @@ +408,5 @@ > > isCustomElement = (aCreator == NS_NewCustomElement || !isValue.IsEmpty()); > > if (isCustomElement && aFromParser != dom::FROM_PARSER_FRAGMENT) { > > RefPtr<nsAtom> tagAtom = nodeInfo->NameAtom(); > > + RefPtr<nsAtom> typeAtom; > > + if (isCustomElement) { > > We already check isCustomElement in above if, so maybe just > > RefPtr<nsAtom> typeAtom = (aCreator == NS_NewCustomElement) ? tagAtom : > NS_Atomize(isValue); > Will do. > ::: testing/web-platform/meta/MANIFEST.json > @@ +523704,5 @@ > > "d1661ab1734f7d1a252030aeac7e9842a7a4cb3b", > > "testharness" > > ], > > "custom-elements/Document-createElement.html": [ > > + "06c2041a52cccc068fa2001af8d205088302f562", > > Node-cloneNode.html also needs an update. Will do.
Attached patch patch, v3 (obsolete) — Splinter Review
Address comment 12.
Attachment #8939488 - Attachment is obsolete: true
Attachment #8939748 - Flags: feedback?(echen)
Comment on attachment 8939748 [details] [diff] [review] patch, v3 Review of attachment 8939748 [details] [diff] [review]: ----------------------------------------------------------------- Looks good, thank you. ::: dom/base/nsNodeUtils.cpp @@ +508,5 @@ > + !extension.IsEmpty()) { > + // The typeAtom can be determined by extension, because we only need to > + // consider two cases: 1) Original node is a autonomous custom element > + // which has CustomElementData. 2) Original node has extension which is > + // a built-in custom element or it's not a custom element, but it Maybe: 2) Original node is a built-in custom element or normal element, but it has `is` attribute when it is being cloned.
Attachment #8939748 - Flags: feedback?(echen) → feedback+
Address comment 15. In this bug, we set correct custom element type. If we have a autonomous custom element, but it has is attribute, e.g. <x-foo is="x-bar"></x-foo>. Hence, we will treat this custom element as 'x-foo' type. Test script: http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=5534 Try: https://treeherder.mozilla.org/#/jobs?repo=try&revision=c5ebaef1895f986d90fbe83695d948a33657a5b8&group_state=expanded&filter-tier=1
Attachment #8939748 - Attachment is obsolete: true
Attachment #8940076 - Flags: review?(bugs)
Comment on attachment 8940076 [details] [diff] [review] Bug 1419662 - Fix incorrect custom element type in CustomElementData. The spec seems to be clear on how this all should work. It is hard to follow, but still clear. >+<autonomous-custom-element id="instance2" is="is-custom-element"></my-custom-element> Fix the closing tag to use the same name as opening tag
Attachment #8940076 - Flags: review?(bugs) → review+
Address comment 17, and carrying r+.
Attachment #8940076 - Attachment is obsolete: true
Attachment #8940570 - Flags: review+
Keywords: checkin-needed
Pushed by archaeopteryx@coole-files.de: https://hg.mozilla.org/integration/mozilla-inbound/rev/48bb9add84a8 Fix incorrect custom element type in CustomElementData. f=echen, r=smaug
Keywords: checkin-needed
Status: NEW → RESOLVED
Closed: 7 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla59
Component: DOM → DOM: Core & HTML
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: