Mutating styleSheet in shadow tree doesn't update the style
https://bugs.webkit.org/show_bug.cgi?id=162744
<rdar://problem/28550588>
Reviewed by Ryosuke Niwa.
Source/WebCore:
We weren't always invalidating the right AuthorStyleSheets (to be renamed) instance
for the scope after mutations.
Test: fast/shadow-dom/mutating-stylesheet-in-shadow-tree.html
* css/CSSStyleSheet.cpp:
(WebCore::CSSStyleSheet::didMutateRules):
(WebCore::CSSStyleSheet::didMutate):
(WebCore::CSSStyleSheet::clearOwnerNode):
(WebCore::CSSStyleSheet::rootStyleSheet):
(WebCore::CSSStyleSheet::ownerDocument):
(WebCore::CSSStyleSheet::styleSheetScope):
Invalidate the right scope after stylesheet mutations.
* css/CSSStyleSheet.h:
* dom/AuthorStyleSheets.cpp:
(WebCore::AuthorStyleSheets::styleResolver):
(WebCore::AuthorStyleSheets::styleResolverIfExists):
Take care to update the right style resolver.
(WebCore::AuthorStyleSheets::forNode):
(WebCore::AuthorStyleSheets::removeStyleSheetCandidateNode):
Start the update timer so clients don't need to request update separately.
(WebCore::AuthorStyleSheets::analyzeStyleSheetChange):
(WebCore::AuthorStyleSheets::updateActiveStyleSheets):
(WebCore::AuthorStyleSheets::updateStyleResolver):
* dom/AuthorStyleSheets.h:
* dom/InlineStyleSheetOwner.cpp:
(WebCore::InlineStyleSheetOwner::insertedIntoDocument):
Save the scope we were inserted into so removals can be done reliably.
(WebCore::InlineStyleSheetOwner::removedFromDocument):
Use and clear the saved scope.
Remove didChangeCandidatesForActiveSet() as it is now done by removeStyleSheetCandidateNode() call.
(WebCore::InlineStyleSheetOwner::clearDocumentData):
(WebCore::InlineStyleSheetOwner::createSheet):
(WebCore::InlineStyleSheetOwner::sheetLoaded):
(WebCore::InlineStyleSheetOwner::startLoadingDynamicSheet):
(WebCore::authorStyleSheetsForElement): Deleted.
* dom/InlineStyleSheetOwner.h:
(WebCore::InlineStyleSheetOwner::styleSheetScope):
* dom/ShadowRoot.cpp:
(WebCore::ShadowRoot::styleResolverIfExists):
* dom/ShadowRoot.h:
* html/HTMLLinkElement.cpp:
(WebCore::HTMLLinkElement::removedFrom):
Remove didChangeCandidatesForActiveSet() as it is now done by removeStyleSheetCandidateNode() call.
* html/HTMLStyleElement.cpp:
(WebCore::HTMLStyleElement::~HTMLStyleElement):
(WebCore::HTMLStyleElement::parseAttribute):
Fix a bug where we wouldn't create stylesheet if a style element was activated by removing a media attribute.
(WebCore::HTMLStyleElement::insertedInto):
(WebCore::HTMLStyleElement::removedFrom):
* page/DOMWindow.cpp:
(WebCore::DOMWindow::getMatchedCSSRules):
* svg/SVGStyleElement.cpp:
(WebCore::SVGStyleElement::~SVGStyleElement):
(WebCore::SVGStyleElement::insertedInto):
(WebCore::SVGStyleElement::removedFrom):
LayoutTests:
* fast/shadow-dom/mutating-stylesheet-in-shadow-tree-expected.html: Added.
* fast/shadow-dom/mutating-stylesheet-in-shadow-tree.html: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@206880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/dom/AuthorStyleSheets.cpp b/Source/WebCore/dom/AuthorStyleSheets.cpp
index cbd0bed..8743b6f 100644
--- a/Source/WebCore/dom/AuthorStyleSheets.cpp
+++ b/Source/WebCore/dom/AuthorStyleSheets.cpp
@@ -69,6 +69,31 @@
{
}
+StyleResolver& AuthorStyleSheets::styleResolver()
+{
+ if (m_shadowRoot)
+ return m_shadowRoot->styleResolver();
+
+ return m_document.ensureStyleResolver();
+}
+
+StyleResolver* AuthorStyleSheets::styleResolverIfExists()
+{
+ if (m_shadowRoot)
+ return m_shadowRoot->styleResolverIfExists();
+
+ return m_document.styleResolverIfExists();
+}
+
+AuthorStyleSheets& AuthorStyleSheets::forNode(Node& node)
+{
+ ASSERT(node.inDocument());
+ auto* shadowRoot = node.containingShadowRoot();
+ if (shadowRoot)
+ return shadowRoot->authorStyleSheets();
+ return node.document().authorStyleSheets();
+}
+
// This method is called whenever a top-level stylesheet has finished loading.
void AuthorStyleSheets::removePendingSheet(RemovePendingSheetNotificationType notification)
{
@@ -133,7 +158,8 @@
void AuthorStyleSheets::removeStyleSheetCandidateNode(Node& node)
{
- m_styleSheetCandidateNodes.remove(&node);
+ if (m_styleSheetCandidateNodes.remove(&node))
+ scheduleActiveSetUpdate();
}
void AuthorStyleSheets::collectActiveStyleSheets(Vector<RefPtr<StyleSheet>>& sheets)
@@ -220,10 +246,10 @@
unsigned newStylesheetCount = newStylesheets.size();
- if (!m_document.styleResolverIfExists())
+ if (!styleResolverIfExists())
return Reconstruct;
- StyleResolver& styleResolver = *m_document.styleResolverIfExists();
+ StyleResolver& styleResolver = *styleResolverIfExists();
// Find out which stylesheets are new.
unsigned oldStylesheetCount = m_activeStyleSheets.size();
@@ -306,6 +332,10 @@
return;
}
+ // FIXME: Support optimized invalidation in shadow trees.
+ if (m_shadowRoot)
+ updateType = UpdateType::ContentsOrInterpretation;
+
m_didUpdateActiveStyleSheets = true;
Vector<RefPtr<StyleSheet>> activeStyleSheets;
@@ -352,8 +382,7 @@
m_document.clearStyleResolver();
return;
}
- auto& styleResolver = m_document.ensureStyleResolver();
- auto& userAgentShadowTreeStyleResolver = m_document.userAgentShadowTreeStyleResolver();
+ auto& styleResolver = this->styleResolver();
if (updateType == Reset) {
styleResolver.ruleSets().resetAuthorStyle();
@@ -366,10 +395,13 @@
styleResolver.appendAuthorStyleSheets(newStyleSheets);
}
- userAgentShadowTreeStyleResolver.ruleSets().resetAuthorStyle();
- auto& authorRuleSet = styleResolver.ruleSets().authorStyle();
- if (authorRuleSet.hasShadowPseudoElementRules())
- userAgentShadowTreeStyleResolver.ruleSets().authorStyle().copyShadowPseudoElementRulesFrom(authorRuleSet);
+ if (!m_shadowRoot) {
+ auto& userAgentShadowTreeStyleResolver = m_document.userAgentShadowTreeStyleResolver();
+ userAgentShadowTreeStyleResolver.ruleSets().resetAuthorStyle();
+ auto& authorRuleSet = styleResolver.ruleSets().authorStyle();
+ if (authorRuleSet.hasShadowPseudoElementRules())
+ userAgentShadowTreeStyleResolver.ruleSets().authorStyle().copyShadowPseudoElementRulesFrom(authorRuleSet);
+ }
}
const Vector<RefPtr<CSSStyleSheet>> AuthorStyleSheets::activeStyleSheetsForInspector() const
@@ -422,6 +454,11 @@
void AuthorStyleSheets::scheduleActiveSetUpdate()
{
+ if (m_shadowRoot) {
+ // FIXME: We need to flush updates recursively to support asynchronous updates in shadow trees.
+ didChangeCandidatesForActiveSet();
+ return;
+ }
if (m_pendingUpdateTimer.isActive())
return;
if (!m_pendingUpdateType)