Changeset 216761 in webkit


Ignore:
Timestamp:
May 12, 2017 5:31:49 AM (7 years ago)
Author:
Antti Koivisto
Message:

Updating class name of a shadow host does not update the style applied by descendants of :host()
https://bugs.webkit.org/show_bug.cgi?id=170762
<rdar://problem/31572668>

Reviewed by Ryosuke Niwa.

Source/WebCore:

We need to invalidate shadow tree style when host classes or attributes change if it may be
affected by host rules.

Test: fast/shadow-dom/css-scoping-host-class-and-attribute-mutation.html

  • css/RuleSet.cpp:

(WebCore::isHostSelectorMatchingInShadowTree):
(WebCore::RuleSet::addRule):

Check if we have :host selectors that affect shadow tree.

  • css/RuleSet.h:

(WebCore::RuleSet::hasHostPseudoClassRulesMatchingInShadowTree):

  • style/AttributeChangeInvalidation.cpp:

(WebCore::Style::mayBeAffectedByHostRules):
(WebCore::Style::AttributeChangeInvalidation::invalidateStyle):

Invalidate the whole subtree if there is a class change that may affect shadow tree style.

  • style/ClassChangeInvalidation.cpp:

(WebCore::Style::mayBeAffectedByHostRules):
(WebCore::Style::ClassChangeInvalidation::invalidateStyle):

  • style/IdChangeInvalidation.cpp:

(WebCore::Style::mayBeAffectedByHostRules):
(WebCore::Style::IdChangeInvalidation::invalidateStyle):

Same for classes and ids.
This should be refactored at some point to reduce copy-code.

LayoutTests:

  • fast/shadow-dom/css-scoping-host-class-and-attribute-mutation-expected.html: Added.
  • fast/shadow-dom/css-scoping-host-class-and-attribute-mutation.html: Added.
Location:
trunk
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r216760 r216761  
     12017-05-12  Antti Koivisto  <antti@apple.com>
     2
     3        Updating class name of a shadow host does not update the style applied by descendants of :host()
     4        https://bugs.webkit.org/show_bug.cgi?id=170762
     5        <rdar://problem/31572668>
     6
     7        Reviewed by Ryosuke Niwa.
     8
     9        * fast/shadow-dom/css-scoping-host-class-and-attribute-mutation-expected.html: Added.
     10        * fast/shadow-dom/css-scoping-host-class-and-attribute-mutation.html: Added.
     11
    1122017-05-12  Claudio Saavedra  <csaavedra@igalia.com>
    213
  • trunk/Source/WebCore/ChangeLog

    r216759 r216761  
     12017-05-12  Antti Koivisto  <antti@apple.com>
     2
     3        Updating class name of a shadow host does not update the style applied by descendants of :host()
     4        https://bugs.webkit.org/show_bug.cgi?id=170762
     5        <rdar://problem/31572668>
     6
     7        Reviewed by Ryosuke Niwa.
     8
     9        We need to invalidate shadow tree style when host classes or attributes change if it may be
     10        affected by host rules.
     11
     12        Test: fast/shadow-dom/css-scoping-host-class-and-attribute-mutation.html
     13
     14        * css/RuleSet.cpp:
     15        (WebCore::isHostSelectorMatchingInShadowTree):
     16        (WebCore::RuleSet::addRule):
     17
     18            Check if we have :host selectors that affect shadow tree.
     19
     20        * css/RuleSet.h:
     21        (WebCore::RuleSet::hasHostPseudoClassRulesMatchingInShadowTree):
     22        * style/AttributeChangeInvalidation.cpp:
     23        (WebCore::Style::mayBeAffectedByHostRules):
     24        (WebCore::Style::AttributeChangeInvalidation::invalidateStyle):
     25
     26            Invalidate the whole subtree if there is a class change that may affect shadow tree style.
     27
     28        * style/ClassChangeInvalidation.cpp:
     29        (WebCore::Style::mayBeAffectedByHostRules):
     30        (WebCore::Style::ClassChangeInvalidation::invalidateStyle):
     31        * style/IdChangeInvalidation.cpp:
     32        (WebCore::Style::mayBeAffectedByHostRules):
     33        (WebCore::Style::IdChangeInvalidation::invalidateStyle):
     34
     35            Same for classes and ids.
     36            This should be refactored at some point to reduce copy-code.
     37
    1382017-05-12  Carlos Garcia Campos  <cgarcia@igalia.com>
    239
  • trunk/Source/WebCore/css/RuleSet.cpp

    r214255 r216761  
    195195}
    196196
     197static bool isHostSelectorMatchingInShadowTree(const CSSSelector& startSelector)
     198{
     199    auto* leftmostSelector = &startSelector;
     200    bool hasDescendantOrChildRelation = false;
     201    while (auto* previous = leftmostSelector->tagHistory()) {
     202        hasDescendantOrChildRelation = leftmostSelector->hasDescendantOrChildRelation();
     203        leftmostSelector = previous;
     204    }
     205    if (!hasDescendantOrChildRelation)
     206        return false;
     207
     208    return leftmostSelector->match() == CSSSelector::PseudoClass && leftmostSelector->pseudoClassType() == CSSSelector::PseudoClassHost;
     209}
     210
    197211void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, AddRuleFlags addRuleFlags)
    198212{
     
    309323        return;
    310324    }
     325
     326    if (!m_hasHostPseudoClassRulesMatchingInShadowTree)
     327        m_hasHostPseudoClassRulesMatchingInShadowTree = isHostSelectorMatchingInShadowTree(*ruleData.selector());
    311328
    312329    if (hostPseudoClassSelector) {
  • trunk/Source/WebCore/css/RuleSet.h

    r214255 r216761  
    193193
    194194    bool hasShadowPseudoElementRules() const;
     195    bool hasHostPseudoClassRulesMatchingInShadowTree() const { return m_hasHostPseudoClassRulesMatchingInShadowTree; }
    195196
    196197private:
     
    212213    Vector<StyleRulePage*> m_pageRules;
    213214    unsigned m_ruleCount { 0 };
     215    bool m_hasHostPseudoClassRulesMatchingInShadowTree { false };
    214216    bool m_autoShrinkToFitEnabled { true };
    215217    RuleFeatureSet m_features;
  • trunk/Source/WebCore/style/AttributeChangeInvalidation.cpp

    r216117 r216761  
    4343}
    4444
    45 static bool mayBeAffectedByHostRules(const Element& element, const QualifiedName& attributeName)
     45static bool mayBeAffectedByHostRules(const Element& element, const QualifiedName& attributeName, bool& mayAffectShadowTree)
    4646{
     47    // FIXME: More of this code should be shared between Class/Attribute/IdInvalidation.
    4748    auto* shadowRoot = element.shadowRoot();
    4849    if (!shadowRoot)
    4950        return false;
    5051    auto& shadowRuleSets = shadowRoot->styleScope().resolver().ruleSets();
    51     if (shadowRuleSets.authorStyle().hostPseudoClassRules().isEmpty())
     52    auto& authorStyle = shadowRuleSets.authorStyle();
     53    if (authorStyle.hostPseudoClassRules().isEmpty() && !authorStyle.hasHostPseudoClassRulesMatchingInShadowTree())
    5254        return false;
    5355
    54     return mayBeAffectedByAttributeChange(shadowRuleSets, element.isHTMLElement(), attributeName);
     56    if (!mayBeAffectedByAttributeChange(shadowRuleSets, element.isHTMLElement(), attributeName))
     57        return false;
     58
     59    if (authorStyle.hasHostPseudoClassRulesMatchingInShadowTree())
     60        mayAffectShadowTree = true;
     61    return true;
    5562}
    5663
     
    7481    auto& ruleSets = m_element.styleResolver().ruleSets();
    7582    bool isHTML = m_element.isHTMLElement();
     83    bool mayAffectShadowTree = false;
    7684
    7785    bool mayAffectStyle = mayBeAffectedByAttributeChange(ruleSets, isHTML, attributeName)
    78         || mayBeAffectedByHostRules(m_element, attributeName)
     86        || mayBeAffectedByHostRules(m_element, attributeName, mayAffectShadowTree)
    7987        || mayBeAffectedBySlottedRules(m_element, attributeName);
    8088
     
    8795    }
    8896
    89     if (m_element.shadowRoot() && ruleSets.authorStyle().hasShadowPseudoElementRules()) {
     97    if (m_element.shadowRoot() && ruleSets.authorStyle().hasShadowPseudoElementRules())
     98        mayAffectShadowTree = true;
     99
     100    if (mayAffectShadowTree) {
    90101        m_element.invalidateStyleForSubtree();
    91102        return;
  • trunk/Source/WebCore/style/ClassChangeInvalidation.cpp

    r216117 r216761  
    8787}
    8888
    89 static bool mayBeAffectedByHostRules(ShadowRoot* shadowRoot, AtomicStringImpl* changedClass)
     89static bool mayBeAffectedByHostRules(ShadowRoot* shadowRoot, AtomicStringImpl* changedClass, bool& mayAffectShadowTree)
    9090{
     91    // FIXME: More of this code should be shared between Class/Attribute/IdInvalidation.
    9192    if (!shadowRoot)
    9293        return false;
    9394    auto& shadowRuleSets = shadowRoot->styleScope().resolver().ruleSets();
    94     if (shadowRuleSets.authorStyle().hostPseudoClassRules().isEmpty())
     95    auto& authorStyle = shadowRuleSets.authorStyle();
     96    if (authorStyle.hostPseudoClassRules().isEmpty() && !authorStyle.hasHostPseudoClassRulesMatchingInShadowTree())
    9597        return false;
    96     return shadowRuleSets.features().classesInRules.contains(changedClass);
     98
     99    if (!shadowRuleSets.features().classesInRules.contains(changedClass))
     100        return false;
     101
     102    if (authorStyle.hasHostPseudoClassRulesMatchingInShadowTree())
     103        mayAffectShadowTree = true;
     104    return true;
    97105}
    98106
     
    112120{
    113121    auto changedClasses = computeClassChange(oldClasses, newClasses);
     122    bool mayAffectShadowTree = false;
    114123
    115124    auto& ruleSets = m_element.styleResolver().ruleSets();
     
    120129    for (auto* changedClass : changedClasses) {
    121130        bool mayAffectStyle = ruleSets.features().classesInRules.contains(changedClass)
    122             || mayBeAffectedByHostRules(shadowRoot, changedClass)
     131            || mayBeAffectedByHostRules(shadowRoot, changedClass, mayAffectShadowTree)
    123132            || mayBeAffectedBySlottedRules(assignedShadowRoots, changedClass);
    124133        if (mayAffectStyle)
     
    129138        return;
    130139
    131     if (shadowRoot && ruleSets.authorStyle().hasShadowPseudoElementRules()) {
     140    if (shadowRoot && ruleSets.authorStyle().hasShadowPseudoElementRules())
     141        mayAffectShadowTree = true;
     142
     143    if (mayAffectShadowTree) {
     144        // FIXME: We should do fine-grained invalidation for shadow tree.
    132145        m_element.invalidateStyleForSubtree();
    133146        return;
  • trunk/Source/WebCore/style/IdChangeInvalidation.cpp

    r214255 r216761  
    3636namespace Style {
    3737
    38 static bool mayBeAffectedByHostRules(const Element& element, const AtomicString& changedId)
     38static bool mayBeAffectedByHostRules(const Element& element, const AtomicString& changedId, bool& mayAffectShadowTree)
    3939{
    4040    auto* shadowRoot = element.shadowRoot();
     
    4242        return false;
    4343    auto& shadowRuleSets = shadowRoot->styleScope().resolver().ruleSets();
    44     if (shadowRuleSets.authorStyle().hostPseudoClassRules().isEmpty())
     44    auto& authorStyle = shadowRuleSets.authorStyle();
     45    if (authorStyle.hostPseudoClassRules().isEmpty() && !authorStyle.hasHostPseudoClassRulesMatchingInShadowTree())
    4546        return false;
    46     return shadowRuleSets.features().idsInRules.contains(changedId);
     47
     48    if (!shadowRuleSets.features().idsInRules.contains(changedId))
     49        return false;
     50
     51    if (authorStyle.hasHostPseudoClassRulesMatchingInShadowTree())
     52        mayAffectShadowTree = true;
     53    return true;
    4754}
    4855
     
    6572
    6673    auto& ruleSets = m_element.styleResolver().ruleSets();
     74    bool mayAffectShadowTree = false;
    6775
    6876    bool mayAffectStyle = ruleSets.features().idsInRules.contains(changedId)
    69         || mayBeAffectedByHostRules(m_element, changedId)
     77        || mayBeAffectedByHostRules(m_element, changedId, mayAffectShadowTree)
    7078        || mayBeAffectedBySlottedRules(m_element, changedId);
    7179
     
    7381        return;
    7482
    75     if (m_element.shadowRoot() && ruleSets.authorStyle().hasShadowPseudoElementRules()) {
     83    if (m_element.shadowRoot() && ruleSets.authorStyle().hasShadowPseudoElementRules())
     84        mayAffectShadowTree = true;
     85
     86    if (mayAffectShadowTree) {
    7687        m_element.invalidateStyleForSubtree();
    7788        return;
Note: See TracChangeset for help on using the changeset viewer.