Changeset 201739 in webkit
- Timestamp:
- Jun 6, 2016 9:02:11 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 27 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r201736 r201739 1 2016-06-02 Ryosuke Niwa <rniwa@webkit.org> 2 3 Update the list of elements attachShadow is allowed 4 https://bugs.webkit.org/show_bug.cgi?id=157706 5 6 Reviewed by Darin Adler. 7 8 Added more test cases for validating elements on which attachShadow is allowed and disallowed. 9 10 * fast/shadow-dom/Element-interface-attachShadow-expected.txt: 11 * fast/shadow-dom/Element-interface-attachShadow.html: 12 1 13 2016-06-03 Ryosuke Niwa <rniwa@webkit.org> 2 14 -
trunk/LayoutTests/fast/shadow-dom/Element-interface-attachShadow-expected.txt
r189841 r201739 5 5 PASS Element.attachShadow must create an instance of ShadowRoot 6 6 PASS Element.attachShadow must throw a InvalidStateError if the context object already hosts a shadow tree 7 PASS Element.attachShadow must throw a NotSupportedError for button, details, input, marquee, meter, progress, select, textarea, and keygen elements 7 PASS Element.attachShadow must throw a NotSupportedError on HTML elements whose local name is not one of article, aside, blockquote, body, div, footer, h1, h2, h3, h4, h5, h6, header, nav, p, section, span 8 PASS Element.attachShadow must not throw a NotSupportedError on article, aside, blockquote, body, div, footer, h1, h2, h3, h4, h5, h6, header, nav, p, section, span 9 PASS Element.attachShadow must throw a NotSupportedError on a HTMLKnownElement which does not have a valid custom element 10 PASS Element.attachShadow must throw a NotSupportedError on a HTMLKnownElement which has a valid custom element 8 11 -
trunk/LayoutTests/fast/shadow-dom/Element-interface-attachShadow.html
r189841 r201739 79 79 }, 'Element.attachShadow must throw a InvalidStateError if the context object already hosts a shadow tree'); 80 80 81 var htmlElementNames = ['a', 'abbr', 'acronym', 'address', 'applet', 'area', 'article', 'aside', 'audio', 'b', 'base', 'basefont', 'bdi', 82 'bdo', 'bgsound', 'big', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 83 'command', 'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dir', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 84 'figure', 'font', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 85 'html', 'i', 'iframe', 'image', 'img', 'input', 'ins', 'isindex', 'kbd', 'keygen', 'label', 'layer', 'legend', 'li', 'link', 'listing', 86 'main', 'map', 'mark', 'marquee', 'menu', 'meta', 'meter', 'nav', 'nobr', 'noembed', 'noframes', 'nolayer', 'object', 'ol', 'optgroup', 87 'option', 'output', 'p', 'param', 'picture', 'plaintext', 'pre', 'progress', 'q', 'rb', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'script', 88 'section', 'select', 'slot', 'small', 'source', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 89 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr', 'xmp', 'noscript']; 90 var allowingAttachShadow = ["article", "aside", "blockquote", "body", "div", "footer", "h1", "h2", "h3", "h4", "h5", "h6", "header", "nav", "p", "section", "span"]; 91 81 92 test(function () { 82 for (var elementName of ['button', 'details', 'input', 'marquee', 'meter', 'progress', 'select', 'textarea', 'keygen']) { 93 for (var elementName of htmlElementNames) { 94 if (allowingAttachShadow.indexOf(elementName) >= 0) 95 continue; 96 83 97 assert_throws({'name': 'NotSupportedError'}, function () { 84 98 document.createElement(elementName).attachShadow({mode: "open"}); … … 89 103 }, 'Calling attachShadow({mode: "closed"}) on ' + elementName + ' element must throw'); 90 104 } 91 }, 'Element.attachShadow must throw a NotSupportedError for button, details, input, marquee, meter, progress, select, textarea, and keygen elements'); 105 }, 'Element.attachShadow must throw a NotSupportedError on HTML elements whose local name is not one of ' + allowingAttachShadow.join(', ')); 106 107 test(function () { 108 for (var elementName of allowingAttachShadow) { 109 assert_true(document.createElement(elementName).attachShadow({mode: "open"}) instanceof ShadowRoot, 110 'Calling attachShadow({mode: "open"}) on ' + elementName + ' element must not throw'); 111 112 assert_true(document.createElement(elementName).attachShadow({mode: "closed"}) instanceof ShadowRoot, 113 'Calling attachShadow({mode: "closed"}) on ' + elementName + ' element must not throw'); 114 } 115 }, 'Element.attachShadow must not throw a NotSupportedError on ' + allowingAttachShadow.join(', ')); 116 117 test(function () { 118 assert_throws({'name': 'NotSupportedError'}, function () { 119 document.createElement('w3cfutureelement').attachShadow({mode: "open"}); 120 }, 'Calling attachShadow({mode: "open"}) on a HTML element whose local name is "w3cfutureelement" must throw'); 121 122 assert_throws({'name': 'NotSupportedError'}, function () { 123 document.createElement('w3cfutureelement').attachShadow({mode: "closed"}); 124 }, 'Calling attachShadow({mode: "closed"}) on a HTML element whose local name is "w3cfutureelement" must throw'); 125 126 }, 'Element.attachShadow must throw a NotSupportedError on a HTMLKnownElement which does not have a valid custom element'); 127 128 test(function () { 129 assert_true(document.createElement('custom-element').attachShadow({mode: "open"}) instanceof ShadowRoot, 130 'Calling attachShadow({mode: "open"}) on a HTML element whose local name is "custom-element" element must not throw'); 131 132 assert_true(document.createElement('custom-element').attachShadow({mode: "closed"}) instanceof ShadowRoot, 133 'Calling attachShadow({mode: "closed"}) on a HTML element whose local name is "custom-element" must not throw'); 134 135 }, 'Element.attachShadow must throw a NotSupportedError on a HTMLKnownElement which has a valid custom element'); 92 136 93 137 </script> -
trunk/Source/WebCore/ChangeLog
r201736 r201739 1 2016-06-02 Ryosuke Niwa <rniwa@webkit.org> 2 3 Update the list of elements attachShadow is allowed 4 https://bugs.webkit.org/show_bug.cgi?id=157706 5 6 Reviewed by Darin Adler. 7 8 Update the list of elements on which attachShadow is allowed per the latest shadow DOM spec: 9 http://www.w3.org/TR/shadow-dom/#widl-Element-attachShadow-ShadowRoot-ShadowRootInit-shadowRootInitDict 10 which now only allows attachShadow on the following elements and custom elements: 11 button, details, input, marquee, meter, progress, select, textarea, keygen 12 13 In order to check that a given HTML element's local name is a valid custom element name, 14 this patch moves CustomElementDefinitions::checkName to Document::validateCustomElementName so that 15 it could be used when either SHADOW_DOM or CUSTOM_ELEMENTS build flag is turned on. 16 17 Also removed Element::canHaveUserAgentShadowRoot since it was only used in Element::attachShadow. 18 19 Test: fast/shadow-dom/Element-interface-attachShadow.html 20 21 * bindings/js/JSDocumentCustom.cpp: 22 (WebCore::JSDocument::defineElement): 23 * dom/CustomElementDefinitions.cpp: 24 (WebCore::CustomElementDefinitions::checkName): Moved to Document::validateCustomElementName. 25 * dom/CustomElementDefinitions.h: 26 * dom/Document.cpp: 27 (WebCore::createHTMLElementWithNameValidation): 28 (WebCore::createFallbackHTMLElement): 29 (WebCore::Document::validateCustomElementName): Moved from CustomElementDefinitions::checkName. 30 * dom/Document.h: 31 * dom/Element.cpp: 32 (WebCore::canAttachAuthorShadowRoot): Added. 33 (WebCore::Element::attachShadow): 34 * dom/Element.h: 35 * html/HTMLButtonElement.h: 36 * html/HTMLDetailsElement.h: 37 * html/HTMLInputElement.h: 38 * html/HTMLKeygenElement.h: 39 * html/HTMLMarqueeElement.h: 40 * html/HTMLMediaElement.h: 41 * html/HTMLMeterElement.h: 42 * html/HTMLPlugInElement.h: 43 * html/HTMLProgressElement.h: 44 * html/HTMLQuoteElement.h: 45 * html/HTMLSelectElement.h: 46 * html/HTMLSummaryElement.h: 47 * html/HTMLTagNames.in: 48 * html/HTMLTextAreaElement.h: 49 * html/HTMLUnknownElement.h: 50 * html/parser/HTMLConstructionSite.cpp: 51 (WebCore::HTMLConstructionSite::createHTMLElementOrFindCustomElementInterface): 52 1 53 2016-06-03 Ryosuke Niwa <rniwa@webkit.org> 2 54 -
trunk/Source/WebCore/bindings/js/JSDocumentCustom.cpp
r201561 r201739 159 159 } 160 160 161 switch ( CustomElementDefinitions::checkName(tagName)) {162 case CustomElement Definitions::NameStatus::Valid:161 switch (Document::validateCustomElementName(tagName)) { 162 case CustomElementNameValidationStatus::Valid: 163 163 break; 164 case CustomElement Definitions::NameStatus::ConflictsWithBuiltinNames:164 case CustomElementNameValidationStatus::ConflictsWithBuiltinNames: 165 165 return throwSyntaxError(&state, "Custom element name cannot be same as one of the builtin elements"); 166 case CustomElement Definitions::NameStatus::NoHyphen:166 case CustomElementNameValidationStatus::NoHyphen: 167 167 return throwSyntaxError(&state, "Custom element name must contain a hyphen"); 168 case CustomElement Definitions::NameStatus::ContainsUpperCase:168 case CustomElementNameValidationStatus::ContainsUpperCase: 169 169 return throwSyntaxError(&state, "Custom element name cannot contain an upper case letter"); 170 170 } -
trunk/Source/WebCore/dom/CustomElementDefinitions.cpp
r197917 r201739 39 39 40 40 namespace WebCore { 41 42 CustomElementDefinitions::NameStatus CustomElementDefinitions::checkName(const AtomicString& tagName)43 {44 bool containsHyphen = false;45 for (unsigned i = 0; i < tagName.length(); i++) {46 if (isASCIIUpper(tagName[i]))47 return NameStatus::ContainsUpperCase;48 if (tagName[i] == '-')49 containsHyphen = true;50 }51 52 if (!containsHyphen)53 return NameStatus::NoHyphen;54 55 // FIXME: We should be taking the advantage of QualifiedNames in SVG and MathML.56 if (tagName == SVGNames::color_profileTag.localName()57 || tagName == SVGNames::font_faceTag.localName()58 || tagName == SVGNames::font_face_formatTag.localName()59 || tagName == SVGNames::font_face_nameTag.localName()60 || tagName == SVGNames::font_face_srcTag.localName()61 || tagName == SVGNames::font_face_uriTag.localName()62 || tagName == SVGNames::missing_glyphTag.localName()63 #if ENABLE(MATHML)64 || tagName == MathMLNames::annotation_xmlTag.localName()65 #endif66 )67 return NameStatus::ConflictsWithBuiltinNames;68 69 return NameStatus::Valid;70 }71 41 72 42 void CustomElementDefinitions::addElementDefinition(Ref<JSCustomElementInterface>&& interface) -
trunk/Source/WebCore/dom/CustomElementDefinitions.h
r197917 r201739 57 57 bool containsConstructor(const JSC::JSObject*) const; 58 58 59 enum class NameStatus { Valid, ConflictsWithBuiltinNames, NoHyphen, ContainsUpperCase };60 static NameStatus checkName(const AtomicString& tagName);61 62 59 private: 63 60 HashMap<AtomicString, Vector<RefPtr<Element>>> m_upgradeCandidatesMap; -
trunk/Source/WebCore/dom/Document.cpp
r201679 r201739 890 890 891 891 #if ENABLE(CUSTOM_ELEMENTS) 892 if ( CustomElementDefinitions::checkName(localName) == CustomElementDefinitions::NameStatus::Valid) {892 if (Document::validateCustomElementName(localName) == CustomElementNameValidationStatus::Valid) { 893 893 Ref<HTMLElement> element = HTMLElement::create(qualifiedName, document); 894 894 element->setIsUnresolvedCustomElement(); … … 1075 1075 } 1076 1076 // FIXME: Should we also check the equality of prefix between the custom element and name? 1077 if ( CustomElementDefinitions::checkName(name.localName()) == CustomElementDefinitions::NameStatus::Valid) {1077 if (Document::validateCustomElementName(name.localName()) == CustomElementNameValidationStatus::Valid) { 1078 1078 Ref<HTMLElement> element = HTMLElement::create(name, document); 1079 1079 element->setIsUnresolvedCustomElement(); … … 1112 1112 return element.releaseNonNull(); 1113 1113 } 1114 1115 #if ENABLE(CUSTOM_ELEMENTS) || ENABLE(SHADOW_DOM) 1116 CustomElementNameValidationStatus Document::validateCustomElementName(const AtomicString& localName) 1117 { 1118 bool containsHyphen = false; 1119 for (auto character : StringView(localName).codeUnits()) { 1120 if (isASCIIUpper(character)) 1121 return CustomElementNameValidationStatus::ContainsUpperCase; 1122 if (character == '-') 1123 containsHyphen = true; 1124 } 1125 1126 if (!containsHyphen) 1127 return CustomElementNameValidationStatus::NoHyphen; 1128 1129 #if ENABLE(MATHML) 1130 const auto& annotationXmlLocalName = MathMLNames::annotation_xmlTag.localName(); 1131 #else 1132 static NeverDestroyed<const AtomicString> annotationXmlLocalName(ASCIILiteral("annotation-xml")); 1133 #endif 1134 1135 if (localName == SVGNames::color_profileTag.localName() 1136 || localName == SVGNames::font_faceTag.localName() 1137 || localName == SVGNames::font_face_formatTag.localName() 1138 || localName == SVGNames::font_face_nameTag.localName() 1139 || localName == SVGNames::font_face_srcTag.localName() 1140 || localName == SVGNames::font_face_uriTag.localName() 1141 || localName == SVGNames::missing_glyphTag.localName() 1142 || localName == annotationXmlLocalName) 1143 return CustomElementNameValidationStatus::ConflictsWithBuiltinNames; 1144 1145 return CustomElementNameValidationStatus::Valid; 1146 } 1147 #endif 1114 1148 1115 1149 #if ENABLE(CSS_GRID_LAYOUT) -
trunk/Source/WebCore/dom/Document.h
r201534 r201739 282 282 }; 283 283 284 enum class CustomElementNameValidationStatus { Valid, ConflictsWithBuiltinNames, NoHyphen, ContainsUpperCase }; 285 284 286 class Document 285 287 : public ContainerNode … … 387 389 WEBCORE_EXPORT RefPtr<Element> createElementNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode&); 388 390 WEBCORE_EXPORT Ref<Element> createElement(const QualifiedName&, bool createdByParser); 391 392 #if ENABLE(CUSTOM_ELEMENTS) || ENABLE(SHADOW_DOM) 393 static CustomElementNameValidationStatus validateCustomElementName(const AtomicString&); 394 #endif 389 395 390 396 #if ENABLE(CSS_GRID_LAYOUT) -
trunk/Source/WebCore/dom/Element.cpp
r201588 r201739 1686 1686 } 1687 1687 1688 bool Element::canHaveUserAgentShadowRoot() const 1689 { 1690 return false; 1688 #if ENABLE(SHADOW_DOM) 1689 static bool canAttachAuthorShadowRoot(const Element& element) 1690 { 1691 static NeverDestroyed<HashSet<AtomicString>> tagNames = [] { 1692 const AtomicString tagList[] = { 1693 articleTag.localName(), 1694 asideTag.localName(), 1695 blockquoteTag.localName(), 1696 bodyTag.localName(), 1697 divTag.localName(), 1698 footerTag.localName(), 1699 h1Tag.localName(), 1700 h2Tag.localName(), 1701 h3Tag.localName(), 1702 h4Tag.localName(), 1703 h5Tag.localName(), 1704 h6Tag.localName(), 1705 headerTag.localName(), 1706 navTag.localName(), 1707 pTag.localName(), 1708 sectionTag.localName(), 1709 spanTag.localName() 1710 }; 1711 1712 HashSet<AtomicString> set; 1713 for (auto& name : tagList) 1714 set.add(name); 1715 return set; 1716 }(); 1717 1718 if (!is<HTMLElement>(element)) 1719 return false; 1720 1721 const auto& localName = element.localName(); 1722 return tagNames.get().contains(localName) || Document::validateCustomElementName(localName) == CustomElementNameValidationStatus::Valid; 1691 1723 } 1692 1724 1693 1725 RefPtr<ShadowRoot> Element::attachShadow(const ShadowRootInit& init, ExceptionCode& ec) 1694 1726 { 1695 if ( canHaveUserAgentShadowRoot()) {1727 if (!canAttachAuthorShadowRoot(*this)) { 1696 1728 ec = NOT_SUPPORTED_ERR; 1697 1729 return nullptr; … … 1720 1752 return root; 1721 1753 } 1754 #endif 1722 1755 1723 1756 ShadowRoot* Element::userAgentShadowRoot() const -
trunk/Source/WebCore/dom/Element.h
r200626 r201739 255 255 }; 256 256 257 #if ENABLE(SHADOW_DOM) 257 258 ShadowRoot* shadowRootForBindings(JSC::ExecState&) const; 258 259 RefPtr<ShadowRoot> attachShadow(const ShadowRootInit&, ExceptionCode&); 260 #endif 259 261 260 262 ShadowRoot* userAgentShadowRoot() const; … … 595 597 virtual Ref<Element> cloneElementWithoutAttributesAndChildren(Document&); 596 598 597 virtual bool canHaveUserAgentShadowRoot() const;598 599 void removeShadowRoot(); 599 600 -
trunk/Source/WebCore/html/HTMLButtonElement.h
r201588 r201739 53 53 // HTMLFormControlElement always creates one, but buttons don't need it. 54 54 bool alwaysCreateUserAgentShadowRoot() const override { return false; } 55 bool canHaveUserAgentShadowRoot() const final { return true; }56 55 57 56 void parseAttribute(const QualifiedName&, const AtomicString&) override; -
trunk/Source/WebCore/html/HTMLDetailsElement.h
r200964 r201739 43 43 44 44 void didAddUserAgentShadowRoot(ShadowRoot*) override; 45 bool canHaveUserAgentShadowRoot() const final { return true; }46 45 bool hasCustomFocusLogic() const final { return true; } 47 46 -
trunk/Source/WebCore/html/HTMLInputElement.h
r201659 r201739 334 334 335 335 void didAddUserAgentShadowRoot(ShadowRoot*) final; 336 bool canHaveUserAgentShadowRoot() const final { return true; }337 336 338 337 void willChangeForm() final; -
trunk/Source/WebCore/html/HTMLKeygenElement.h
r197864 r201739 56 56 bool shouldSaveAndRestoreFormControlState() const override; 57 57 58 bool canHaveUserAgentShadowRoot() const final { return true; }59 60 58 bool isKeytypeRSA() const; 61 59 -
trunk/Source/WebCore/html/HTMLMarqueeElement.h
r197566 r201739 63 63 const char* activeDOMObjectName() const override { return "HTMLMarqueeElement"; } 64 64 65 bool canHaveUserAgentShadowRoot() const final { return true; }66 67 65 RenderMarquee* renderMarquee() const; 68 66 }; -
trunk/Source/WebCore/html/HTMLMediaElement.h
r201735 r201739 505 505 bool alwaysCreateUserAgentShadowRoot() const override { return true; } 506 506 507 // FIXME: Shadow DOM spec says we should be able to create shadow root on audio and video elements508 bool canHaveUserAgentShadowRoot() const final { return true; }509 510 507 bool supportsFocus() const override; 511 508 bool isMouseFocusable() const override; -
trunk/Source/WebCore/html/HTMLMeterElement.h
r200041 r201739 77 77 void didElementStateChange(); 78 78 void didAddUserAgentShadowRoot(ShadowRoot*) override; 79 bool canHaveUserAgentShadowRoot() const final { return true; }80 79 81 80 RefPtr<MeterValueElement> m_value; -
trunk/Source/WebCore/html/HTMLPlugInElement.h
r200041 r201739 118 118 bool dispatchBeforeLoadEvent(const String& sourceURL); // Not implemented, generates a compile error if subclasses call this by mistake. 119 119 120 // FIXME: Shadow DOM spec says we should be able to create shadow root on applet, embed, and object.121 bool canHaveUserAgentShadowRoot() const final { return true; }122 123 120 // This will load the plugin if necessary. 124 121 virtual RenderWidget* renderWidgetLoadingPlugin() const = 0; -
trunk/Source/WebCore/html/HTMLProgressElement.h
r200041 r201739 63 63 void didElementStateChange(); 64 64 void didAddUserAgentShadowRoot(ShadowRoot*) override; 65 bool canHaveUserAgentShadowRoot() const final { return true; }66 65 bool isDeterminate() const; 67 66 -
trunk/Source/WebCore/html/HTMLQuoteElement.h
r197563 r201739 36 36 private: 37 37 HTMLQuoteElement(const QualifiedName&, Document&); 38 38 39 39 bool isURLAttribute(const Attribute&) const override; 40 40 }; -
trunk/Source/WebCore/html/HTMLSelectElement.h
r200041 r201739 119 119 120 120 bool canStartSelection() const final { return false; } 121 122 bool canHaveUserAgentShadowRoot() const final { return true; }123 121 124 122 bool isEnumeratable() const final { return true; } -
trunk/Source/WebCore/html/HTMLSummaryElement.h
r200964 r201739 43 43 void didAddUserAgentShadowRoot(ShadowRoot*) override; 44 44 45 // FIXME: Shadow DOM spec says we should be able to create shadow root on this element46 bool canHaveUserAgentShadowRoot() const final { return true; }47 45 bool hasCustomFocusLogic() const final { return true; } 48 46 -
trunk/Source/WebCore/html/HTMLTagNames.in
r200075 r201739 34 34 colgroup interfaceName=HTMLTableColElement 35 35 command interfaceName=HTMLElement 36 webkitShadowContent interfaceName=HTMLElement, noConstructor37 36 data 38 37 datalist interfaceName=HTMLDataListElement, conditional=DATALIST_ELEMENT -
trunk/Source/WebCore/html/HTMLTextAreaElement.h
r201588 r201739 72 72 73 73 void didAddUserAgentShadowRoot(ShadowRoot*) override; 74 bool canHaveUserAgentShadowRoot() const final { return true; }75 74 76 75 void maxLengthAttributeChanged(const AtomicString& newValue); -
trunk/Source/WebCore/html/HTMLUnknownElement.h
r197566 r201739 48 48 } 49 49 50 #if ENABLE(METER_ELEMENT)51 bool canHaveUserAgentShadowRoot() const final { return false; }52 #else53 bool canHaveUserAgentShadowRoot() const final { return localName() == "meter"; }54 #endif55 56 50 bool isHTMLUnknownElement() const override { return true; } 57 51 }; -
trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp
r200934 r201739 674 674 QualifiedName qualifiedName(nullAtom, localName, xhtmlNamespaceURI); 675 675 #if ENABLE(CUSTOM_ELEMENTS) 676 if ( CustomElementDefinitions::checkName(localName) == CustomElementDefinitions::NameStatus::Valid) {676 if (Document::validateCustomElementName(localName) == CustomElementNameValidationStatus::Valid) { 677 677 element = HTMLElement::create(qualifiedName, ownerDocument); 678 678 element->setIsUnresolvedCustomElement();
Note: See TracChangeset
for help on using the changeset viewer.