Changeset 208302 in webkit
- Timestamp:
- Nov 2, 2016 2:34:58 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 5 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r208300 r208302 1 2016-11-02 Ryosuke Niwa <rniwa@webkit.org> 2 3 Load stylesheets in link elements inside a connected shadow tree 4 https://bugs.webkit.org/show_bug.cgi?id=160683 5 <rdar://problem/29040652> 6 7 Reviewed by Antti Koivisto. 8 9 Added W3C style testharness.js tests for loading stylesheets via a link element inside a ahadow tree. 10 11 * fast/shadow-dom/link-element-in-shadow-tree-expected.txt: Added. 12 * fast/shadow-dom/link-element-in-shadow-tree.html: Added. 13 * fast/shadow-dom/resources/green-host.css: Added. 14 * fast/shadow-dom/selected-stylesheet-in-shadow-tree-expected.txt: Added. 15 * fast/shadow-dom/selected-stylesheet-in-shadow-tree.html: Added. 16 1 17 2016-11-02 Alex Christensen <achristensen@webkit.org> 2 18 -
trunk/Source/WebCore/ChangeLog
r208301 r208302 1 2016-11-02 Ryosuke Niwa <rniwa@webkit.org> 2 3 Load stylesheets in link elements inside a connected shadow tree 4 https://bugs.webkit.org/show_bug.cgi?id=160683 5 <rdar://problem/29040652> 6 7 Reviewed by Antti Koivisto. 8 9 Allow external stylesheets within a shadow tree by storing the appropriate style scope in HTMLLinkElement 10 when it's connected to a document instead of always talking to document's style scope. 11 12 Also improve ShadowRoot's insertedInto and removedFrom so that they only try to add and remove itself from 13 m_inDocumentShadowRoots when the connected-ness changes. 14 15 This patch also removes the superfluous call to notifyChildNodeRemoved in Element::removeShadowRoot to 16 avoid invoking notifyChildNodeRemoved during a document teardown, which is incorrect. It's sufficient that 17 ~ShadowRoot calls ContainerNode::removeDetachedChildren(), and in turn removeDetachedChildrenInContainer() 18 since the latter function tears down nodes via the deletion queue during a document destruction and use 19 notifyChildNodeRemoved() on nodes that outlive the shadow root. 20 21 Tests: fast/shadow-dom/link-element-in-shadow-tree.html 22 fast/shadow-dom/selected-stylesheet-in-shadow-tree.html 23 24 * dom/Document.cpp: 25 (WebCore::Document::didInsertInDocumentShadowRoot): Assert that the shadow root is not in the set. 26 (WebCore::Document::didRemoveInDocumentShadowRoot): Assert that the shadow root is not in the document as 27 this function is now called after Node::removedFrom in ShadowRoot::removedFrom. 28 * dom/Element.cpp: 29 (WebCore::Element::removeShadowRoot): See the description above. 30 * dom/ShadowRoot.cpp: 31 (WebCore::ShadowRoot::insertedInto): Only call didInsertInDocumentShadowRoot when the this shadow root is 32 newly connected to a document so we can add assertions in didInsertInDocumentShadowRoot. 33 (WebCore::ShadowRoot::removedFrom): Ditto for the removal. 34 * html/HTMLLinkElement.cpp: 35 (WebCore::HTMLLinkElement::HTMLLinkElement): 36 (WebCore::HTMLLinkElement::~HTMLLinkElement): 37 (WebCore::HTMLLinkElement::setDisabledState): Exit early when the element is not in a document as invoking 38 didChangeActiveStyleSheetCandidates would require having a valid m_styleScope and process() already exits 39 early when inDocument() is false. 40 (WebCore::HTMLLinkElement::parseAttribute): 41 (WebCore::HTMLLinkElement::process): Removed the early exit for when the element is in a shadow tree. 42 (WebCore::HTMLLinkElement::insertedInto): Exit early unless this element has just become connected to 43 a document instead of whenever its self-inclusive ancestor is inserted into a container. 44 (WebCore::HTMLLinkElement::removedFrom): Ditto for removal. Also call removeStyleSheetCandidateNode after 45 calling removePendingSheet since the latter depends on m_styleScope being not null. 46 (WebCore::HTMLLinkElement::addPendingSheet): 47 (WebCore::HTMLLinkElement::removePendingSheet): 48 * html/HTMLLinkElement.h: 49 * html/HTMLStyleElement.cpp: 50 (WebCore::HTMLStyleElement::insertedInto): Only call inline style owner's insertedIntoDocument if this 51 element has just become connected to a document. 52 (WebCore::HTMLStyleElement::removedFrom): Ditto for the removal. 53 * style/StyleScope.h: 54 * svg/SVGStyleElement.cpp: 55 (WebCore::SVGStyleElement::insertedInto): Ditto. 56 (WebCore::SVGStyleElement::removedFrom): Ditto for the removal. 57 1 58 2016-11-02 Dave Hyatt <hyatt@apple.com> 2 59 -
trunk/Source/WebCore/dom/Document.cpp
r208256 r208302 6981 6981 { 6982 6982 ASSERT(shadowRoot.inDocument()); 6983 ASSERT(!m_inDocumentShadowRoots.contains(&shadowRoot)); 6983 6984 m_inDocumentShadowRoots.add(&shadowRoot); 6984 6985 } … … 6986 6987 void Document::didRemoveInDocumentShadowRoot(ShadowRoot& shadowRoot) 6987 6988 { 6989 ASSERT(!shadowRoot.inDocument()); 6988 6990 ASSERT(m_inDocumentShadowRoots.contains(&shadowRoot)); 6989 6991 m_inDocumentShadowRoots.remove(&shadowRoot); -
trunk/Source/WebCore/dom/Element.cpp
r208256 r208302 1785 1785 oldRoot->setHost(nullptr); 1786 1786 oldRoot->setParentTreeScope(&document()); 1787 1788 notifyChildNodeRemoved(*this, *oldRoot);1789 1787 } 1790 1788 -
trunk/Source/WebCore/dom/ShadowRoot.cpp
r208118 r208302 85 85 Node::InsertionNotificationRequest ShadowRoot::insertedInto(ContainerNode& insertionPoint) 86 86 { 87 auto result = DocumentFragment::insertedInto(insertionPoint); 88 if (inDocument()) 87 bool wasInDocument = inDocument(); 88 DocumentFragment::insertedInto(insertionPoint); 89 if (insertionPoint.inDocument() && !wasInDocument) 89 90 document().didInsertInDocumentShadowRoot(*this); 90 return result;91 return InsertionDone; 91 92 } 92 93 93 94 void ShadowRoot::removedFrom(ContainerNode& insertionPoint) 94 95 { 95 if (inDocument()) 96 DocumentFragment::removedFrom(insertionPoint); 97 if (insertionPoint.inDocument() && !inDocument()) 96 98 document().didRemoveInDocumentShadowRoot(*this); 97 DocumentFragment::removedFrom(insertionPoint);98 99 } 99 100 -
trunk/Source/WebCore/html/HTMLLinkElement.cpp
r207669 r208302 81 81 , m_loading(false) 82 82 , m_createdByParser(createdByParser) 83 , m_isInShadowTree(false)84 83 , m_firedLoad(false) 85 84 , m_loadedResource(false) … … 102 101 m_cachedSheet->removeClient(*this); 103 102 104 if ( inDocument())105 document().styleScope().removeStyleSheetCandidateNode(*this);103 if (m_styleScope) 104 m_styleScope->removeStyleSheetCandidateNode(*this); 106 105 107 106 linkLoadEventSender().cancelEvent(*this); … … 113 112 DisabledState oldDisabledState = m_disabledState; 114 113 m_disabledState = disabled ? Disabled : EnabledViaScript; 115 if (oldDisabledState != m_disabledState) { 116 // If we change the disabled state while the sheet is still loading, then we have to 117 // perform three checks: 118 if (styleSheetIsLoading()) { 119 // Check #1: The sheet becomes disabled while loading. 120 if (m_disabledState == Disabled) 121 removePendingSheet(); 122 123 // Check #2: An alternate sheet becomes enabled while it is still loading. 124 if (m_relAttribute.isAlternate && m_disabledState == EnabledViaScript) 125 addPendingSheet(ActiveSheet); 126 127 // Check #3: A main sheet becomes enabled while it was still loading and 128 // after it was disabled via script. It takes really terrible code to make this 129 // happen (a double toggle for no reason essentially). This happens on 130 // virtualplastic.net, which manages to do about 12 enable/disables on only 3 131 // sheets. :) 132 if (!m_relAttribute.isAlternate && m_disabledState == EnabledViaScript && oldDisabledState == Disabled) 133 addPendingSheet(ActiveSheet); 134 135 // If the sheet is already loading just bail. 136 return; 137 } 138 139 // Load the sheet, since it's never been loaded before. 140 if (!m_sheet && m_disabledState == EnabledViaScript) 141 process(); 142 else 143 document().styleScope().didChangeActiveStyleSheetCandidates(); 114 if (oldDisabledState == m_disabledState) 115 return; 116 117 ASSERT(inDocument() || !styleSheetIsLoading()); 118 if (!inDocument()) 119 return; 120 121 // If we change the disabled state while the sheet is still loading, then we have to 122 // perform three checks: 123 if (styleSheetIsLoading()) { 124 // Check #1: The sheet becomes disabled while loading. 125 if (m_disabledState == Disabled) 126 removePendingSheet(); 127 128 // Check #2: An alternate sheet becomes enabled while it is still loading. 129 if (m_relAttribute.isAlternate && m_disabledState == EnabledViaScript) 130 addPendingSheet(ActiveSheet); 131 132 // Check #3: A main sheet becomes enabled while it was still loading and 133 // after it was disabled via script. It takes really terrible code to make this 134 // happen (a double toggle for no reason essentially). This happens on 135 // virtualplastic.net, which manages to do about 12 enable/disables on only 3 136 // sheets. :) 137 if (!m_relAttribute.isAlternate && m_disabledState == EnabledViaScript && oldDisabledState == Disabled) 138 addPendingSheet(ActiveSheet); 139 140 // If the sheet is already loading just bail. 141 return; 142 } 143 144 // Load the sheet, since it's never been loaded before. 145 if (!m_sheet && m_disabledState == EnabledViaScript) 146 process(); 147 else { 148 ASSERT(m_styleScope); 149 m_styleScope->didChangeActiveStyleSheetCandidates(); 144 150 } 145 151 } … … 177 183 process(); 178 184 if (m_sheet && !isDisabled()) 179 document().styleScope().didChangeActiveStyleSheetCandidates();185 m_styleScope->didChangeActiveStyleSheetCandidates(); 180 186 return; 181 187 } … … 215 221 void HTMLLinkElement::process() 216 222 { 217 if (!inDocument() || m_isInShadowTree) {223 if (!inDocument()) { 218 224 ASSERT(!m_sheet); 219 225 return; … … 284 290 // we no longer contain a stylesheet, e.g. perhaps rel or type was changed 285 291 clearSheet(); 286 document().styleScope().didChangeActiveStyleSheetCandidates();292 m_styleScope->didChangeActiveStyleSheetCandidates(); 287 293 } 288 294 } … … 298 304 Node::InsertionNotificationRequest HTMLLinkElement::insertedInto(ContainerNode& insertionPoint) 299 305 { 306 bool wasInDocument = inDocument(); 300 307 HTMLElement::insertedInto(insertionPoint); 301 if (!insertionPoint.inDocument() )308 if (!insertionPoint.inDocument() || wasInDocument) 302 309 return InsertionDone; 303 310 304 m_isInShadowTree = isInShadowTree(); 305 if (m_isInShadowTree) 306 return InsertionDone; 307 308 document().styleScope().addStyleSheetCandidateNode(*this, m_createdByParser); 311 m_styleScope = &Style::Scope::forNode(*this); 312 m_styleScope->addStyleSheetCandidateNode(*this, m_createdByParser); 309 313 310 314 process(); … … 315 319 { 316 320 HTMLElement::removedFrom(insertionPoint); 317 if (!insertionPoint.inDocument()) 318 return; 319 320 if (m_isInShadowTree) { 321 ASSERT(!m_sheet); 322 return; 323 } 324 document().styleScope().removeStyleSheetCandidateNode(*this); 321 if (!insertionPoint.inDocument() || inDocument()) 322 return; 325 323 326 324 if (m_sheet) … … 329 327 if (styleSheetIsLoading()) 330 328 removePendingSheet(RemovePendingSheetNotifyLater); 329 330 if (m_styleScope) { 331 m_styleScope->removeStyleSheetCandidateNode(*this); 332 m_styleScope = nullptr; 333 } 334 331 335 } 332 336 … … 545 549 if (m_pendingSheetType == InactiveSheet) 546 550 return; 547 document().styleScope().addPendingSheet(); 551 ASSERT(m_styleScope); 552 m_styleScope->addPendingSheet(); 548 553 } 549 554 … … 556 561 return; 557 562 563 ASSERT(m_styleScope); 558 564 if (type == InactiveSheet) { 559 565 // Document just needs to know about the sheet for exposure through document.styleSheets 560 document().styleScope().didChangeActiveStyleSheetCandidates();561 return; 562 } 563 564 document().styleScope().removePendingSheet(566 m_styleScope->didChangeActiveStyleSheetCandidates(); 567 return; 568 } 569 570 m_styleScope->removePendingSheet( 565 571 notification == RemovePendingSheetNotifyImmediately 566 572 ? Style::Scope::RemovePendingSheetNotifyImmediately -
trunk/Source/WebCore/html/HTMLLinkElement.h
r205455 r208302 120 120 121 121 LinkLoader m_linkLoader; 122 Style::Scope* m_styleScope { nullptr }; 122 123 CachedResourceHandle<CachedCSSStyleSheet> m_cachedSheet; 123 124 RefPtr<CSSStyleSheet> m_sheet; … … 135 136 bool m_loading; 136 137 bool m_createdByParser; 137 bool m_isInShadowTree;138 138 bool m_firedLoad; 139 139 bool m_loadedResource; -
trunk/Source/WebCore/html/HTMLStyleElement.cpp
r207669 r208302 95 95 Node::InsertionNotificationRequest HTMLStyleElement::insertedInto(ContainerNode& insertionPoint) 96 96 { 97 HTMLElement::insertedInto(insertionPoint); 98 if (insertionPoint.inDocument()) 97 bool wasInDocument = inDocument(); 98 auto result = HTMLElement::insertedInto(insertionPoint); 99 if (insertionPoint.inDocument() && !wasInDocument) 99 100 m_styleSheetOwner.insertedIntoDocument(*this); 100 101 return InsertionDone; 101 return result; 102 102 } 103 103 … … 105 105 { 106 106 HTMLElement::removedFrom(insertionPoint); 107 108 if (insertionPoint.inDocument()) 107 if (insertionPoint.inDocument() && !inDocument()) 109 108 m_styleSheetOwner.removedFromDocument(*this); 110 109 } -
trunk/Source/WebCore/svg/SVGStyleElement.cpp
r207716 r208302 117 117 Node::InsertionNotificationRequest SVGStyleElement::insertedInto(ContainerNode& rootParent) 118 118 { 119 SVGElement::insertedInto(rootParent); 120 if (rootParent.inDocument()) 119 bool wasInDocument = inDocument(); 120 auto result = SVGElement::insertedInto(rootParent); 121 if (rootParent.inDocument() && !wasInDocument) 121 122 m_styleSheetOwner.insertedIntoDocument(*this); 122 return InsertionDone;123 return result; 123 124 } 124 125 … … 126 127 { 127 128 SVGElement::removedFrom(rootParent); 128 if (rootParent.inDocument() )129 if (rootParent.inDocument() && !inDocument()) 129 130 m_styleSheetOwner.removedFromDocument(*this); 130 131 }
Note: See TracChangeset
for help on using the changeset viewer.